void chess_generate_init(void) { static int initialized = 0; ChessSquare sq; int dirs, d; int slide, jump; int file, rank; int to_file, to_rank; if (initialized) return; initialized = 1; for (sq = CHESS_SQUARE_A1; sq <= CHESS_SQUARE_H8; sq++) { dirs = 0; file = chess_square_file(sq); rank = chess_square_rank(sq); for (d = 0; d < 8; d++) { slide = slides_array[d]; to_file = file + chess_square_file(slide + 36) - 4; to_rank = rank + chess_square_rank(slide + 36) - 4; if (to_file >= CHESS_FILE_A && to_file <= CHESS_FILE_H && to_rank >= CHESS_RANK_1 && to_rank <= CHESS_RANK_8) dirs |= dirs_array[d]; } slide_dirs[sq] = dirs; } for (sq = CHESS_SQUARE_A1; sq <= CHESS_SQUARE_H8; sq++) { dirs = 0; file = chess_square_file(sq); rank = chess_square_rank(sq); for (d = 0; d < 8; d++) { jump = jumps_array[d]; to_file = file + chess_square_file(jump + 36) - 4; to_rank = rank + chess_square_rank(jump + 36) - 4; if (to_file >= CHESS_FILE_A && to_file <= CHESS_FILE_H && to_rank >= CHESS_RANK_1 && to_rank <= CHESS_RANK_8) dirs |= dirs_array[d]; } jump_dirs[sq] = dirs; } }
void chess_position_undo_move(ChessPosition* position, ChessUnmove unmove) { ChessSquare from = chess_unmove_from(unmove); ChessSquare to = chess_unmove_to(unmove); ChessUnmoveCaptured captured = chess_unmove_captured(unmove); ChessUnmoveEp ep = chess_unmove_ep(unmove); ChessPiece piece; ChessColor other = position->to_move; ChessColor color = chess_color_other(other); ChessFile file; if (from == 0 && to == 0) { /* Null move */ piece = CHESS_PIECE_NONE; } else { if (chess_unmove_promotion(unmove)) piece = chess_piece_of_color(CHESS_PIECE_WHITE_PAWN, color); else piece = position->piece[to]; assert(color == chess_piece_color(piece)); /* Unmove the piece */ position->piece[from] = piece; position->piece[to] = captured_piece(captured, other); /* Handle castling */ if (piece == CHESS_PIECE_WHITE_KING && from == CHESS_SQUARE_E1) { if (to == CHESS_SQUARE_G1) { position->piece[CHESS_SQUARE_F1] = CHESS_PIECE_NONE; position->piece[CHESS_SQUARE_H1] = CHESS_PIECE_WHITE_ROOK; } else if (to == CHESS_SQUARE_C1) { position->piece[CHESS_SQUARE_D1] = CHESS_PIECE_NONE; position->piece[CHESS_SQUARE_A1] = CHESS_PIECE_WHITE_ROOK; } } else if (piece == CHESS_PIECE_BLACK_KING && from == CHESS_SQUARE_E8) { if (to == CHESS_SQUARE_G8) { position->piece[CHESS_SQUARE_F8] = CHESS_PIECE_NONE; position->piece[CHESS_SQUARE_H8] = CHESS_PIECE_BLACK_ROOK; } else if (to == CHESS_SQUARE_C8) { position->piece[CHESS_SQUARE_D8] = CHESS_PIECE_NONE; position->piece[CHESS_SQUARE_A8] = CHESS_PIECE_BLACK_ROOK; } } position->castle = chess_unmove_castle(unmove); } /* Handle ep */ if (ep == CHESS_UNMOVE_EP_NONE) { position->ep = CHESS_FILE_INVALID; } else if (ep == CHESS_UNMOVE_EP_CAPTURE) { assert(piece == CHESS_PIECE_WHITE_PAWN || piece == CHESS_PIECE_BLACK_PAWN); /* Restore the captured pawn */ file = chess_square_file(to); if (color == CHESS_COLOR_WHITE) position->piece[chess_square_from_fr(file, CHESS_RANK_5)] = CHESS_PIECE_BLACK_PAWN; else position->piece[chess_square_from_fr(file, CHESS_RANK_4)] = CHESS_PIECE_WHITE_PAWN; position->ep = file; } else { position->ep = ep - CHESS_UNMOVE_EP_AVAILABLE; } /* Update king positions */ if (piece == CHESS_PIECE_WHITE_KING) position->wking = from; else if (piece == CHESS_PIECE_BLACK_KING) position->bking = from; /* Update move counters */ position->fifty = chess_unmove_fifty(unmove); position->to_move = color; if (position->to_move == CHESS_COLOR_BLACK) position->move_num--; }
ChessUnmove chess_position_make_move(ChessPosition* position, ChessMove move) { ChessSquare from = chess_move_from(move); ChessSquare to = chess_move_to(move); ChessMovePromote promote = chess_move_promotes(move); ChessPiece piece; ChessColor color = position->to_move; ChessUnmoveEp ep; ChessUnmoveCaptured captured; ChessCastleState castle = position->castle; int fifty = position->fifty; /* Move the piece */ if (move == CHESS_MOVE_NULL) { piece = CHESS_PIECE_NONE; captured = CHESS_UNMOVE_CAPTURED_NONE; } else { piece = position->piece[from]; captured = capture_piece(position->piece[to]); position->piece[from] = CHESS_PIECE_NONE; if (promote == CHESS_MOVE_PROMOTE_NONE) { position->piece[to] = piece; if (piece == CHESS_PIECE_WHITE_KING) position->wking = to; else if (piece == CHESS_PIECE_BLACK_KING) position->bking = to; } else { position->piece[to] = promoted_piece(promote, color); } /* Handle castling */ if (piece == CHESS_PIECE_WHITE_KING && from == CHESS_SQUARE_E1) { if (to == CHESS_SQUARE_G1) { position->piece[CHESS_SQUARE_F1] = CHESS_PIECE_WHITE_ROOK; position->piece[CHESS_SQUARE_H1] = CHESS_PIECE_NONE; } else if (to == CHESS_SQUARE_C1) { position->piece[CHESS_SQUARE_D1] = CHESS_PIECE_WHITE_ROOK; position->piece[CHESS_SQUARE_A1] = CHESS_PIECE_NONE; } } else if (piece == CHESS_PIECE_BLACK_KING && from == CHESS_SQUARE_E8) { if (to == CHESS_SQUARE_G8) { position->piece[CHESS_SQUARE_F8] = CHESS_PIECE_BLACK_ROOK; position->piece[CHESS_SQUARE_H8] = CHESS_PIECE_NONE; } else if (to == CHESS_SQUARE_C8) { position->piece[CHESS_SQUARE_D8] = CHESS_PIECE_BLACK_ROOK; position->piece[CHESS_SQUARE_A8] = CHESS_PIECE_NONE; } } /* Check if castling availability was lost */ if (position->castle & (CHESS_CASTLE_STATE_WKQ)) { if (from == CHESS_SQUARE_A1 || to == CHESS_SQUARE_A1) position->castle &= ~CHESS_CASTLE_STATE_WQ; if (from == CHESS_SQUARE_H1 || to == CHESS_SQUARE_H1) position->castle &= ~CHESS_CASTLE_STATE_WK; if (from == CHESS_SQUARE_E1 || to == CHESS_SQUARE_E1) position->castle &= ~(CHESS_CASTLE_STATE_WKQ); } if (position->castle & (CHESS_CASTLE_STATE_BKQ)) { if (from == CHESS_SQUARE_A8 || to == CHESS_SQUARE_A8) position->castle &= ~CHESS_CASTLE_STATE_BQ; if (from == CHESS_SQUARE_H8 || to == CHESS_SQUARE_H8) position->castle &= ~CHESS_CASTLE_STATE_BK; if (from == CHESS_SQUARE_E8 || to == CHESS_SQUARE_E8) position->castle &= ~(CHESS_CASTLE_STATE_BKQ); } } /* Handle ep */ if (position->ep == CHESS_FILE_INVALID) { ep = CHESS_UNMOVE_EP_NONE; } else { if (piece == CHESS_PIECE_WHITE_PAWN && to == chess_square_from_fr(position->ep, CHESS_RANK_6)) { position->piece[chess_square_from_fr(position->ep, CHESS_RANK_5)] = CHESS_PIECE_NONE; ep = CHESS_UNMOVE_EP_CAPTURE; } else if (piece == CHESS_PIECE_BLACK_PAWN && to == chess_square_from_fr(position->ep, CHESS_RANK_3)) { position->piece[chess_square_from_fr(position->ep, CHESS_RANK_4)] = CHESS_PIECE_NONE; ep = CHESS_UNMOVE_EP_CAPTURE; } else { ep = CHESS_UNMOVE_EP_AVAILABLE + position->ep; } } /* Update ep on a double pawn move */ if (piece == CHESS_PIECE_WHITE_PAWN && to - from == 16) position->ep = chess_square_file(to); else if (piece == CHESS_PIECE_BLACK_PAWN && from - to == 16) position->ep = chess_square_file(to); else position->ep = CHESS_FILE_INVALID; /* Update fifty counter only if a reversible move was played */ if (piece == CHESS_PIECE_WHITE_PAWN || piece == CHESS_PIECE_BLACK_PAWN || captured != CHESS_UNMOVE_CAPTURED_NONE || castle != position->castle) position->fifty = 0; else position->fifty++; /* Update move counter */ position->to_move = chess_color_other(position->to_move); if (position->to_move == CHESS_COLOR_WHITE) position->move_num++; return chess_unmove_make(from, to, captured, promote != CHESS_MOVE_PROMOTE_NONE, ep, castle, fifty); }