Skip to content

Commit

Permalink
speed and accuracy improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
sictransit authored Nov 26, 2024
1 parent 0537086 commit 6fb539e
Show file tree
Hide file tree
Showing 18 changed files with 457 additions and 216 deletions.
129 changes: 81 additions & 48 deletions Common/Board.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using SicTransit.Woodpusher.Common.Interfaces;
using SicTransit.Woodpusher.Common.Lookup;
using SicTransit.Woodpusher.Model;
using SicTransit.Woodpusher.Model.Enums;
using SicTransit.Woodpusher.Model.Extensions;
using System.Numerics;

namespace SicTransit.Woodpusher.Common;

Expand All @@ -14,7 +12,9 @@ public class Board : IBoard
private readonly Bitboard activeBoard;
private readonly Bitboard opponentBoard;
private readonly bool whiteIsPlaying;
private readonly BoardInternals internals;
private readonly BoardInternals internals;

private int? score = null;

public Counters Counters { get; }

Expand Down Expand Up @@ -57,18 +57,36 @@ public int Score
{
get
{
var phase = white.Phase + black.Phase;
if (!score.HasValue)
{
var phase = white.Phase + black.Phase;

var score = 0;
score = 0;

foreach (var piece in GetPieces())
{
var evaluation = internals.Scoring.EvaluatePiece(piece, phase);

score += evaluation * (piece.Is(Piece.White) ? 1 : -1);
foreach (var piece in GetPieces(Piece.White))
{
var evaluation = internals.Scoring.EvaluatePiece(piece, phase);

score += evaluation;
}

//score += BitOperations.PopCount(white.Knight) > 1 ? 50 : 0;
//score += BitOperations.PopCount(white.Bishop) > 1 ? 50 : 0;
//score += BitOperations.PopCount(white.Rook) > 1 ? 50 : 0;

foreach (var piece in GetPieces(Piece.None))
{
var evaluation = internals.Scoring.EvaluatePiece(piece, phase);

score -= evaluation;
}

//score -= BitOperations.PopCount(black.Knight) > 1 ? 50 : 0;
//score -= BitOperations.PopCount(black.Bishop) > 1 ? 50 : 0;
//score -= BitOperations.PopCount(black.Rook) > 1 ? 50 : 0;
}

return score;
return score.Value;
}
}

Expand Down Expand Up @@ -232,46 +250,66 @@ public IEnumerable<Piece> GetPiecesInRange(Piece piece, Piece color)

var opponent = GetBitboard(color);

foreach (var knight in opponent.GetPieces(Piece.Knight, threats.Knight))
if ((opponent.AllPieces & threats.All) == 0)
{
yield return knight;
yield break;
}

foreach (var pawn in opponent.GetPieces(Piece.Pawn, threats.Pawn))
var target = piece.GetMask();

if ((opponent.Queen & threats.Queen) != 0)
{
yield return pawn;
foreach (var queen in opponent.GetPieces(Piece.Queen, threats.Queen))
{
if (!IsOccupied(internals.Moves.GetTravelMask(queen.GetMask(), target)))
{
yield return queen;
}
}
}

foreach (var king in opponent.GetPieces(Piece.King, threats.King))
if ((opponent.Bishop & threats.Bishop) != 0)
{
yield return king;
foreach (var bishop in opponent.GetPieces(Piece.Bishop, threats.Bishop))
{
if (!IsOccupied(internals.Moves.GetTravelMask(bishop.GetMask(), target)))
{
yield return bishop;
}
}
}

var target = piece.GetMask();

foreach (var bishop in opponent.GetPieces(Piece.Bishop, threats.Bishop))
if ((opponent.Rook & threats.Rook) != 0)
{
if (!IsOccupied(internals.Moves.GetTravelMask(bishop.GetMask(), target)))
foreach (var rook in opponent.GetPieces(Piece.Rook, threats.Rook))
{
yield return bishop;
if (!IsOccupied(internals.Moves.GetTravelMask(rook.GetMask(), target)))
{
yield return rook;
}
}
}

foreach (var queen in opponent.GetPieces(Piece.Queen, threats.Queen))
if ((opponent.Knight & threats.Knight) != 0)
{
if (!IsOccupied(internals.Moves.GetTravelMask(queen.GetMask(), target)))
foreach (var knight in opponent.GetPieces(Piece.Knight, threats.Knight))
{
yield return queen;
yield return knight;
}
}

foreach (var rook in opponent.GetPieces(Piece.Rook, threats.Rook))
if ((opponent.Pawn & threats.Pawn) != 0)
{
if (!IsOccupied(internals.Moves.GetTravelMask(rook.GetMask(), target)))
foreach (var pawn in opponent.GetPieces(Piece.Pawn, threats.Pawn))
{
yield return rook;
yield return pawn;
}
}

foreach (var king in opponent.GetPieces(Piece.King, threats.King))
{
yield return king;
}
}

public IEnumerable<Move> GetLegalMoves()
Expand All @@ -284,18 +322,18 @@ public IEnumerable<Move> GetLegalMoves(Piece piece)
return PlayLegalMoves().Where(b => b.Counters.LastMove.Piece == piece).Select(b => b.Counters.LastMove);
}

