caching check and nlm
This commit is contained in:
parent
5b45fc32c0
commit
9942832b18
@ -29,10 +29,10 @@ void AIvsAIController::make_move(Move move) {
|
|||||||
view.update_board(board, -1, {});
|
view.update_board(board, -1, {});
|
||||||
|
|
||||||
Colour current_colour = board.white_to_play ? White : Black;
|
Colour current_colour = board.white_to_play ? White : Black;
|
||||||
if (board.is_checkmate_for(current_colour))
|
if (board.is_checkmate())
|
||||||
view.notify_checkmate(current_colour);
|
view.notify_checkmate(current_colour);
|
||||||
|
|
||||||
if (board.is_stalemate_for(current_colour))
|
if (board.is_stalemate())
|
||||||
view.notify_stalemate(current_colour);
|
view.notify_stalemate(current_colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,9 +55,9 @@ void ManualController::make_move(Move move) {
|
|||||||
reset_selection();
|
reset_selection();
|
||||||
|
|
||||||
Colour current_colour = board.white_to_play ? White : Black;
|
Colour current_colour = board.white_to_play ? White : Black;
|
||||||
if (board.is_checkmate_for(current_colour))
|
if (board.is_checkmate())
|
||||||
view.notify_checkmate(current_colour);
|
view.notify_checkmate(current_colour);
|
||||||
|
|
||||||
if (board.is_stalemate_for(current_colour))
|
if (board.is_stalemate())
|
||||||
view.notify_stalemate(current_colour);
|
view.notify_stalemate(current_colour);
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,8 @@ int main(int argc, char* argv[]) {
|
|||||||
// ";
|
// ";
|
||||||
|
|
||||||
// pos for ai timing<
|
// pos for ai timing<
|
||||||
// std::string pos =
|
std::string pos =
|
||||||
// "r3k2r/p1ppqpb1/Bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPB1PPP/R3K2R b KQkq - 0
|
"r3k2r/p1ppqpb1/Bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPB1PPP/R3K2R b KQkq - 0 3 ";
|
||||||
// 3";
|
|
||||||
std::string pos = "r3k2r/p1p1qpb1/bn1ppnp1/3PN3/1p2P3/P1N2Q1p/1PPBBPPP/"
|
|
||||||
"1R2K2R b Kkq - 0 4";
|
|
||||||
|
|
||||||
Board b = Board::setup_fen_position(pos);
|
Board b = Board::setup_fen_position(pos);
|
||||||
|
|
||||||
@ -36,8 +33,8 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
Controller& controller = manual;
|
Controller& controller = manual;
|
||||||
|
|
||||||
// controller.start();
|
controller.start();
|
||||||
|
|
||||||
perft(pos);
|
// perft();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,8 @@ int ai::v1_pure_minimax::_search(const Board& b, int depth) {
|
|||||||
if (depth == 0 || stop_computation)
|
if (depth == 0 || stop_computation)
|
||||||
return eval(b);
|
return eval(b);
|
||||||
|
|
||||||
if (b.no_legal_moves_for(b.white_to_play ? White : Black)) {
|
if (b.no_legal_moves()) {
|
||||||
if (b.is_check_for(b.white_to_play ? White : Black))
|
if (b.is_check())
|
||||||
return -INFINITY;
|
return -INFINITY;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -94,10 +94,8 @@ Board Board::setup_fen_position(std::string fen) {
|
|||||||
index = fen.find(' ', index) + 1;
|
index = fen.find(' ', index) + 1;
|
||||||
board.n_full_moves = std::stoi(fen.substr(index));
|
board.n_full_moves = std::stoi(fen.substr(index));
|
||||||
|
|
||||||
board.w_check = board._is_check_for(White);
|
board.check = board._is_check_for(board.white_to_play ? White : Black);
|
||||||
board.b_check = board._is_check_for(Black);
|
board.nlm = board._no_legal_moves_for(board.white_to_play ? White : Black);
|
||||||
board.w_nlm = board._no_legal_moves_for(White);
|
|
||||||
board.b_nlm = board._no_legal_moves_for(Black);
|
|
||||||
|
|
||||||
return board;
|
return board;
|
||||||
}
|
}
|
||||||
@ -175,6 +173,13 @@ std::string Board::to_fen() const {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Board Board::skip_turn() const {
|
||||||
|
Board ret = *this;
|
||||||
|
ret.white_to_play = !ret.white_to_play;
|
||||||
|
ret.check = ret._is_check_for(ret.white_to_play ? White : Black);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
Board Board::make_move(Move move, bool recurse_call) const {
|
Board Board::make_move(Move move, bool recurse_call) const {
|
||||||
Board ret;
|
Board ret;
|
||||||
std::copy(
|
std::copy(
|
||||||
@ -284,10 +289,8 @@ Board Board::make_move(Move move, bool recurse_call) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (recurse_call) {
|
if (recurse_call) {
|
||||||
ret.w_check = ret._is_check_for(White);
|
ret.check = ret._is_check_for(ret.white_to_play ? White : Black);
|
||||||
ret.b_check = ret._is_check_for(Black);
|
ret.nlm = ret._no_legal_moves_for(ret.white_to_play ? White : Black);
|
||||||
ret.w_nlm = ret._no_legal_moves_for(White);
|
|
||||||
ret.b_nlm = ret._no_legal_moves_for(Black);
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -354,17 +357,9 @@ bool Board::_is_check_for(Colour colour) const {
|
|||||||
all_moves.insert(all_moves.end(), moves.begin(), moves.end());
|
all_moves.insert(all_moves.end(), moves.begin(), moves.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const Move& move : all_moves) {
|
for (const Move& move : all_moves)
|
||||||
// if (colour == White
|
if (move.target_square == king_idx)
|
||||||
// && move.target_square
|
|
||||||
// == Coords::from_algebraic("b6").to_index())
|
|
||||||
// std::cout << "am here" << std::endl;
|
|
||||||
if (move.target_square == king_idx) {
|
|
||||||
std::cout << "indeed check for " << to_string(colour)
|
|
||||||
<< std::endl;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
all_moves.clear();
|
all_moves.clear();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -372,36 +367,35 @@ bool Board::_is_check_for(Colour colour) const {
|
|||||||
|
|
||||||
bool Board::_no_legal_moves_for(Colour colour) const {
|
bool Board::_no_legal_moves_for(Colour colour) const {
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 64; i++) {
|
||||||
if (colour_at(i) == colour) {
|
if (squares[i] == Piece::None || colour_at(i) != colour)
|
||||||
std::vector<Move> moves =
|
continue;
|
||||||
legal_moves(squares[i], *this, Coords::from_index(i));
|
std::vector<Move> moves;
|
||||||
if (moves.size() > 0)
|
moves = legal_moves(squares[i], *this, Coords::from_index(i));
|
||||||
return false;
|
if (moves.size() > 0)
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::no_legal_moves_for(int8_t colour) const {
|
bool Board::no_legal_moves() const {
|
||||||
return colour == White ? w_nlm : b_nlm;
|
return nlm;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::is_check_for(int8_t colour) const {
|
bool Board::is_check() const {
|
||||||
return colour == White ? w_check : b_check;
|
return check;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::is_checkmate_for(Colour colour) const {
|
bool Board::is_checkmate() const {
|
||||||
return no_legal_moves_for(colour) && is_check_for(colour);
|
return check && nlm;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::is_stalemate_for(Colour colour) const {
|
bool Board::is_stalemate() const {
|
||||||
return no_legal_moves_for(colour) && !is_check_for(colour);
|
return !check && nlm;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::is_terminal() const {
|
bool Board::is_terminal() const {
|
||||||
return n_half_moves == 100 || insufficient_material() || white_to_play
|
return n_half_moves == 100 || insufficient_material() || is_checkmate()
|
||||||
? is_checkmate_for(White) || is_stalemate_for(White)
|
|| is_stalemate();
|
||||||
: is_checkmate_for(Black) || is_stalemate_for(Black);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Move> Board::all_legal_moves() const {
|
std::vector<Move> Board::all_legal_moves() const {
|
||||||
|
@ -11,7 +11,7 @@ struct Board {
|
|||||||
int8_t get_king_of(int8_t) const;
|
int8_t get_king_of(int8_t) const;
|
||||||
bool _no_legal_moves_for(Colour) const;
|
bool _no_legal_moves_for(Colour) const;
|
||||||
bool _is_check_for(Colour) const;
|
bool _is_check_for(Colour) const;
|
||||||
bool w_nlm = false, b_nlm = false, w_check = false, b_check = false;
|
bool nlm = false, check = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int8_t squares[64] = {Piece::None};
|
int8_t squares[64] = {Piece::None};
|
||||||
@ -19,15 +19,17 @@ struct Board {
|
|||||||
int8_t w_castle_rights = CastleSide::NeitherSide;
|
int8_t w_castle_rights = CastleSide::NeitherSide;
|
||||||
int8_t b_castle_rights = CastleSide::NeitherSide;
|
int8_t b_castle_rights = CastleSide::NeitherSide;
|
||||||
int8_t en_passant_target = -1;
|
int8_t en_passant_target = -1;
|
||||||
uint8_t n_half_moves = 0;
|
int n_half_moves = 0;
|
||||||
uint8_t n_full_moves = 0;
|
int n_full_moves = 0;
|
||||||
|
|
||||||
|
|
||||||
static Board setup_fen_position(std::string fen);
|
static Board setup_fen_position(std::string fen);
|
||||||
|
|
||||||
|
Board skip_turn() const;
|
||||||
Board make_move(Move, bool = true) const;
|
Board make_move(Move, bool = true) const;
|
||||||
std::string to_fen() const;
|
std::string to_fen() const;
|
||||||
bool no_legal_moves_for(int8_t) const;
|
bool no_legal_moves() const;
|
||||||
bool is_check_for(int8_t) const;
|
bool is_check() const;
|
||||||
bool insufficient_material_for(Colour) const;
|
bool insufficient_material_for(Colour) const;
|
||||||
|
|
||||||
bool insufficient_material() const {
|
bool insufficient_material() const {
|
||||||
@ -37,9 +39,9 @@ struct Board {
|
|||||||
|
|
||||||
std::vector<Move> all_legal_moves() const;
|
std::vector<Move> all_legal_moves() const;
|
||||||
|
|
||||||
bool is_checkmate_for(Colour) const;
|
bool is_checkmate() const;
|
||||||
|
|
||||||
bool is_stalemate_for(Colour) const;
|
bool is_stalemate() const;
|
||||||
|
|
||||||
bool is_terminal() const;
|
bool is_terminal() const;
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ static std::map<std::string, std::map<int, int>> pos2expected{
|
|||||||
{3, 2812}, // 11
|
{3, 2812}, // 11
|
||||||
{4, 43238}, // 157
|
{4, 43238}, // 157
|
||||||
{5, 674624}, // 2199
|
{5, 674624}, // 2199
|
||||||
// {6, 11030083},
|
{6, 11030083},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -55,11 +55,11 @@ static std::map<std::string, std::map<int, int>> pos2expected{
|
|||||||
{
|
{
|
||||||
"r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq - 0 4",
|
"r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq - 0 4",
|
||||||
{
|
{
|
||||||
{1, 6}, // 0
|
{1, 6}, // 0
|
||||||
{2, 264}, // 1
|
{2, 264}, // 1
|
||||||
{3, 9467}, // 69
|
{3, 9467}, // 69
|
||||||
{4, 422333}, // 3085
|
{4, 422333}, // 3085
|
||||||
// {5, 15833292}, // 124452
|
{5, 15833292}, // 124452
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -67,11 +67,11 @@ static std::map<std::string, std::map<int, int>> pos2expected{
|
|||||||
{
|
{
|
||||||
"r2q1rk1/pP1p2pp/Q4n2/bbp1p3/Np6/1B3NBn/pPPP1PPP/R3K2R b KQ - 0 5",
|
"r2q1rk1/pP1p2pp/Q4n2/bbp1p3/Np6/1B3NBn/pPPP1PPP/R3K2R b KQ - 0 5",
|
||||||
{
|
{
|
||||||
{1, 6}, // 0
|
{1, 6}, // 0
|
||||||
{2, 264}, // 2
|
{2, 264}, // 2
|
||||||
{3, 9467}, // 104
|
{3, 9467}, // 104
|
||||||
{4, 422333}, // 3742
|
{4, 422333}, // 3742
|
||||||
// {5, 15833292}, // 136784
|
{5, 15833292}, // 136784
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -79,10 +79,10 @@ static std::map<std::string, std::map<int, int>> pos2expected{
|
|||||||
{
|
{
|
||||||
"rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 6",
|
"rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 6",
|
||||||
{
|
{
|
||||||
{1, 44}, // 0
|
{1, 44}, // 0
|
||||||
{2, 1486}, // 12
|
{2, 1486}, // 12
|
||||||
{3, 62379}, // 357
|
{3, 62379}, // 357
|
||||||
// {4, 2103487}, // 13804
|
{4, 2103487}, // 13804
|
||||||
// {5, 89941194}, // 1230428
|
// {5, 89941194}, // 1230428
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -92,43 +92,13 @@ static std::map<std::string, std::map<int, int>> pos2expected{
|
|||||||
"r4rk1/1pp1qppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PP1QPPP/R4RK1 w - - 0 "
|
"r4rk1/1pp1qppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PP1QPPP/R4RK1 w - - 0 "
|
||||||
"7",
|
"7",
|
||||||
{
|
{
|
||||||
{1, 46}, // 0
|
{1, 46}, // 0
|
||||||
{2, 2079}, // 16
|
{2, 2079}, // 16
|
||||||
{3, 89890}, // 602
|
{3, 89890}, // 602
|
||||||
// {4, 3894594}, // 26612
|
{4, 3894594}, // 26612
|
||||||
// {5, 164075551}, // 1230428
|
// {5, 164075551}, // 1230428
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// -- Position 7
|
|
||||||
{
|
|
||||||
"r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 4 3",
|
|
||||||
{
|
|
||||||
{4, 4085603}, //
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// -- Position 7 after a1b1
|
|
||||||
{
|
|
||||||
"r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/1R2K2R b Kkq - 5 3",
|
|
||||||
{
|
|
||||||
{3, 83348}, //
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// -- Position 7 after a1b1 d7d6
|
|
||||||
{
|
|
||||||
"r3k2r/p1p1qpb1/bn1ppnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/1R2K2R w Kkq - 0 4",
|
|
||||||
{
|
|
||||||
{2, 1919}, //
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// -- Position 7 after a1b1 d7d6 a2a3
|
|
||||||
{
|
|
||||||
"r3k2r/p1p1qpb1/bn1ppnp1/3PN3/1p2P3/P1N2Q1p/1PPBBPPP/1R2K2R b Kkq - 0 "
|
|
||||||
"4",
|
|
||||||
{
|
|
||||||
{1, 45}, //
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::stringstream res;
|
static std::stringstream res;
|
||||||
@ -142,43 +112,43 @@ int move_generation_test(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (b.is_terminal())
|
if (b.is_terminal())
|
||||||
return 1;
|
return 0;
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
std::vector<Move> moves = b.all_legal_moves();
|
std::vector<Move> moves = b.all_legal_moves();
|
||||||
// if (depth == 1)
|
if (depth == 1)
|
||||||
// return moves.size();
|
return moves.size();
|
||||||
|
|
||||||
int num_pos = 0;
|
int num_pos = 0;
|
||||||
|
|
||||||
// if (depth == max_depth) {
|
if (depth == max_depth) {
|
||||||
// // Parallel execution at the top level
|
// Parallel execution at the top level
|
||||||
// std::vector<std::future<int>> futures;
|
std::vector<std::future<int>> futures;
|
||||||
// for (const Move& move : moves) {
|
for (const Move& move : moves) {
|
||||||
// Board tmp_board = b.make_move(move);
|
Board tmp_board = b.make_move(move);
|
||||||
// futures.push_back(pool.enqueue(
|
futures.push_back(pool.enqueue(
|
||||||
// move_generation_test,
|
move_generation_test,
|
||||||
// tmp_board,
|
tmp_board,
|
||||||
// depth - 1,
|
depth - 1,
|
||||||
// max_depth,
|
max_depth,
|
||||||
// std::ref(pool)
|
std::ref(pool)
|
||||||
// ));
|
));
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// for (auto& future : futures)
|
for (auto& future : futures)
|
||||||
// num_pos += future.get(); // Retrieve the result of each task
|
num_pos += future.get(); // Retrieve the result of each task
|
||||||
// } else {
|
} else {
|
||||||
// Regular sequential execution
|
// Regular sequential execution
|
||||||
for (const Move& move : moves) {
|
for (const Move& move : moves) {
|
||||||
// std::cout << "Looking at " << move << std::endl;
|
// std::cout << "Looking at " << move << std::endl;
|
||||||
Board tmp_board = b.make_move(move);
|
Board tmp_board = b.make_move(move);
|
||||||
int n = move_generation_test(tmp_board, depth - 1, max_depth, pool);
|
int n = move_generation_test(tmp_board, depth - 1, max_depth, pool);
|
||||||
if (depth == max_depth)
|
if (depth == max_depth)
|
||||||
res << move << ": " << n << std::endl;
|
res << move << ": " << n << std::endl;
|
||||||
num_pos += n;
|
num_pos += n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
return num_pos;
|
return num_pos;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,8 @@ static bool is_clear_king_side(const Board& b, const Coords xy) {
|
|||||||
|
|
||||||
std::optional<Move> move = move_for_position(b, xy, c);
|
std::optional<Move> move = move_for_position(b, xy, c);
|
||||||
Board board_after_move = b.make_move(move.value(), false);
|
Board board_after_move = b.make_move(move.value(), false);
|
||||||
if (board_after_move.is_check_for(b.colour_at(xy)))
|
board_after_move = board_after_move.skip_turn();
|
||||||
|
if (board_after_move.is_check())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -25,7 +26,8 @@ static bool is_clear_queen_side(const Board& b, const Coords xy) {
|
|||||||
|
|
||||||
std::optional<Move> move = move_for_position(b, xy, c);
|
std::optional<Move> move = move_for_position(b, xy, c);
|
||||||
Board board_after_move = b.make_move(move.value(), false);
|
Board board_after_move = b.make_move(move.value(), false);
|
||||||
if (dx < 3 && board_after_move.is_check_for(b.colour_at(xy)))
|
board_after_move = board_after_move.skip_turn();
|
||||||
|
if (dx < 3 && board_after_move.is_check())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -46,11 +48,9 @@ std::vector<Move> king_moves(const Board& b, const Coords xy) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.is_check_for(b.colour_at(xy))) {
|
|
||||||
std::cout << b.to_fen() << std::endl;
|
if (b.is_check())
|
||||||
std::cout << "Check for " << to_string(b.colour_at(xy)) << std::endl;
|
|
||||||
return keep_only_blocking(ret, b);
|
return keep_only_blocking(ret, b);
|
||||||
}
|
|
||||||
|
|
||||||
// -- Castles
|
// -- Castles
|
||||||
int8_t castling_rights = b.colour_at(xy) == Colour::White
|
int8_t castling_rights = b.colour_at(xy) == Colour::White
|
||||||
|
@ -13,10 +13,10 @@ keep_only_blocking(const std::vector<Move> candidates, const Board& board) {
|
|||||||
std::vector<Move> ret;
|
std::vector<Move> ret;
|
||||||
for (Move move : candidates) {
|
for (Move move : candidates) {
|
||||||
Board board_after_move = board.make_move(move, false);
|
Board board_after_move = board.make_move(move, false);
|
||||||
if (!board_after_move.is_check_for(my_colour))
|
board_after_move = board_after_move.skip_turn();
|
||||||
|
|
||||||
|
if (!board_after_move.is_check())
|
||||||
ret.push_back(move);
|
ret.push_back(move);
|
||||||
else
|
|
||||||
std::cout << "removing " << move << std::endl;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user