/** moves_are_connected(): This function is used for LMR, testing if a reduced move actually contained a threat. The function tests if the move that refuted null move was connected to the first move. This idea is from Tord Romstad. Created 101707; last modified 101807 **/ BOOL moves_are_connected(MOVE move_1, MOVE move_2) { if (move_1 == NULL_MOVE || move_2 == NULL_MOVE) return FALSE; if (MOVE_TO(move_1) == MOVE_FROM(move_2)) return TRUE; if (MOVE_FROM(move_1) == MOVE_TO(move_2)) return TRUE; if (MASK(MOVE_FROM(move_1)) & in_between_bb[MOVE_FROM(move_2)] [MOVE_TO(move_2)]) return TRUE; return FALSE; }
static int history_index(int move, const board_t * board) { int index; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!move_is_tactical(move,board)); index = PIECE_TO_12(board->square[MOVE_FROM(move)]) * 64 + SQUARE_TO_64(MOVE_FROM(move)) * 64 + SQUARE_TO_64(MOVE_TO(move)); ASSERT(index>=0&&index<HistorySize); return index; }
static bool capture_is_good(int move, const board_t * board) { int piece, capture; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(MOVE_IS_TACTICAL(move,board)); // special cases if (MOVE_IS_EN_PASSANT(move)) return true; if (MOVE_IS_UNDER_PROMOTE(move)) return false; // REMOVE ME? // captures and queen promotes capture = board->square[MOVE_TO(move)]; if (capture != Empty) { // capture ASSERT(move_is_capture(move,board)); if (MOVE_IS_PROMOTE(move)) return true; // promote-capture piece = board->square[MOVE_FROM(move)]; if (VALUE_PIECE(capture) >= VALUE_PIECE(piece)) return true; } return see_move(move,board,0) >= 0; }
static int mvv_lva(int move, const board_t * board) { int piece, capture, promote; int value; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(move_is_tactical(move,board)); if (MOVE_IS_EN_PASSANT(move)) { // en-passant capture value = 5; // PxP } else if ((capture = board->square[MOVE_TO(move)]) != Empty) { // normal capture piece = board->square[MOVE_FROM(move)]; value = PIECE_ORDER(capture) * 6 - PIECE_ORDER(piece) + 5; ASSERT(value>=0&&value<30); } else { // promote ASSERT(MOVE_IS_PROMOTE(move)); promote = move_promote(move); value = PIECE_ORDER(promote) - 5; ASSERT(value>=-4&&value<0); } ASSERT(value>=-4&&value<+30); return value; }
void str_CSA_move( char *str, unsigned int move ) { int type_c = MOVE_TYPE( move ); int type = type_c & ~mask_piece_color; int from = MOVE_FROM( move ); int to = MOVE_TO( move ); int prom = MOVE_PROMOTE( move ); if( from == move_drop ) { snprintf( str, 7, "%d%d%d%d%s", 0, 0, 5-( to%5), ( to/5 +1 ), ch_piece_csa[ type ] ); } else if( prom ) { snprintf( str, 7, "%d%d%d%d%s", 5-( from%5 ), ( from/5 +1 ), 5-( to%5), ( to/5 +1 ), ch_piece_csa[ type + m_promote ] ); } else { snprintf( str, 7, "%d%d%d%d%s", 5-( from%5 ), ( from/5 +1 ), 5-( to%5), ( to/5 +1 ), ch_piece_csa[ type ] ); } return; }
bool pseudo_is_legal(int move, board_t * board) { int me, opp; int from, to; int piece; bool legal; int king; undo_t undo[1]; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); // init me = board->turn; opp = COLOUR_OPP(me); from = MOVE_FROM(move); to = MOVE_TO(move); piece = board->square[from]; ASSERT(COLOUR_IS(piece,me)); // slow test for en-passant captures if (MOVE_IS_EN_PASSANT(move)) { move_do(board,move,undo); legal = !IS_IN_CHECK(board,me); move_undo(board,move,undo); return legal; } // king moves (including castle) if (PIECE_IS_KING(piece)) { legal = !is_attacked(board,to,opp); if (DEBUG) { ASSERT(board->square[from]==piece); board->square[from] = Empty; ASSERT(legal==!is_attacked(board,to,opp)); board->square[from] = piece; } return legal; } // pins if (is_pinned(board,from,me)) { king = KING_POS(board,me); return DELTA_INC_LINE(king-to) == DELTA_INC_LINE(king-from); // does not discover the line } return true; }
/* Undoes a move on a board. */ void undo_move(board_t* board, move_t move) { #define UNDO_CASTLE(color, king_side_from, king_side_to, queen_side_from, queen_side_to) \ if (to_square > from_square) { UPDATE_CASTLE_BITBOARDS(color, color##_ROOK, king_side_from, king_side_to); } \ else { UPDATE_CASTLE_BITBOARDS(color, color##_ROOK, queen_side_from, queen_side_to); } #define UNDO_CAPTURE(other_color, square_offset) int captured_square = to_square; \ if (IS_ENPASSANT(move)) { \ captured_square += square_offset; \ } \ board->color_bitboard[other_color] |= SQUARE_MASK[captured_square]; \ board->piece_bitboard[captured_piece] |= SQUARE_MASK[captured_square]; \ board->pieces[captured_square] = captured_piece; #define UNDO_PROMOTION(pawn) board->piece_bitboard[promotion_piece] ^= SQUARE_MASK[to_square]; \ board->piece_bitboard[pawn] |= SQUARE_MASK[to_square]; board->state_index--; board->can_castle = board->state[board->state_index].can_castle; board->passed_square = board->state[board->state_index].passed_square; board->fifty_move_rule_counter = board->state[board->state_index].fifty_move_rule_counter; board->material[WHITE] = board->state[board->state_index].material[WHITE]; board->material[BLACK] = board->state[board->state_index].material[BLACK]; board->hash_key = board->state[board->state_index].hash_key; int from_square = MOVE_FROM(move), to_square = MOVE_TO(move), moving_piece = MOVING_PIECE(move), captured_piece = CAPTURED_PIECE(move), promotion_piece = PROMOTION_PIECE(move); bitboard_t from_to_bitboard = SQUARE_MASK[from_square] | SQUARE_MASK[to_square]; board->pieces[from_square] = moving_piece; board->pieces[to_square] = EMPTY; if (board->to_move == BLACK) { board->color_bitboard[WHITE] ^= from_to_bitboard; if (IS_CASTLE(move)) { UNDO_CASTLE(WHITE, H1, F1, A1, D1); } if (IS_PROMOTION(move)) { UNDO_PROMOTION(WHITE_PAWN); } if (captured_piece) { UNDO_CAPTURE(BLACK, -8); } if (moving_piece == WHITE_KING) board->king_position[WHITE] = from_square; else board->piece_bitboard[moving_piece] ^= from_to_bitboard; board->to_move = WHITE; } else { board->color_bitboard[BLACK] ^= from_to_bitboard; if (IS_CASTLE(move)) { UNDO_CASTLE(BLACK, H8, F8, A8, D8); } if (IS_PROMOTION(move)) { UNDO_PROMOTION(BLACK_PAWN); } if (captured_piece) { UNDO_CAPTURE(WHITE, 8); } if (moving_piece == BLACK_KING) board->king_position[BLACK] = from_square; else board->piece_bitboard[moving_piece] ^= from_to_bitboard; board->to_move = BLACK; } board->all_pieces_bitboard = board->color_bitboard[WHITE] | board->color_bitboard[BLACK]; }
void move_undo(int move, const undo_t * undo) { int me; int from, to; int piece,pos; ASSERT(move_is_ok(move)); ASSERT(undo!=NULL); // init me = undo->turn; from = MOVE_FROM(move); to = MOVE_TO(move); piece = Square[to]; pos=piece & 31; ASSERT(COLOUR_IS(piece,me)); Square[from]=piece; Piece[pos]=from; BitRanks[from>>4] ^= g_BitRankMask[from]; BitFiles[from & 0xf]^= g_BitFileMask[from]; if(undo->capture)//吃子更新 { Square[to]=undo->capture_piece; Piece[undo->capture_piece & 31]=to; Piece_size[PIECE_COLOUR(undo->capture_piece)]++; Number[PieceTo32[undo->capture_piece & 31]]++; }else { Square[to]=Empty; BitRanks[to>>4] ^= g_BitRankMask[to]; BitFiles[to&0xf]^= g_BitFileMask[to]; } Turn = undo->turn; Opening = undo->opening; Endgame = undo->endgame; Key = undo->key; Lock = undo->lock; Sp--; }
int see(Move_t move, Board_t *board) { Board_t temp_board = *global_board(); Board_t *ptr = &temp_board; int attacking_piece = MOVE_PIECE(move); int captured_piece; int gain[32]; int depth = 0; int from = MOVE_FROM(move); int to = MOVE_TO(move); if (ENEMY_PAWNS(ptr) & SQ_MASK(to)) captured_piece = PAWN; else if (ENEMY_KNIGHTS(ptr) & SQ_MASK(to)) captured_piece = KNIGHT; else if (ENEMY_BISHOPS(ptr) & SQ_MASK(to)) captured_piece = BISHOP; else if (ENEMY_ROOKS(ptr) & SQ_MASK(to)) captured_piece = ROOK; else if (ENEMY_QUEENS(ptr) & SQ_MASK(to)) captured_piece = QUEEN; else captured_piece = 0; gain[0] = Piece_Values[captured_piece]; if (MOVE_IS_EN_PASSANT(move)) gain[0] = Piece_Values[PAWN]; do { make_quick_move_on_board(ptr, from, to, captured_piece, attacking_piece); captured_piece = attacking_piece; depth++; gain[depth] = Piece_Values[captured_piece] - gain[depth-1]; if (MAX(-gain[depth-1], gain[depth]) < 0) break; attacking_piece = get_least_valuable_attacker(ptr, to, &from); } while (attacking_piece); while (--depth) gain[depth-1] = -MAX(-gain[depth-1], gain[depth]); return gain[0]; }
bool move_is_check(int move, board_t * board) { undo_t undo[1]; bool check; int me, opp, king; int from, to, piece; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); // slow test for complex moves if (MOVE_IS_SPECIAL(move)) { move_do(board,move,undo); check = IS_IN_CHECK(board,board->turn); move_undo(board,move,undo); return check; } // init me = board->turn; opp = COLOUR_OPP(me); king = KING_POS(board,opp); from = MOVE_FROM(move); to = MOVE_TO(move); piece = board->square[from]; ASSERT(COLOUR_IS(piece,me)); // direct check if (PIECE_ATTACK(board,piece,to,king)) return true; // indirect check if (is_pinned(board,from,opp) && DELTA_INC_LINE(king-to) != DELTA_INC_LINE(king-from)) { return true; } return false; }
static unsigned int history_index(int move, const board_t * board) { unsigned int index; int move_from = MOVE_FROM(move); int piece_12 = PIECE_TO_12(board->square[move_from]); ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!move_is_tactical(move,board)); // index = PIECE_TO_12(board->square[MOVE_FROM(move)]) * 64 + SQUARE_TO_64(MOVE_TO(move)); fruit 2.1 // index = PIECE_TO_12(board->square[MOVE_FROM(move)]) * (64*64) + SQUARE_TO_64(MOVE_FROM(move)) * 64 + SQUARE_TO_64(MOVE_TO(move)); Toga II 1.2.1 (corrected?). index = 64 * piece_12 + SQUARE_TO_64(MOVE_TO(move)); // fruit 2.1 and Toga II 1.4beta5c ASSERT(index >= 0 && index < HistorySize); return index; }
void move_undo(board_t * board, int move, const undo_t * undo) { int me; int from, to; int piece, pos; int rook; ASSERT(board!=NULL); ASSERT(move_is_ok(move)); ASSERT(undo!=NULL); // init me = undo->turn; from = MOVE_FROM(move); to = MOVE_TO(move); piece = board->square[to]; ASSERT(COLOUR_IS(piece,me)); // castle if (MOVE_IS_CASTLE(move)) { rook = Rook64 | COLOUR_FLAG(me); // HACK if (to == G1) { square_move(board,F1,H1,rook,false); } else if (to == C1) { square_move(board,D1,A1,rook,false); } else if (to == G8) { square_move(board,F8,H8,rook,false); } else if (to == C8) { square_move(board,D8,A8,rook,false); } else { ASSERT(false); } } // move the piece backward if (MOVE_IS_PROMOTE(move)) { // promote ASSERT(piece==move_promote(move)); square_clear(board,to,piece,false); piece = PAWN_MAKE(me); pos = undo->pawn_pos; square_set(board,from,piece,pos,false); } else { // normal move square_move(board,to,from,piece,false); } // put the captured piece back if (undo->capture) { square_set(board,undo->capture_square,undo->capture_piece,undo->capture_pos,false); } // update board info board->turn = undo->turn; board->flags = undo->flags; board->ep_square = undo->ep_square; board->ply_nb = undo->ply_nb; board->cap_sq = undo->cap_sq; board->opening = undo->opening; board->endgame = undo->endgame; board->key = undo->key; board->pawn_key = undo->pawn_key; board->material_key = undo->material_key; // update key stack ASSERT(board->sp>0); board->sp--; // debug ASSERT(board_is_ok(board)); ASSERT(board_is_legal(board)); }
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; }
bool move_is_pseudo( int move, board_t *board ) { int me, opp; int from, to; int piece, capture; ASSERT(move_is_ok(move)); ASSERT(board != NULL); // init me = board->turn; opp = COLOUR_OPP(board->turn); // from from = MOVE_FROM(move); ASSERT(SQUARE_IS_OK(from)); piece = board->square[from]; if(INDEX_TO_COLOUR(piece) != me) return false; // to to = MOVE_TO(move); ASSERT(SQUARE_IS_OK(to)); capture = board->square[to]; if( INDEX_TO_COLOUR(capture) == me ) return false; // move switch(INDEX_TO_PIECE(piece)) { case RedKing: if(KING_IN_CITY(to) && KLegalDt[to - from + 256]) return true; if(EQUAL_FILE(from, to) && INDEX_TO_PIECE(capture) == BlackKing) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(FileCapMin[row][board->file[col]] + col == to) return true; } return false; case BlackKing: if(KING_IN_CITY(to) && KLegalDt[to - from + 256]) return true; if(EQUAL_FILE(from, to) && INDEX_TO_PIECE(capture) ==RedKing) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(FileCapMax[row][board->file[col]] + col == to) return true; } return false; case RedAdvisor: case BlackAdvisor: if(ADVISOR_IN_CITY(to) && ALegalDt[to - from + 256]) return true; return false; case RedBishop: case BlackBishop: if(BISHOP_IN_CITY(to) && BLegalDt[to - from + 256] && board->square[(to + from) >> 1] == PieceNone)// return true; return false; case RedKnight: case BlackKnight: if(NLegalDt[to - from + 256] && board->square[from + NLegalDt[to - from + 256]] == PieceNone)// return true; return false; case RedRook: case BlackRook: if(capture) { if(EQUAL_FILE(from, to)) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(FileCapMax[row][board->file[col]] + col == to || FileCapMin[row][board->file[col]] + col == to) return true; } else if(EQUAL_RANK(from, to)) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(RankCapMax[col][board->rank[row]] + (row << 4) == to || RankCapMin[col][board->rank[row]] + (row << 4) == to) return true; } } else { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; int to_row = SQUARE_RANK(to) - 3; int to_col = SQUARE_FILE(to) - 3; int rowbit = board->rank[row]; int colbit = board->file[col]; if(EQUAL_FILE(from, to)) { //if(FileNonCapMin[row][board->file[col]] + col <= to && to <= FileNonCapMax[row][board->file[col]] + col) if(PinNb[row][to_row][colbit] == 0) return true; } else if(EQUAL_RANK(from, to)) { //if(RankNonCapMin[col][board->rank[row]] + (row << 4) <= to && to <= RankNonCapMax[col][board->rank[row]] + (row << 4)) if(PinNb[col][to_col][rowbit] == 0) return true; } } return false; case RedCannon: case BlackCannon: if(capture) { if(EQUAL_RANK(from, to)) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(CannonRankCapMax[col][board->rank[row]] + (row << 4) == to || CannonRankCapMin[col][board->rank[row]] + (row << 4) == to) return true; } else if(EQUAL_FILE(from, to)) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(CannonFileCapMax[row][board->file[col]] + col == to || CannonFileCapMin[row][board->file[col]] + col == to) return true; } } else { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; int to_row = SQUARE_RANK(to) - 3; int to_col = SQUARE_FILE(to) - 3; int rowbit = board->rank[row]; int colbit = board->file[col]; if(EQUAL_RANK(from, to)) { //if(RankNonCapMin[col][board->rank[row]] + (row << 4) <= to && to <= RankNonCapMax[col][board->rank[row]] + (row << 4)) if(PinNb[col][to_col][rowbit] == 0) return true; } else if(EQUAL_FILE(from, to)) { //if(FileNonCapMin[row][board->file[col]] + col <= to&& to <= FileNonCapMax[row][board->file[col]] + col) if(PinNb[row][to_row][colbit] == 0) return true; } } return false; case BlackPawn: if((from + 16) == to) return true; if(SQUARE_COLOUR(from) == Red) { if((from - 1) == to || (from + 1) == to) return true; } return false; case RedPawn: if((from - 16) == to) return true; if(SQUARE_COLOUR(from) == Black) { if((from - 1) == to || (from + 1) == to) return true; } default: return false; } return false; }
void adjust_history_table(Move_t move, int depth, int color) { if (History_Table[color][MOVE_FROM(move)][MOVE_TO(move)] == -VALUE_INFINITE) History_Table[color][MOVE_FROM(move)][MOVE_TO(move)] = depth * depth; else History_Table[color][MOVE_FROM(move)][MOVE_TO(move)] += depth * depth; }
bool capture_is_good(int move, const board_t * board, bool in_pv) { #else static bool capture_is_good(int move, const board_t * board, bool in_pv) { #endif int piece, capture; int see_value; // WHM 11/22/08 ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(move_is_tactical(move,board)); // special cases if (MOVE_IS_EN_PASSANT(move)) return true; if (move_is_under_promote(move)) return false; // REMOVE ME? Keep, looks good to me. WHM; // if (MOVE_IS_PROMOTE(move)) return true; // WHM; promote-to-queen, measures a little weaker // too many garbage lines going nuts. // captures and queen promotes capture = board->square[MOVE_TO(move)]; piece = board->square[MOVE_FROM(move)]; if (capture != Empty) { // capture ASSERT(move_is_capture(move,board)); if (MOVE_IS_PROMOTE(move)) return true; // capture a piece on Rank8 and promote to queen if (VALUE_PIECE(capture) >= VALUE_PIECE(piece)) return true; } // return see_move(move,board) >= 0; WHM 11/22/08 // WHM 11/22/08 START see_value = see_move(move,board); if (see_value >= 0) return true; if (TryNodePVQueenPromotes) { if (in_pv && MOVE_IS_PROMOTE(move)) { ASSERT(!move_is_under_promote(move)); return true; // WHM: } } if (TryKingAttackSacs || TryKingBoxSacs || TryPasserSacs) { if (in_pv && see_value > -ValueBishop && capture != Empty) { ASSERT(COLOUR_IS(capture,COLOUR_OPP(board->turn))); // king attack sacs. if (TryKingAttackSacs) { if (narrow_piece_attack_king(board, piece, MOVE_TO(move), KING_POS(board,COLOUR_OPP(board->turn)))) { return true; } } // sacrifice attacks around the narrow/close king box can be examined more fully. Rybka lessons. if (TryKingBoxSacs) { if (DISTANCE(MOVE_TO(move),KING_POS(board,COLOUR_OPP(board->turn))) <= 1) { return true; } } // passer sacrifices... if (TryPasserSacs) { if (PIECE_IS_PAWN(capture) && PAWN_RANK(MOVE_TO(move),COLOUR_OPP(board->turn)) >= Rank6) { return true; } } } } // WHM 11/22/08 END return false; }
int get_history_score(Move_t move, int color) { return History_Table[color][MOVE_FROM(move)][MOVE_TO(move)]; }
void move_do(board_t * board, int move, undo_t * undo) { int me, opp; int from, to; int piece, pos, capture; int old_flags, new_flags; int delta; int sq; int pawn, rook; ASSERT(board!=NULL); ASSERT(move_is_ok(move)); ASSERT(undo!=NULL); ASSERT(board_is_legal(board)); // initialise undo undo->capture = false; undo->turn = board->turn; undo->flags = board->flags; undo->ep_square = board->ep_square; undo->ply_nb = board->ply_nb; undo->cap_sq = board->cap_sq; undo->opening = board->opening; undo->endgame = board->endgame; undo->key = board->key; undo->pawn_key = board->pawn_key; undo->material_key = board->material_key; // init me = board->turn; opp = COLOUR_OPP(me); from = MOVE_FROM(move); to = MOVE_TO(move); piece = board->square[from]; ASSERT(COLOUR_IS(piece,me)); // update key stack ASSERT(board->sp<StackSize); board->stack[board->sp++] = board->key; // update turn board->turn = opp; board->key ^= RANDOM_64(RandomTurn); // update castling rights old_flags = board->flags; new_flags = old_flags & CastleMask[from] & CastleMask[to]; board->flags = new_flags; board->key ^= Castle64[new_flags^old_flags]; // HACK // update en-passant square if ((sq=board->ep_square) != SquareNone) { board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(sq)-FileA); board->ep_square = SquareNone; } if (PIECE_IS_PAWN(piece)) { delta = to - from; if (delta == +32 || delta == -32) { pawn = PAWN_MAKE(opp); if (board->square[to-1] == pawn || board->square[to+1] == pawn) { board->ep_square = (from + to) / 2; board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(to)-FileA); } } } // update move number (captures are handled later) board->ply_nb++; if (PIECE_IS_PAWN(piece)) board->ply_nb = 0; // conversion // update last square board->cap_sq = SquareNone; // remove the captured piece sq = to; if (MOVE_IS_EN_PASSANT(move)) sq = SQUARE_EP_DUAL(sq); if ((capture=board->square[sq]) != Empty) { ASSERT(COLOUR_IS(capture,opp)); ASSERT(!PIECE_IS_KING(capture)); undo->capture = true; undo->capture_square = sq; undo->capture_piece = capture; undo->capture_pos = board->pos[sq]; square_clear(board,sq,capture,true); board->ply_nb = 0; // conversion board->cap_sq = to; } // move the piece if (MOVE_IS_PROMOTE(move)) { // promote undo->pawn_pos = board->pos[from]; square_clear(board,from,piece,true); piece = move_promote(move); // insert the promote piece in MV order for (pos = board->piece_size[me]; pos > 0 && piece > board->square[board->piece[me][pos-1]]; pos--) // HACK ; square_set(board,to,piece,pos,true); board->cap_sq = to; } else { // normal move square_move(board,from,to,piece,true); } // move the rook in case of castling if (MOVE_IS_CASTLE(move)) { rook = Rook64 | COLOUR_FLAG(me); // HACK if (to == G1) { square_move(board,H1,F1,rook,true); } else if (to == C1) { square_move(board,A1,D1,rook,true); } else if (to == G8) { square_move(board,H8,F8,rook,true); } else if (to == C8) { square_move(board,A8,D8,rook,true); } else { ASSERT(false); } } // debug ASSERT(board_is_ok(board)); }
void move_do(int move, undo_t * undo) { int me, opp; int from, to; int piece, capture,pos; int piece_key; ASSERT(undo!=NULL); //ASSERT(board_is_legal(board)); // initialise undo undo->capture = false; undo->turn = Turn; undo->opening = Opening; undo->endgame = Endgame; undo->key = Key; undo->lock = Lock; // init me = Turn; opp =COLOUR_OPP(me); from = MOVE_FROM(move); to = MOVE_TO(move); piece = Square[from]; if(piece==0) printf("Error move piece %x\n ",move); pos=piece & 31; // update key stack Stack[Sp++] = Lock; // update turn Turn = opp; Key ^= g_ZobristKeyPlayer; Lock ^= g_ZobristLockPlayer; piece_key=PieceToKey32[pos]; if ((capture=Square[to]) != Empty) { undo->capture = true; undo->capture_square = to; undo->capture_piece = capture; //吃掉的子进行清除 Piece[capture & 31]=0; Piece_size[PIECE_COLOUR(capture)]--; Number[PieceTo32[capture & 31]]--; Key ^= g_ZobristKeyTable[piece_key][to]; Lock ^= g_ZobristLockTable[piece_key][to]; }else { //没有吃子,只更新位行、位列 BitRanks[to>>4] ^= g_BitRankMask[to]; BitFiles[to & 0xf] ^= g_BitFileMask[to]; } Square[from] = Empty; Square[to] = piece; Piece[pos] = to; BitRanks[from>>4] ^= g_BitRankMask[from]; BitFiles[from & 0xf] ^= g_BitFileMask[from]; if (piece_key < 5) { Opening +=g_PST[piece_key][to] - g_PST[piece_key][from]; Endgame +=g_PST[piece_key+5][to] - g_PST[piece_key+5][from]; } else { Opening -=g_PST[piece_key-5][254 - to] - g_PST[piece_key-5][254 - from]; Endgame -=g_PST[piece_key][254 - to] - g_PST[piece_key][254 - from]; } Key ^= g_ZobristKeyTable[piece_key][to] ^ g_ZobristKeyTable[piece_key][from]; Lock ^= g_ZobristLockTable[piece_key][to] ^ g_ZobristLockTable[piece_key][from]; // move the piece }
bool move_is_pseudo(int move, board_t * board) { int me, opp; int from, to; int piece, capture; int inc, delta; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); // special cases if (MOVE_IS_SPECIAL(move)) { return move_is_pseudo_debug(move,board); } ASSERT((move&~07777)==0); // init me = board->turn; opp = COLOUR_OPP(board->turn); // from from = MOVE_FROM(move); ASSERT(SQUARE_IS_OK(from)); piece = board->square[from]; if (!COLOUR_IS(piece,me)) return false; ASSERT(piece_is_ok(piece)); // to to = MOVE_TO(move); ASSERT(SQUARE_IS_OK(to)); capture = board->square[to]; if (COLOUR_IS(capture,me)) return false; // move if (PIECE_IS_PAWN(piece)) { if (SQUARE_IS_PROMOTE(to)) return false; inc = PAWN_MOVE_INC(me); delta = to - from; ASSERT(delta_is_ok(delta)); if (capture == Empty) { // pawn push if (delta == inc) return true; if (delta == (2*inc) && PAWN_RANK(from,me) == Rank2 && board->square[from+inc] == Empty) { return true; } } else { // pawn capture if (delta == (inc-1) || delta == (inc+1)) return true; } } else { if (PIECE_ATTACK(board,piece,from,to)) return true; } return false; }
/* Plays a move on a board. The move is assumed to be legal. */ void make_move(board_t* board, move_t move) { #define MAKE_CASTLE(color, removed_castle_bits, king_side_from, king_side_to, queen_side_from, queen_side_to) \ board->can_castle &= removed_castle_bits; \ if (to_square > from_square) { \ UPDATE_CASTLE_BITBOARDS(color, color##_ROOK, king_side_to, king_side_from); \ board->hash_key ^= (hash_keys.keys[king_side_to][color##_ROOK] ^ hash_keys.keys[king_side_from][color##_ROOK]); \ } else { \ UPDATE_CASTLE_BITBOARDS(color, color##_ROOK, queen_side_to, queen_side_from); \ board->hash_key ^= (hash_keys.keys[queen_side_to][color##_ROOK] ^ hash_keys.keys[queen_side_from][color##_ROOK]); } #define MAKE_CAPTURE(other_color, square_offset) int captured_square = to_square; \ if (IS_ENPASSANT(move)) { \ captured_square += square_offset; \ board->pieces[captured_square] = EMPTY; } \ board->color_bitboard[other_color] ^= SQUARE_MASK[captured_square]; \ board->piece_bitboard[captured_piece] ^= SQUARE_MASK[captured_square]; \ board->fifty_move_rule_counter = 0; \ board->material[other_color] -= MATERIAL_VALUE[captured_piece]; \ board->hash_key ^= hash_keys.keys[captured_square][captured_piece]; #define MAKE_PAWN_MOVE(color, square_offset) \ if ((from_square^to_square) == 16) { \ board->passed_square = (to_square - square_offset); \ board->hash_key ^= hash_keys.en_passant_targets[board->passed_square]; }\ if (IS_PROMOTION(move)) { \ board->pieces[to_square] = promotion_piece; \ board->piece_bitboard[color##_PAWN] ^= SQUARE_MASK[to_square]; \ board->piece_bitboard[promotion_piece] |= SQUARE_MASK[to_square]; \ board->material[color] += MATERIAL_VALUE[promotion_piece] - 1; \ board->hash_key ^= (hash_keys.keys[to_square][color##_PAWN] ^ hash_keys.keys[to_square][promotion_piece]); } \ board->fifty_move_rule_counter = 0; board->state[board->state_index].move = move; board->state[board->state_index].can_castle = board->can_castle; board->state[board->state_index].passed_square = board->passed_square; board->state[board->state_index].fifty_move_rule_counter = board->fifty_move_rule_counter; board->state[board->state_index].material[WHITE] = board->material[WHITE]; board->state[board->state_index].material[BLACK] = board->material[BLACK]; board->state[board->state_index].hash_key = board->hash_key; board->fifty_move_rule_counter++; if (board->passed_square) board->hash_key ^= hash_keys.en_passant_targets[board->passed_square]; board->passed_square = 0; int from_square = MOVE_FROM(move), to_square = MOVE_TO(move), moving_piece = MOVING_PIECE(move), captured_piece = CAPTURED_PIECE(move), promotion_piece = PROMOTION_PIECE(move); bitboard_t from_to_bitboard = SQUARE_MASK[from_square] | SQUARE_MASK[to_square]; board->pieces[from_square] = EMPTY; board->pieces[to_square] = moving_piece; board->hash_key ^= (hash_keys.keys[from_square][moving_piece] ^ hash_keys.keys[to_square][moving_piece]); if (board->to_move == WHITE) { board->color_bitboard[WHITE] ^= from_to_bitboard; if (IS_CASTLE(move)) { MAKE_CASTLE(WHITE, 0xC, H1, F1, A1, D1); } if (captured_piece) { MAKE_CAPTURE(BLACK, -8); } if (moving_piece == WHITE_PAWN) { MAKE_PAWN_MOVE(WHITE, 8); } if (moving_piece == WHITE_KING) board->king_position[WHITE] = to_square; else board->piece_bitboard[moving_piece] ^= from_to_bitboard; board->to_move = BLACK; } else { board->color_bitboard[BLACK] ^= from_to_bitboard; if (IS_CASTLE(move)) { MAKE_CASTLE(BLACK, 0x3, H8, F8, A8, D8); } if (captured_piece) { MAKE_CAPTURE(WHITE, 8); } if (moving_piece == BLACK_PAWN) { MAKE_PAWN_MOVE(BLACK, -8); } if (moving_piece == BLACK_KING) board->king_position[BLACK] = to_square; else board->piece_bitboard[moving_piece] ^= from_to_bitboard; board->to_move = WHITE; } board->hash_key ^= hash_keys.side; board->can_castle &= FROM_SQUARE_CASTLING_RIGHTS_MASK[from_square]; if (board->can_castle != board->state[board->state_index].can_castle) { if ((board->can_castle & WHITE_CASTLE_OO) != (board->state[board->state_index].can_castle & WHITE_CASTLE_OO)) board->hash_key ^= hash_keys.white_king_side_castle; if ((board->can_castle & WHITE_CASTLE_OOO) != (board->state[board->state_index].can_castle & WHITE_CASTLE_OOO)) board->hash_key ^= hash_keys.white_queen_side_castle; if ((board->can_castle & BLACK_CASTLE_OO) != (board->state[board->state_index].can_castle & BLACK_CASTLE_OO)) board->hash_key ^= hash_keys.black_king_side_castle; if ((board->can_castle & BLACK_CASTLE_OOO) != (board->state[board->state_index].can_castle & BLACK_CASTLE_OOO)) board->hash_key ^= hash_keys.black_queen_side_castle; } board->all_pieces_bitboard = board->color_bitboard[WHITE] | board->color_bitboard[BLACK]; board->state_index++; }