Skip to content
8 changes: 4 additions & 4 deletions src/Lynx.Benchmark/MoveGenerator_SpanUnsafeAdd_Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -822,10 +822,10 @@ private static bool IsAnyKingMoveValid(int piece, Position position, ref Evaluat
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsValidMove(Position position, Move move)
{
var gameState = position.MakeMove(move);
position.MakeMove(move);

bool result = position.WasProduceByAValidMove();
position.UnmakeMove(move, gameState);
position.UnmakeMove(move);

return result;
}
Expand Down Expand Up @@ -1499,10 +1499,10 @@ private static bool IsAnyKingMoveValid(int piece, Position position, ref Evaluat
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsValidMove(Position position, Move move)
{
var gameState = position.MakeMove(move);
position.MakeMove(move);

bool result = position.WasProduceByAValidMove();
position.UnmakeMove(move, gameState);
position.UnmakeMove(move);

return result;
}
Expand Down
24 changes: 9 additions & 15 deletions src/Lynx.Benchmark/ParseGame_Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,9 @@ internal OriginalGame(string fen, string[] movesUCIString) : this(fen)
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public GameState MakeMove(Move moveToPlay)
public void MakeMove(Move moveToPlay)
{
var gameState = CurrentPosition.MakeMove(moveToPlay);
CurrentPosition.MakeMove(moveToPlay);

if (CurrentPosition.WasProduceByAValidMove())
{
Expand All @@ -538,13 +538,11 @@ public GameState MakeMove(Move moveToPlay)
else
{
_logger.Warn("Error trying to play {0}", moveToPlay.UCIString());
CurrentPosition.UnmakeMove(moveToPlay, gameState);
CurrentPosition.UnmakeMove(moveToPlay);
}

PositionHashHistory.Add(CurrentPosition.UniqueIdentifier);
HalfMovesWithoutCaptureOrPawnMove = Utils.Update50movesRule(moveToPlay, HalfMovesWithoutCaptureOrPawnMove);

return gameState;
}
}

Expand Down Expand Up @@ -608,9 +606,9 @@ internal ImprovedGame(string fen, ReadOnlySpan<char> rawMoves, Span<Range> range
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public GameState MakeMove(Move moveToPlay)
public void MakeMove(Move moveToPlay)
{
var gameState = CurrentPosition.MakeMove(moveToPlay);
CurrentPosition.MakeMove(moveToPlay);

if (CurrentPosition.WasProduceByAValidMove())
{
Expand All @@ -621,13 +619,11 @@ public GameState MakeMove(Move moveToPlay)
else
{
_logger.Warn("Error trying to play {0}", moveToPlay.UCIString());
CurrentPosition.UnmakeMove(moveToPlay, gameState);
CurrentPosition.UnmakeMove(moveToPlay);
}

PositionHashHistory.Add(CurrentPosition.UniqueIdentifier);
HalfMovesWithoutCaptureOrPawnMove = Utils.Update50movesRule(moveToPlay, HalfMovesWithoutCaptureOrPawnMove);

return gameState;
}
}

Expand Down Expand Up @@ -695,9 +691,9 @@ public ImprovedGame2(ReadOnlySpan<char> fen, ReadOnlySpan<char> rawMoves, Span<R
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public GameState MakeMove(Move moveToPlay)
public void MakeMove(Move moveToPlay)
{
var gameState = CurrentPosition.MakeMove(moveToPlay);
CurrentPosition.MakeMove(moveToPlay);

if (CurrentPosition.WasProduceByAValidMove())
{
Expand All @@ -708,13 +704,11 @@ public GameState MakeMove(Move moveToPlay)
else
{
_logger.Warn("Error trying to play {0}", moveToPlay.UCIString());
CurrentPosition.UnmakeMove(moveToPlay, gameState);
CurrentPosition.UnmakeMove(moveToPlay);
}

PositionHashHistory.Add(CurrentPosition.UniqueIdentifier);
HalfMovesWithoutCaptureOrPawnMove = Utils.Update50movesRule(moveToPlay, HalfMovesWithoutCaptureOrPawnMove);

return gameState;
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/Lynx.Benchmark/TryParseFromUCIString_Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,11 @@ public TryParseFromUCIString_Benchmark_Game(ReadOnlySpan<char> fen, ReadOnlySpan

_gameInitialPosition = new Position(CurrentPosition);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public GameState MakeMove(Move moveToPlay)
public void MakeMove(Move moveToPlay)
{
var gameState = CurrentPosition.MakeMove(moveToPlay);
CurrentPosition.MakeMove(moveToPlay);

if (CurrentPosition.WasProduceByAValidMove())
{
Expand All @@ -246,13 +247,11 @@ public GameState MakeMove(Move moveToPlay)
else
{
_logger.Warn("Error trying to play {0}", moveToPlay.UCIString());
CurrentPosition.UnmakeMove(moveToPlay, gameState);
CurrentPosition.UnmakeMove(moveToPlay);
}

PositionHashHistory.Add(CurrentPosition.UniqueIdentifier);
HalfMovesWithoutCaptureOrPawnMove = Utils.Update50movesRule(moveToPlay, HalfMovesWithoutCaptureOrPawnMove);

return gameState;
}
}
}
12 changes: 6 additions & 6 deletions src/Lynx.Dev/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ static void GeneralMoveTest(Game game)
game.CurrentPosition.Print();

Console.WriteLine(move.ToEPDString(game.CurrentPosition));
var gameState = game.MakeMove(move);
game.MakeMove(move);
game.CurrentPosition.Print();

Console.WriteLine("White occupancy:");
Expand All @@ -538,7 +538,7 @@ static void GeneralMoveTest(Game game)
Console.WriteLine("Black occupancy:");
game.CurrentPosition.OccupancyBitBoards[(int)Side.Black].Print();

game.CurrentPosition.UnmakeMove(move, gameState);
game.CurrentPosition.UnmakeMove(move);
}
}

Expand All @@ -552,9 +552,9 @@ static void CastlingRightsTest(Game game)
game.CurrentPosition.Print();

Console.WriteLine(move.ToEPDString(game.CurrentPosition));
var gameState = game.MakeMove(move);
game.MakeMove(move);
game.CurrentPosition.Print();
game.CurrentPosition.UnmakeMove(move, gameState);
game.CurrentPosition.UnmakeMove(move);
}
}
}
Expand Down Expand Up @@ -1118,14 +1118,14 @@ static void TestMoveGen(string fen)

var newPosition = new Position(position);
newPosition.MakeMove(move);
var savedState = position.MakeMove(move);
position.MakeMove(move);

Console.WriteLine($"Position\t{newPosition.FEN()}, Zobrist key {newPosition.UniqueIdentifier}");
Console.WriteLine($"Position\t{position.FEN()}, Zobrist key {position.UniqueIdentifier}");

Console.WriteLine($"Unmaking {epdMoveString} in\t{position.FEN()}");

//position.UnmakeMove(move, savedState);
//position.UnmakeMove(move);

Console.WriteLine($"Position\t{position.FEN()}, Zobrist key {position.UniqueIdentifier}");

Expand Down
1 change: 1 addition & 0 deletions src/Lynx/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ public SearchResult BestMove(in SearchConstraints searchConstrains, bool isPonde
SearchResult resultToReturn = IDDFS(isPondering, jointCts.Token);
//SearchResult resultToReturn = await SearchBestMove(maxDepth, decisionTime);

// This is done to allow sending consecutive search commands
Game.ResetCurrentPositionToBeforeSearchState();
if (!isPondering
&& resultToReturn.BestMove != default
Expand Down
48 changes: 24 additions & 24 deletions src/Lynx/Evaluation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,16 @@ public partial class Position
int blackPawnKingRingAttacks = (blackPawnAttacks & KingRing[whiteKing]).CountBits();
evaluationContext.IncreaseKingRingAttacks((int)Side.Black, blackPawnKingRingAttacks);

if (IsIncrementalEval)
if (_state.IsIncrementalEval)
{
packedScore = IncrementalEvalAccumulator;
gamePhase = IncrementalPhaseAccumulator;
packedScore = _state.IncrementalEvalAccumulator;
gamePhase = _state.IncrementalPhaseAccumulator;

var kingPawnIndex = _kingPawnUniqueIdentifier & Constants.KingPawnHashMask;
var kingPawnIndex = _state.KingPawnUniqueIdentifier & Constants.KingPawnHashMask;
ref var entry = ref pawnEvalTable[kingPawnIndex];

// pawnEvalTable hit: We can reuse cached eval for pawn additional evaluation + PieceProtectedByPawnBonus + KingShieldBonus
if (entry.Key == _kingPawnUniqueIdentifier)
if (entry.Key == _state.KingPawnUniqueIdentifier)
{
packedScore += entry.PackedScore;
}
Expand Down Expand Up @@ -152,7 +152,7 @@ public partial class Position
// Pawn islands
pawnScore += PawnIslands(whitePawns, blackPawns);

entry.Update(_kingPawnUniqueIdentifier, pawnScore);
entry.Update(_state.KingPawnUniqueIdentifier, pawnScore);
packedScore += pawnScore;
}

Expand Down Expand Up @@ -191,14 +191,14 @@ public partial class Position
}
else
{
IncrementalEvalAccumulator = 0;
IncrementalPhaseAccumulator = 0;
_state.IncrementalEvalAccumulator = 0;
_state.IncrementalPhaseAccumulator = 0;

var kingPawnIndex = _kingPawnUniqueIdentifier & Constants.KingPawnHashMask;
var kingPawnIndex = _state.KingPawnUniqueIdentifier & Constants.KingPawnHashMask;
ref var entry = ref pawnEvalTable[kingPawnIndex];

// pawnTable hit: We can reuse cached eval for pawn additional evaluation + PieceProtectedByPawnBonus + KingShieldBonus
if (entry.Key == _kingPawnUniqueIdentifier)
if (entry.Key == _state.KingPawnUniqueIdentifier)
{
packedScore += entry.PackedScore;

Expand All @@ -211,7 +211,7 @@ public partial class Position
{
whitePawnsCopy = whitePawnsCopy.WithoutLS1B(out var pieceSquareIndex);

IncrementalEvalAccumulator += PSQT(whiteBucket, blackBucket, (int)Piece.P, pieceSquareIndex);
_state.IncrementalEvalAccumulator += PSQT(whiteBucket, blackBucket, (int)Piece.P, pieceSquareIndex);

// No incremental eval - included in pawn table | packedScore += AdditionalPieceEvaluation(...);
}
Expand All @@ -225,7 +225,7 @@ public partial class Position
{
blackPawnsCopy = blackPawnsCopy.WithoutLS1B(out var pieceSquareIndex);

IncrementalEvalAccumulator += PSQT(blackBucket, whiteBucket, (int)Piece.p, pieceSquareIndex);
_state.IncrementalEvalAccumulator += PSQT(blackBucket, whiteBucket, (int)Piece.p, pieceSquareIndex);

// No incremental eval - included in pawn table | packedScore -= AdditionalPieceEvaluation(...);
}
Expand All @@ -249,7 +249,7 @@ public partial class Position
{
whitePawnsCopy = whitePawnsCopy.WithoutLS1B(out var pieceSquareIndex);

IncrementalEvalAccumulator += PSQT(whiteBucket, blackBucket, (int)Piece.P, pieceSquareIndex);
_state.IncrementalEvalAccumulator += PSQT(whiteBucket, blackBucket, (int)Piece.P, pieceSquareIndex);

pawnScore += PawnAdditionalEvaluation(ref evaluationContext, whiteBucket, blackBucket, pieceSquareIndex, (int)Piece.P, whiteKing, blackKing);
}
Expand All @@ -268,15 +268,15 @@ public partial class Position
{
blackPawnsCopy = blackPawnsCopy.WithoutLS1B(out var pieceSquareIndex);

IncrementalEvalAccumulator += PSQT(blackBucket, whiteBucket, (int)Piece.p, pieceSquareIndex);
_state.IncrementalEvalAccumulator += PSQT(blackBucket, whiteBucket, (int)Piece.p, pieceSquareIndex);

pawnScore -= PawnAdditionalEvaluation(ref evaluationContext, blackBucket, whiteBucket, pieceSquareIndex, (int)Piece.p, blackKing, whiteKing);
}

// Pawn islands
pawnScore += PawnIslands(whitePawns, blackPawns);

entry.Update(_kingPawnUniqueIdentifier, pawnScore);
entry.Update(_state.KingPawnUniqueIdentifier, pawnScore);
packedScore += pawnScore;
}

Expand All @@ -292,9 +292,9 @@ public partial class Position
{
bitboard = bitboard.WithoutLS1B(out var pieceSquareIndex);

IncrementalEvalAccumulator += PSQT(whiteBucket, blackBucket, pieceIndex, pieceSquareIndex);
_state.IncrementalEvalAccumulator += PSQT(whiteBucket, blackBucket, pieceIndex, pieceSquareIndex);

IncrementalPhaseAccumulator += GamePhaseByPiece[pieceIndex];
_state.IncrementalPhaseAccumulator += GamePhaseByPiece[pieceIndex];

packedScore += AdditionalPieceEvaluation(ref evaluationContext, pieceSquareIndex, whiteBucket, blackBucket, pieceIndex, (int)Side.White, blackPawnAttacks, blackKing);
}
Expand All @@ -313,17 +313,17 @@ public partial class Position
{
bitboard = bitboard.WithoutLS1B(out var pieceSquareIndex);

IncrementalEvalAccumulator += PSQT(blackBucket, whiteBucket, pieceIndex, pieceSquareIndex);
_state.IncrementalEvalAccumulator += PSQT(blackBucket, whiteBucket, pieceIndex, pieceSquareIndex);

IncrementalPhaseAccumulator += GamePhaseByPiece[pieceIndex];
_state.IncrementalPhaseAccumulator += GamePhaseByPiece[pieceIndex];

packedScore -= AdditionalPieceEvaluation(ref evaluationContext, pieceSquareIndex, blackBucket, whiteBucket, pieceIndex, (int)Side.Black, whitePawnAttacks, whiteKing);
}
}

packedScore += IncrementalEvalAccumulator;
gamePhase += IncrementalPhaseAccumulator;
IsIncrementalEval = true;
packedScore += _state.IncrementalEvalAccumulator;
gamePhase += _state.IncrementalPhaseAccumulator;
_state.IsIncrementalEval = true;
}

// Kings - they can't be incremental due to the king buckets
Expand Down Expand Up @@ -519,8 +519,8 @@ public partial class Position
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Phase()
{
var gamePhase = IsIncrementalEval
? IncrementalPhaseAccumulator
var gamePhase = _state.IsIncrementalEval
? _state.IncrementalPhaseAccumulator
: PhaseFromScratch();

return (gamePhase > MaxPhase) // Early promotions
Expand Down
11 changes: 4 additions & 7 deletions src/Lynx/Model/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ public void ParsePositionCommand(ReadOnlySpan<char> positionCommandSpan)
{
try
{

// We divide the position command in these two sections:
// "position startpos ||"
// "position startpos || moves e2e4 e7e5"
Expand Down Expand Up @@ -266,9 +265,9 @@ public static bool IsThreefoldRepetition(ReadOnlySpan<ulong> positionHashHistory
public static bool Is50MovesRepetition(int halfMovesWithoutCaptureOrPawnMove) => halfMovesWithoutCaptureOrPawnMove >= 100;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public GameState MakeMove(Move moveToPlay)
public void MakeMove(Move moveToPlay)
{
var gameState = CurrentPosition.MakeMove(moveToPlay);
CurrentPosition.MakeMove(moveToPlay);

if (CurrentPosition.WasProduceByAValidMove())
{
Expand All @@ -280,17 +279,15 @@ public GameState MakeMove(Move moveToPlay)
}
else
{
CurrentPosition.UnmakeMove(moveToPlay, gameState);
CurrentPosition.UnmakeMove(moveToPlay);
_logger.Warn("Error trying to play move {0} in {1}", moveToPlay.UCIString(), CurrentPosition.FEN(HalfMovesWithoutCaptureOrPawnMove));
}

return gameState;
}

/// <summary>
/// Cleans <see cref="CurrentPosition"/> value, since in case of search cancellation
/// (either by the engine time management logic or by external stop command)
/// currentPosition won't be the initial one
/// currentPosition won't be the initial one.
/// </summary>
public void ResetCurrentPositionToBeforeSearchState()
{
Expand Down
Loading
Loading