aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/board.cpp8
-rw-r--r--src/bot.cpp180
-rw-r--r--src/bot.hpp3
-rw-r--r--src/main.cpp3
-rw-r--r--src/repl.cpp4
5 files changed, 123 insertions, 75 deletions
diff --git a/src/board.cpp b/src/board.cpp
index d7fe87b..3c5f5ec 100644
--- a/src/board.cpp
+++ b/src/board.cpp
@@ -79,7 +79,7 @@ void printBoard(Board *b) {
std::cout << bg << " " << symbol << " " << reset;
}
- std::printf(" | %d\n", 8 - rank);
+ std::printf("| %d\n", 8 - rank);
}
}
@@ -97,7 +97,7 @@ void printBoard(Board *b) {
8 - (int)b->enPassant.rank);
std::printf("Move clock: %d\n", b->MoveClock);
std::printf("Half move clock: %d\n", b->halfMoveClock);
- std::printf("Board Eval: %f\n", EvaluateBoard(b));
+ std::printf("Board Eval: %f\n", EvaluateBoardForWhite(b));
}
void PlayMove(Move move, Board *b) {
@@ -135,10 +135,14 @@ void PlayMove(Move move, Board *b) {
};
}
+ if (piece.type == PAWN && move.To.rank == (piece.color ? 0 : 7)) {
+ piece.type = QUEEN;
+ }
if (b->halfMoveClock >= 50) {
b->state = DRAW;
}
b->pieces[PositionToIndex(move.To)] = piece;
b->pieces[PositionToIndex(move.From)] = {false, NONE, false};
+ b->turn = !b->turn;
};
int PositionToIndex(Position i) { return i.rank * 8 + i.file; }
diff --git a/src/bot.cpp b/src/bot.cpp
index 8889156..e3a39f2 100644
--- a/src/bot.cpp
+++ b/src/bot.cpp
@@ -1,103 +1,145 @@
#include "bot.hpp"
#include "board.hpp"
#include "moves.hpp"
+#include <algorithm>
+#include <cassert>
#include <cmath>
-#include <ctime>
+#include <iostream>
int PAWN_VALUE = 100;
int KNIGHT_VALUE = 200;
int BISHOP_VALUE = 300;
int ROOK_VALUE = 400;
int QUEEN_VALUE = 900;
+int MATE = 10000;
+
+const int SEARCH_DEPTH = 3;
+
+int positions_consider = 0;
Move EngineGetBestMove(Board *b) {
auto moves = GetLegalMoves(b);
- std::srand(std::time(0)); // use current time as seed for random generator
- int random_pos = std::rand() % moves.size();
- Move move = moves[random_pos];
- return move;
+ if (moves.size() == 0) {
+ assert(false && "Unhanled error zero legal moves for bot");
+ }
+ Move bestMove = moves[0];
+ float BestEval = (b->turn ? -INFINITY : INFINITY);
+ for (Move move : moves) {
+ Board TestBoard = *b;
+ PlayMove(move, &TestBoard);
+ float alpha = -INFINITY;
+ float beta = INFINITY;
+
+ float eval = minimax(SEARCH_DEPTH - 1, &TestBoard, alpha, beta);
+ if (b->turn) {
+ if (eval > BestEval) {
+ BestEval = eval;
+ bestMove = move;
+ }
+ } else {
+ if (eval < BestEval) {
+ BestEval = eval;
+ bestMove = move;
+ }
+ }
+ }
+ std::cout << "\nConsider: " << positions_consider << "\n";
+ return bestMove;
+}
+float minimax(int depth, Board *b, float alpha, float beta) {
+ if (depth == 0) {
+ return EvaluateBoardForWhite(b);
+ }
+ auto moves = GetLegalMoves(b);
+ if (moves.size() == 0) {
+ return EvaluateBoardForWhite(b);
+ }
+ if (b->turn) {
+ float bestEval = -INFINITY;
+
+ for (Move move : moves) {
+ Board next = *b;
+ PlayMove(move, &next);
+
+ float eval = minimax(depth - 1, &next, alpha, beta);
+ bestEval = std::max(bestEval, eval);
+
+ alpha = std::max(alpha, bestEval);
+
+ if (alpha >= beta) {
+ break;
+ }
+ }
+
+ return bestEval;
+ } else {
+ float BestEval = INFINITY;
+
+ for (Move move : moves) {
+ Board next = *b;
+ PlayMove(move, &next);
+
+ float eval = minimax(depth - 1, &next, alpha, beta);
+
+ BestEval = std::min(BestEval, eval);
+
+ beta = std::min(beta, BestEval);
+ if (alpha >= beta) {
+ break; // *snips*
+ }
+ }
+ return BestEval;
+ }
}
-float EvaluateBoard(Board *b) {
+float EvaluateBoardForWhite(Board *b) {
+ positions_consider++;
float score = 0;
- Board BoardCopy = *b;
bool isStaleMate = false;
- auto legalMoves = GetLegalMoves(&BoardCopy);
+ GetLegalMoves(b);
if (b->state == WHITE_WON) {
- score = INFINITY;
+ return MATE;
}
if (b->state == BLACK_WON) {
- score = INFINITY * -1;
+ return -MATE;
}
if (b->state == STALEMATE || b->state == DRAW) {
isStaleMate = true;
}
- int white_pawn_count = 0;
- int white_knight_count = 0;
- int white_bishop_count = 0;
- int white_rook_count = 0;
- int white_queen_count = 0;
-
- int black_pawn_count = 0;
- int black_knight_count = 0;
- int black_bishop_count = 0;
- int black_rook_count = 0;
- int black_queen_count = 0;
+
for (Piece piece : b->pieces) {
- if (piece.type == NONE) {
+ if (piece.type == NONE)
continue;
- }
- if (piece.color) {
- // white
- if (piece.type == PAWN) {
- white_pawn_count++;
- }
- if (piece.type == KNIGHT) {
- white_knight_count++;
- }
- if (piece.type == BISHOP) {
- white_bishop_count++;
- }
- if (piece.type == ROOK) {
- white_rook_count++;
- }
- if (piece.type == QUEEN) {
- white_queen_count++;
- }
- continue;
- }
- // black
- if (piece.type == PAWN) {
- black_pawn_count++;
- }
- if (piece.type == KNIGHT) {
- black_knight_count++;
- }
- if (piece.type == BISHOP) {
- black_bishop_count++;
- }
- if (piece.type == ROOK) {
- black_rook_count++;
- }
- if (piece.type == QUEEN) {
- black_queen_count++;
+ int value = 0;
+
+ switch (piece.type) {
+ case PAWN:
+ value = PAWN_VALUE;
+ break;
+ case KNIGHT:
+ value = KNIGHT_VALUE;
+ break;
+ case BISHOP:
+ value = BISHOP_VALUE;
+ break;
+ case ROOK:
+ value = ROOK_VALUE;
+ break;
+ case QUEEN:
+ value = QUEEN_VALUE;
+ break;
+ default:
+ break;
}
- }
- score += white_pawn_count * PAWN_VALUE;
- score += white_knight_count * KNIGHT_VALUE;
- score += white_bishop_count * BISHOP_VALUE;
- score += white_rook_count * ROOK;
- score += white_queen_count * QUEEN_VALUE;
-
- score -= black_pawn_count * PAWN_VALUE;
- score -= black_knight_count * KNIGHT_VALUE;
- score -= black_bishop_count * BISHOP_VALUE;
- score -= black_rook_count * ROOK;
- score -= black_queen_count * QUEEN_VALUE;
+ if (piece.color)
+ score += value;
+ else
+ score -= value;
+ }
if (isStaleMate) {
return 0;
}
diff --git a/src/bot.hpp b/src/bot.hpp
index 1a2b951..1403bc4 100644
--- a/src/bot.hpp
+++ b/src/bot.hpp
@@ -3,6 +3,7 @@
#include "board.hpp"
Move EngineGetBestMove(Board *b);
-float EvaluateBoard(Board *b);
+float EvaluateBoardForWhite(Board *b);
+float minimax(int depth, Board *b, float alpha, float beta);
#endif /* SRC_BOT_H_ */
diff --git a/src/main.cpp b/src/main.cpp
index 706ca28..555e728 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -3,6 +3,8 @@
#include "moves.hpp"
#include "repl.hpp"
#include <cstdio>
+#include <cstdlib>
+#include <ctime>
#include <string>
using namespace std;
@@ -37,6 +39,7 @@ Board initBoard(string startingFEN) {
#define askMode = false
int main(int argc, char **argv) {
+ srand(time(0));
std::string startingFen =
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
if (argc < 1 || argc > 2) {
diff --git a/src/repl.cpp b/src/repl.cpp
index ce545d1..b936af0 100644
--- a/src/repl.cpp
+++ b/src/repl.cpp
@@ -53,10 +53,9 @@ int startREPL(Board *b) {
return 0;
}
if (b->state == TURN) {
- if (b->turn == false) {
+ if (true) {
Move move = EngineGetBestMove(b);
PlayMove(move, b);
- b->turn = !b->turn;
printBoard(b);
continue;
}
@@ -147,7 +146,6 @@ int startREPL(Board *b) {
}
std::println();
PlayMove(move, b);
- b->turn = !b->turn;
printBoard(b);
}
}