public IEnumerable<IBoard> PlayLegalMoves()
public IEnumerable<IBoard> PlayLegalMoves(bool onlyCaptures = false)
{
foreach (var piece in activeBoard.GetPieces())
{
foreach (var board in PlayLegalMoves(piece))
foreach (var board in PlayLegalMoves(piece, onlyCaptures))
{
yield return board;
}
}
}

private IEnumerable<IBoard> PlayLegalMoves(Piece piece)
private IEnumerable<IBoard> PlayLegalMoves(Piece piece, bool onlyCaptures)
{
foreach (var vector in internals.Moves.GetVectors(piece))
{
Expand All @@ -306,9 +344,14 @@ private IEnumerable<IBoard> PlayLegalMoves(Piece piece)
break;
}

var hostileTarget = opponentBoard.Peek(move.Target);
var taking = opponentBoard.IsOccupied(move.Target);

if (!taking && onlyCaptures)
{
continue;
}

if (!ValidateMove(move, hostileTarget))
if (!ValidateMove(move, taking))
{
break;
}
Expand All @@ -318,7 +361,7 @@ private IEnumerable<IBoard> PlayLegalMoves(Piece piece)
// Moving into check?
if (board.IsAttacked(board.FindKing(ActiveColor)))
{
if (hostileTarget != Piece.None)
if (taking)
{
break;
}
Expand All @@ -328,31 +371,21 @@ private IEnumerable<IBoard> PlayLegalMoves(Piece piece)

yield return board;

if (hostileTarget != Piece.None)
if (taking)
{
break;
}
}
}
}

private bool ValidateMove(Move move, Piece hostileTarget)
private bool ValidateMove(Move move, bool taking)
{
if (move.Piece.Is(Piece.Pawn))
{
if (hostileTarget == Piece.None)
if ((taking && move.Flags.HasFlag(SpecialMove.PawnMoves)) || (!taking && move.Flags.HasFlag(SpecialMove.PawnTakes)))
{
if (move.Flags.HasFlag(SpecialMove.PawnTakes))
{
return false;
}
}
else
{
if (move.Flags.HasFlag(SpecialMove.PawnMoves))
{
return false;
}
return false;
}

if (move.Flags.HasFlag(SpecialMove.PawnTakesEnPassant) && move.Target != Counters.EnPassantTarget)
Expand Down
2 changes: 1 addition & 1 deletion Common/Interfaces/IBoard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public interface IBoard

IBoard Play(Move move);

IEnumerable<IBoard> PlayLegalMoves();
IEnumerable<IBoard> PlayLegalMoves(bool onlyCaptures = false);

IEnumerable<Move> GetLegalMoves();

Expand Down
2 changes: 1 addition & 1 deletion Common/Interfaces/IEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public interface IEngine

void Position(string fen, IEnumerable<AlgebraicMove>? algebraicMoves = null);

AlgebraicMove FindBestMove(int timeLimit = 1000);
AlgebraicMove? FindBestMove(int timeLimit = 1000);

void Perft(int depth);
}
Expand Down
6 changes: 4 additions & 2 deletions Common/Lookup/Scoring.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ public class Scoring
private readonly Dictionary<Piece, int> middleGameEvaluations = new();
private readonly Dictionary<Piece, int> endGameEvaluations = new();

public const int DrawScore = 0;
public const int MateScore = 1000000;
public const int MoveMaximumScore = MateScore * 2;

private static readonly int[] PawnMiddleGameModifiers =
{
0, 0, 0, 0, 0, 0, 0, 0,
Expand Down Expand Up @@ -203,8 +207,6 @@ private static void InitializeEvaluations(Dictionary<Piece, int> evaluations, bo

public int EvaluatePiece(Piece piece, int phase)
{
// TODO: This will not handle promotions.

var end = endGameEvaluations[piece] * (24 - phase);
var middle = middleGameEvaluations[piece] * phase;

Expand Down
2 changes: 2 additions & 0 deletions Common/Lookup/ThreatMasks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public class ThreatMasks
public ulong Bishop { get; }
public ulong Queen { get; }
public ulong King { get; }
public ulong All { get; }

public ThreatMasks(ulong pawn, ulong rook, ulong knight, ulong bishop, ulong queen, ulong king)
{
Expand All @@ -17,6 +18,7 @@ public ThreatMasks(ulong pawn, ulong rook, ulong knight, ulong bishop, ulong que
Bishop = bishop;
Queen = queen;
King = king;
All = pawn | rook | knight | bishop | queen | king;
}
}
}
10 changes: 10 additions & 0 deletions Engine/Enum/EntryType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace SicTransit.Woodpusher.Engine.Enum
{
internal enum EntryType
{
None,
UpperBound,
LowerBound,
Exact,
}
}
6 changes: 2 additions & 4 deletions Engine/Extensions/MathExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
public static class MathExtensions
{
public static int ApproximateNextDepthTime(List<(int depth, long time)> progress)
public static int ApproximateNextDepthTime(List<(int depth, long time)> progress, int nextDepth)
{
int n = progress.Count;

Expand Down Expand Up @@ -30,9 +30,7 @@ public static int ApproximateNextDepthTime(List<(int depth, long time)> progress
// Convert ln(a) back to a
double a = Math.Exp(lnA);

int maxX = progress.Max(p => p.depth);

return (int)(a * Math.Exp(b * (maxX + 2)));
return (int)(a * Math.Exp(b * (nextDepth)));
}
}
}
Loading

0 comments on commit 6fb539e

Please sign in to comment.