Skip to content

Commit

Permalink
implementation of incremental evaluation
Browse files Browse the repository at this point in the history
  • Loading branch information
Skoolin committed Sep 20, 2023
1 parent 8977852 commit 196cc6c
Showing 1 changed file with 51 additions and 22 deletions.
73 changes: 51 additions & 22 deletions Chess-Challenge/src/My Bot/MyBot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,15 @@ public Move Think(Board board, Timer timer)
for (int depth = 0; SoftTimeLimit * timer.MillisecondsElapsedThisTurn < timer.MillisecondsRemaining && ++depth < 64;)
{
var score = // #DEBUG
AlphaBeta(depth, -100_000_000, 100_000_000, true, true);
AlphaBeta(depth, -100_000_000, 100_000_000, true, 0, 0, 0, true, true);

SendReport(board, timer, depth, score); // #DEBUG
//stats.PrintStatistics(); // #DEBUG
}

return bestMove;

int AlphaBeta(int depth, int alpha, int beta, bool nullMoveAllowed = true, bool root = false)
int AlphaBeta(int depth, int alpha, int beta, bool needsEval, int mgScore, int egScore, int phase, bool nullMoveAllowed = true, bool root = false)
{
stats.Nodes++; // #DEBUG

Expand All @@ -175,28 +175,35 @@ int AlphaBeta(int depth, int alpha, int beta, bool nullMoveAllowed = true, bool

bool inQSearch = depth <= 0;

// Static evaluation using Piece-Square Tables (https://www.chessprogramming.org/Piece-Square_Tables)
int mgScore = 0, egScore = 0, phase = 0;
// Colors are represented by the xor value of the PSQT flip
foreach (int xor in new[] { 56, 0 })
int prevMg = mgScore;
int prevEg = egScore;
int prevPh = phase;

if (needsEval)
{
for (int piece = 0; piece < 6; piece++)
// Static evaluation using Piece-Square Tables (https://www.chessprogramming.org/Piece-Square_Tables)
mgScore = egScore = phase = 0;
// Colors are represented by the xor value of the PSQT flip
foreach (int xor in new[] { 56, 0 })
{
ulong bitboard = board.GetPieceBitboard((PieceType)piece + 1, xor is 56);
while (bitboard != 0)
for (int piece = 0; piece < 6; piece++)
{
int index = piece + // piece index
16 * (BitboardHelper.ClearAndGetIndexOfLSB(ref bitboard) // row of square
^ xor); // flip board for white pieces
ulong bitboard = board.GetPieceBitboard((PieceType)piece + 1, xor is 56);
while (bitboard != 0)
{
int index = piece + // piece index
16 * (BitboardHelper.ClearAndGetIndexOfLSB(ref bitboard) // row of square
^ xor); // flip board for white pieces

mgScore += pieceSquareTables[index];
egScore += pieceSquareTables[index + 6];
phase += 0b_0100_0010_0001_0001_0000 >> 4 * piece & 0xF;
mgScore += pieceSquareTables[index];
egScore += pieceSquareTables[index + 6];
phase += 0b_0100_0010_0001_0001_0000 >> 4 * piece & 0xF;
}
}
}

mgScore = -mgScore;
egScore = -egScore;
mgScore = -mgScore;
egScore = -egScore;
}
}

// Interpolate between game phases and add a bonus for the side to move
Expand Down Expand Up @@ -241,7 +248,7 @@ int AlphaBeta(int depth, int alpha, int beta, bool nullMoveAllowed = true, bool
if (nullMoveAllowed && depth >= 2 && staticScore >= beta)
{
board.ForceSkipTurn();
score = -AlphaBeta(depth - 4 - depth / 6, -beta, 1 - beta, false);
score = -AlphaBeta(depth - 4 - depth / 6, -beta, 1 - beta, false, mgScore, egScore, phase, false);
board.UndoSkipTurn();
if (score >= beta) return beta;
}
Expand Down Expand Up @@ -283,6 +290,28 @@ int AlphaBeta(int depth, int alpha, int beta, bool nullMoveAllowed = true, bool
break;
}


bool newNeedsEval = move.IsCastles || move.IsCapture || move.IsPromotion;

var tuple = (mgScore, egScore);

void adjustScores(PieceType piece, int squareIdx, int mult)
{
int whiteMult = board.IsWhiteToMove ? mult : -mult;
int index = (int)piece - 1 + 16 * (squareIdx ^ (board.IsWhiteToMove ? 56 : 0));
tuple.mgScore += pieceSquareTables[index] * whiteMult;
tuple.egScore += pieceSquareTables[index + 6] * whiteMult;
}

adjustScores(move.MovePieceType, move.StartSquare.Index, -1);
adjustScores(move.MovePieceType, move.TargetSquare.Index, 1);

if (move.IsCapture)
adjustScores(move.CapturePieceType, move.TargetSquare.Index ^ 56, 1);

int Search(int depth, int newAlpha) =>
-AlphaBeta(depth, newAlpha, -alpha, newNeedsEval, tuple.mgScore, tuple.egScore, move.IsCapture ? phase - 0b_0100_0010_0001_0001_0000 >> 4 * ((int)move.CapturePieceType - 1) & 0xF : phase);

board.MakeMove(move);

if (
Expand All @@ -293,16 +322,16 @@ int AlphaBeta(int depth, int alpha, int beta, bool nullMoveAllowed = true, bool
// late move reductions
moveCount <= 5
|| depth <= 2
|| alpha < (score = -AlphaBeta(depth - moveCount / LMRMoves - depth / LMRDepth - (pvNode ? 1 : 2), -alpha - 1, -alpha))
|| alpha < (score = Search(depth - moveCount / LMRMoves - depth / LMRDepth - (pvNode ? 1 : 2), -alpha - 1))
)
&&
// zero window search
alpha < (score = -AlphaBeta(depth - 1, -alpha - 1, -alpha))
alpha < (score = Search(depth - 1, -alpha - 1))
&& score < beta
&& pvNode
)
// full window search
score = -AlphaBeta(depth - 1, -beta, -alpha);
score = Search(depth - 1, -beta);

board.UndoMove(move);

Expand Down

0 comments on commit 196cc6c

Please sign in to comment.