int see_square(const board_t * board, int to, int colour) { int att, def; alists_t alists[1]; alist_t * alist; int piece_value; int piece; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(to)); ASSERT(COLOUR_IS_OK(colour)); ASSERT(COLOUR_IS(board->square[to],COLOUR_OPP(colour))); // build attacker list att = colour; alist = alists->alist[att]; ALIST_CLEAR(alist); alist_build(alist,board,to,att); if (alist->size == 0) return 0; // no attacker => stop SEE // build defender list def = COLOUR_OPP(att); alist = alists->alist[def]; ALIST_CLEAR(alist); alist_build(alist,board,to,def); // captured piece piece = board->square[to]; ASSERT(piece_is_ok(piece)); ASSERT(COLOUR_IS(piece,def)); piece_value = VALUE_PIECE(piece); // SEE search return see_rec(alists,board,att,to,piece_value); }
static int see_rec(alists_t * alists, const board_t * board, int colour, int to, int piece_value) { int from, piece; int value; ASSERT(alists!=NULL); ASSERT(board!=NULL); ASSERT(COLOUR_IS_OK(colour)); ASSERT(SQUARE_IS_OK(to)); ASSERT(piece_value>0); // find the least valuable attacker from = alist_pop(alists->alist[colour],board); if (from == SquareNone) return 0; // no more attackers // find hidden attackers alists_hidden(alists,board,from,to); // calculate the capture value value = +piece_value; // captured piece if (value == ValueKing) return value; // do not allow an answer to a king capture piece = board->square[from]; ASSERT(piece_is_ok(piece)); ASSERT(COLOUR_IS(piece,colour)); piece_value = VALUE_PIECE(piece); // promote if (piece_value == ValuePawn && SQUARE_IS_PROMOTE(to)) { // HACK: PIECE_IS_PAWN(piece) ASSERT(PIECE_IS_PAWN(piece)); piece_value = ValueQueen; value += ValueQueen - ValuePawn; } value -= see_rec(alists,board,COLOUR_OPP(colour),to,piece_value); if (value < 0) value = 0; return value; }
int see_move(int move, const board_t * board) { int att, def; int from, to; alists_t alists[1]; int value, piece_value; int piece, capture; alist_t * alist; int pos; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); // init from = MOVE_FROM(move); to = MOVE_TO(move); // move the piece piece_value = 0; piece = board->square[from]; ASSERT(piece_is_ok(piece)); att = PIECE_COLOUR(piece); def = COLOUR_OPP(att); // promote if (MOVE_IS_PROMOTE(move)) { ASSERT(PIECE_IS_PAWN(piece)); piece = move_promote(move); ASSERT(piece_is_ok(piece)); ASSERT(COLOUR_IS(piece,att)); } piece_value += VALUE_PIECE(piece); // clear attacker lists ALIST_CLEAR(alists->alist[Black]); ALIST_CLEAR(alists->alist[White]); // find hidden attackers alists_hidden(alists,board,from,to); // capture the piece value = 0; capture = board->square[to]; if (capture != Empty) { ASSERT(piece_is_ok(capture)); ASSERT(COLOUR_IS(capture,def)); value += VALUE_PIECE(capture); } // promote if (MOVE_IS_PROMOTE(move)) { value += VALUE_PIECE(piece) - ValuePawn; } // en-passant if (MOVE_IS_EN_PASSANT(move)) { ASSERT(value==0); ASSERT(PIECE_IS_PAWN(board->square[SQUARE_EP_DUAL(to)])); value += ValuePawn; alists_hidden(alists,board,SQUARE_EP_DUAL(to),to); } // build defender list alist = alists->alist[def]; alist_build(alist,board,to,def); if (alist->size == 0) return value; // no defender => stop SEE // build attacker list alist = alists->alist[att]; alist_build(alist,board,to,att); // remove the moved piece (if it's an attacker) for (pos = 0; pos < alist->size && alist->square[pos] != from; pos++) ; if (pos < alist->size) alist_remove(alist,pos); // SEE search value -= see_rec(alists,board,def,to,piece_value); return value; }
/* ファイルのロード */ EXPORT ERR load_file(TC *filename) { W err, i, fd; LINK l, v; F_LINK stat; F_STATE fs; /* アンロード処理 */ if (filename == NULL) { err = ER_OK; fd = ER_NOEXS; goto fin3; } /* 入力ファイルへのリンク取り出し */ err = get_lnk(filename, &l, F_NORM); if (err < ER_OK) { P(("load_file: get_lnk %d\n", err)); goto fin0; } /* 入力ファイルのオープン - 現在レコードはファイルの先頭 */ err = opn_fil(&l, F_READ | F_EXCL, NULL); if (err < ER_OK) { P(("load_file: opn_fil %d\n", err)); goto fin0; } fd = err; /* リンク数の獲得 */ err = ofl_sts(fd, NULL, &fs, NULL); if (err < ER_OK) { P(("load_file: ofl_sts %d\n", err)); goto fin1; } /* 仮身名用領域の確保 */ OBJentry = fs.f_nlink; if (OBJentry) { OBJname = calloc(OBJentry, sizeof(FNAME)); if (OBJname == NULL) { P(("load_file: calloc NULL\n")); err = ER_NOMEM; goto fin1; } } else { OBJname = NULL; } /* 全リンクの読み出し */ for (i = 0; i < OBJentry; i++) { err = fnd_lnk(fd, F_FWD, NULL, 0, NULL); if (err < ER_OK) { P(("load_file: fnd_lnk %d\n", err)); goto fin2; } err = rea_rec(fd, 0, (B *)&v, sizeof(VLINK), NULL, NULL); if (err < ER_OK) { P(("load_file: rea_rec %d\n", err)); goto fin2; } /* リンクファイル/リンクレコードに応じて処理 */ err = lnk_sts((LINK *)&v, &stat); if (err >= ER_OK) { memcpy(OBJname[i].tc, stat.f_name, sizeof(stat.f_name)); } else if (err == ER_NOLNK) { err = fil_sts((LINK *)&v, OBJname[i].tc, NULL, NULL); } if (err < ER_OK) { P(("load_file: fil_sts %d\n", err)); P(("load_file: warning, this object is ignored\n")); /* goto fin2; */ } err = see_rec(fd, 1, 0, NULL); if (err < ER_OK) { P(("load_flie: see_rec %d\n", err)); goto fin2; } } /* 主TADレコードへ移動 */ err = fnd_rec(fd, F_ENDTOP, (1 << 1), 0, NULL); if (err < ER_OK) { P(("load_file: fnd_rec %d\n", err)); goto fin2; } /* レコードサイズの取得 */ err = rea_rec(fd, 0, NULL, 0, &TADsize, NULL); if (err < ER_OK) { P(("load_file: rea_rec %d\n", err)); goto fin2; } /* メモリの確保 */ TADdata = malloc(TADsize); if (TADdata == NULL) { P(("load_file: malloc NULL\n")); err = ER_NOMEM; goto fin2; } /* レコード全体の読み込み */ err = rea_rec(fd, 0, (B *)TADdata, TADsize, NULL, NULL); if (err < ER_OK) { P(("load_file: rea_rec %d\n", err)); goto fin3; } DP(("load_file: TADsize %d, OBJentry %d\n", TADsize, OBJentry)); /* ファイルをクローズして終了 */ goto fin1; fin3: if (TADdata != NULL) { free(TADdata); TADdata = NULL; } fin2: if (OBJname != NULL) { free(OBJname); OBJname = NULL; } fin1: if (fd >= 0) cls_fil(fd); fin0: return err; }