bool move_is_legal(int move, const board_t * board) { bool legal; ASSERT(move_is_ok(move)); ASSERT(board_is_ok(board)); legal = move_is_pseudo(move,board) && pseudo_is_legal(move,board); ASSERT(legal==move_is_legal_debug(move,board)); return legal; }
bool pseudo_is_legal(int move, const board_t * board) { board_t new_board[1]; ASSERT(move_is_ok(move)); ASSERT(board_is_ok(board)); ASSERT(move_is_pseudo(move,board)); board_copy(new_board,board); move_do(new_board,move); return !is_in_check(new_board,colour_opp(new_board->turn)); }
bool quiet_is_pseudo( int move, board_t *board ) { int to; ASSERT(move_is_ok(move)); ASSERT(board != NULL); ASSERT(!board_is_check(board)); to = MOVE_TO(move); ASSERT(SQUARE_IS_OK(to)); if( board->square[to] != Empty ) return false; // capture return move_is_pseudo(move, board ); }
void move_do(board_t * board, int move) { int me, opp; int from, to; int piece, pos, capture; int old_flags, new_flags; int sq, ep_square; int pawn; ASSERT(board_is_ok(board)); ASSERT(move_is_ok(move)); ASSERT(move_is_pseudo(move,board)); // init me = board->turn; opp = colour_opp(me); from = move_from(move); to = move_to(move); piece = board->square[from]; ASSERT(colour_equal(piece,me)); pos = board->pos[from]; ASSERT(pos>=0); // update turn board->turn = opp; board->key ^= random_64(RandomTurn); // update castling rights old_flags = board_flags(board); if (piece_is_king(piece)) { board->castle[me][SideH] = SquareNone; board->castle[me][SideA] = SquareNone; } if (board->castle[me][SideH] == from) board->castle[me][SideH] = SquareNone; if (board->castle[me][SideA] == from) board->castle[me][SideA] = SquareNone; if (board->castle[opp][SideH] == to) board->castle[opp][SideH] = SquareNone; if (board->castle[opp][SideA] == to) board->castle[opp][SideA] = SquareNone; new_flags = board_flags(board); board->key ^= hash_castle_key(new_flags^old_flags); // HACK // update en-passant square ep_square = sq = board->ep_square; if (sq != SquareNone) { board->key ^= random_64(RandomEnPassant+square_file(sq)); board->ep_square = SquareNone; } if (piece_is_pawn(piece) && abs(to-from) == 32) { pawn = piece_make_pawn(opp); if (board->square[to-1] == pawn || board->square[to+1] == pawn) { board->ep_square = sq = (from + to) / 2; board->key ^= random_64(RandomEnPassant+square_file(sq)); } } // update ply number (captures are handled later) board->ply_nb++; if (piece_is_pawn(piece)) board->ply_nb = 0; // conversion // update move number if (me == Black) board->move_nb++; // castle if (colour_equal(board->square[to],me)) { int rank; int king_from, king_to; int rook_from, rook_to; int rook; rank = colour_is_white(me) ? Rank1 : Rank8; king_from = from; rook_from = to; if (to > from) { // h side king_to = square_make(FileG,rank); rook_to = square_make(FileF,rank); } else { // a side king_to = square_make(FileC,rank); rook_to = square_make(FileD,rank); } // remove the rook pos = board->pos[rook_from]; ASSERT(pos>=0); rook = Rook64 | me; // HACK square_clear(board,rook_from,rook); // move the king square_move(board,king_from,king_to,piece); // put the rook back square_set(board,rook_to,rook,pos); ASSERT(board->key==hash_key(board)); return; } // remove the captured piece if (piece_is_pawn(piece) && to == ep_square) { // en-passant capture sq = square_ep_dual(to); capture = board->square[sq]; ASSERT(capture==piece_make_pawn(opp)); square_clear(board,sq,capture); board->ply_nb = 0; // conversion } else { capture = board->square[to]; if (capture != Empty) { // normal capture ASSERT(colour_equal(capture,opp)); ASSERT(!piece_is_king(capture)); square_clear(board,to,capture); board->ply_nb = 0; // conversion } } // move the piece if (move_is_promote(move)) { // promote square_clear(board,from,piece); piece = move_promote_hack(move) | me; // HACK square_set(board,to,piece,pos); } else { // normal move square_move(board,from,to,piece); } ASSERT(board->key==hash_key(board)); }
int sort_next(sort_t * sort, int ThreadId) { int move; int gen; ASSERT(sort!=NULL); while (true) { while (sort->pos < LIST_SIZE(sort->list)) { // next move move = LIST_MOVE(sort->list,sort->pos); sort->value = HistoryMax; // default score, HistoryMax instead of 16384 sort->pos++; ASSERT(move!=MoveNone); // test if (false) { } else if (sort->test == TEST_NONE) { // no-op } else if (sort->test == TEST_TRANS_KILLER) { if (!move_is_pseudo(move,sort->board)) continue; if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_GOOD_CAPTURE) { ASSERT(move_is_tactical(move,sort->board)); if (move == sort->trans_killer) continue; if (!capture_is_good(move,sort->board,sort->in_pv)) { LIST_ADD(sort->bad,move); continue; } if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_BAD_CAPTURE) { ASSERT(move_is_tactical(move,sort->board)); ASSERT(!capture_is_good(move,sort->board,sort->in_pv)); ASSERT(move!=sort->trans_killer); if (!pseudo_is_legal(move,sort->board)) continue; sort->value = HistoryBadCap; // WHM(31) } else if (sort->test == TEST_KILLER) { if (move == sort->trans_killer) continue; if (!quiet_is_pseudo(move,sort->board)) continue; if (!pseudo_is_legal(move,sort->board)) continue; ASSERT(!move_is_tactical(move,sort->board)); sort->value = HistoryKiller; // WHM(31) } else if (sort->test == TEST_QUIET) { ASSERT(!move_is_tactical(move,sort->board)); if (move == sort->trans_killer) continue; if (move == sort->killer_1) continue; if (move == sort->killer_2) continue; if (move == sort->killer_3) continue; if (move == sort->killer_4) continue; if (!pseudo_is_legal(move,sort->board)) continue; sort->value = history_prob(move,sort->board,ThreadId); } else { ASSERT(false); return MoveNone; } ASSERT(pseudo_is_legal(move,sort->board)); return move; } // next stage gen = Code[sort->gen++]; if (false) { } else if (gen == GEN_TRANS) { LIST_CLEAR(sort->list); if (sort->trans_killer != MoveNone) LIST_ADD(sort->list,sort->trans_killer); sort->test = TEST_TRANS_KILLER; } else if (gen == GEN_GOOD_CAPTURE) { gen_captures(sort->list,sort->board); note_mvv_lva(sort->list,sort->board); list_sort(sort->list); LIST_CLEAR(sort->bad); sort->test = TEST_GOOD_CAPTURE; } else if (gen == GEN_BAD_CAPTURE) { list_copy(sort->list,sort->bad); sort->test = TEST_BAD_CAPTURE; } else if (gen == GEN_KILLER) { LIST_CLEAR(sort->list); if (sort->killer_1 != MoveNone) LIST_ADD(sort->list,sort->killer_1); if (sort->killer_2 != MoveNone) LIST_ADD(sort->list,sort->killer_2); if (sort->killer_3 != MoveNone) LIST_ADD(sort->list,sort->killer_3); if (sort->killer_4 != MoveNone) LIST_ADD(sort->list,sort->killer_4); sort->test = TEST_KILLER; } else if (gen == GEN_QUIET) { gen_quiet_moves(sort->list,sort->board); note_quiet_moves(sort->list,sort->board,sort->in_pv,ThreadId); list_sort(sort->list); sort->test = TEST_QUIET; } else { ASSERT(gen==GEN_END); return MoveNone; } sort->pos = 0; } }
int sort_next_qs(sort_t * sort) { int move; int gen; ASSERT(sort!=NULL); while (true) { while (sort->pos < LIST_SIZE(sort->list)) { // next move move = LIST_MOVE(sort->list,sort->pos); sort->pos++; ASSERT(move!=MoveNone); // test if (false) { } else if (sort->test == TEST_LEGAL) { if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_TRANS_KILLER) { if (!move_is_pseudo(move,sort->board)) continue; if (!pseudo_is_legal(move,sort->board)) continue; // check if (!MOVE_IS_TACTICAL(move,sort->board) && (!move_is_check(move,sort->board) || sort->depth < 0)) continue; } else if (sort->test == TEST_CAPTURE_QS) { ASSERT(MOVE_IS_TACTICAL(move,sort->board)); ASSERT(sort->value==NodePV||sort->value==NodeCut||sort->value==NodeAll); if (move == sort->trans_killer) continue; if (sort->value != NodePV && !capture_is_good(move,sort->board)) continue; if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_CHECK_QS) { ASSERT(!MOVE_IS_TACTICAL(move,sort->board)); ASSERT(move_is_check(move,sort->board)); if (move == sort->trans_killer) continue; if (see_move(move,sort->board,0) < 0) continue; if (!pseudo_is_legal(move,sort->board)) continue; } else { ASSERT(false); return MoveNone; } ASSERT(pseudo_is_legal(move,sort->board)); return move; } // next stage gen = Code[sort->gen++]; if (false) { } else if (gen == GEN_EVASION_QS) { gen_pseudo_evasions(sort->list,sort->board,sort->attack); note_moves_simple(sort->list,sort->board,sort->trans_killer); list_sort(sort->list); sort->test = TEST_LEGAL; } else if (gen == GEN_TRANS) { LIST_CLEAR(sort->list); if (sort->trans_killer != MoveNone) LIST_ADD(sort->list,sort->trans_killer); sort->test = TEST_TRANS_KILLER; } else if (gen == GEN_CAPTURE_QS) { gen_captures(sort->list,sort->board); note_mvv_lva(sort->list,sort->board); list_sort(sort->list); sort->test = TEST_CAPTURE_QS; } else if (gen == GEN_CHECK_QS) { gen_quiet_checks(sort->list,sort->board); sort->test = TEST_CHECK_QS; } else { ASSERT(gen==GEN_END); return MoveNone; } sort->pos = 0; } }
int sort_next(sort_t * sort) { int move; int gen; ASSERT(sort!=NULL); while (true) { while (sort->pos < LIST_SIZE(sort->list)) { // next move move = LIST_MOVE(sort->list,sort->pos); sort->value = 65536; // default score sort->pos++; ASSERT(move!=MoveNone); // test if (false) { } else if (sort->test == TEST_NONE) { // Evasion (no-op) } else if (sort->test == TEST_TRANS_KILLER) { if (!move_is_pseudo(move,sort->board)) continue; if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_CAPTURE) { ASSERT(MOVE_IS_TACTICAL(move,sort->board)); if (move == sort->trans_killer) continue; if (!capture_is_good(move,sort->board)) { LIST_ADD(sort->bad,move); continue; } if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_KILLER) { if (move == sort->trans_killer) continue; if (!quiet_is_pseudo(move,sort->board)) continue; if (!pseudo_is_legal(move,sort->board)) continue; ASSERT(!MOVE_IS_TACTICAL(move,sort->board)); sort->value = 32768; } else if (sort->test == TEST_QUIET) { ASSERT(!MOVE_IS_TACTICAL(move,sort->board)); if (move == sort->trans_killer) continue; if (move == sort->killer_1) continue; if (move == sort->killer_2) continue; if (!pseudo_is_legal(move,sort->board)) continue; sort->value = history_prob(move,sort->board); } else if (sort->test == TEST_BAD) { ASSERT(MOVE_IS_TACTICAL(move,sort->board)); ASSERT(!capture_is_good(move,sort->board)); ASSERT(move!=sort->trans_killer); if (!pseudo_is_legal(move,sort->board)) continue; } else { ASSERT(false); return MoveNone; } ASSERT(pseudo_is_legal(move,sort->board)); return move; } // next stage gen = Code[sort->gen++]; if (false) { } else if (gen == GEN_TRANS) { LIST_CLEAR(sort->list); if (sort->trans_killer != MoveNone) LIST_ADD(sort->list,sort->trans_killer); sort->test = TEST_TRANS_KILLER; } else if (gen == GEN_CAPTURE) { gen_captures(sort->list,sort->board); note_mvv_lva(sort->list,sort->board); list_sort(sort->list); LIST_CLEAR(sort->bad); sort->test = TEST_CAPTURE; } else if (gen == GEN_KILLER) { LIST_CLEAR(sort->list); if (sort->killer_1 != MoveNone) LIST_ADD(sort->list,sort->killer_1); if (sort->killer_2 != MoveNone) LIST_ADD(sort->list,sort->killer_2); sort->test = TEST_KILLER; } else if (gen == GEN_QUIET) { gen_quiet_moves(sort->list,sort->board); note_quiet_moves(sort->list,sort->board); list_sort(sort->list); sort->test = TEST_QUIET; } else if (gen == GEN_BAD) { list_copy(sort->list,sort->bad); sort->test = TEST_BAD; } else { ASSERT(gen==GEN_END); return MoveNone; } sort->pos = 0; } }