Skip to content

Commit

Permalink
optz: don't sort entire move list
Browse files Browse the repository at this point in the history
branching factor is slowly going down and we are getting faster cut-offs, we won't need to always sort the entire move list soon
  • Loading branch information
znxftw committed Dec 27, 2024
1 parent 2b4dd8a commit 4b57cb0
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 25 deletions.
35 changes: 26 additions & 9 deletions Rudim.Test/UnitTest/Board/MoveOrderingTest.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,42 @@
using Rudim.Board;
using Rudim.Common;
using System.Collections.Generic;
using Xunit;

namespace Rudim.Test.UnitTest.Board
{
public class MoveOrderingTest
{
[Fact]
public void ShouldOrderMovesByScore()
public void ShouldSortMovesByScore()
{
BoardState boardState = BoardState.ParseFEN(Helpers.KiwiPeteFEN);
List<Move> moves = new()
{
new Move(Square.e2, Square.e4, MoveTypes.Quiet) { Score = 100 },
new Move(Square.d2, Square.d4, MoveTypes.Quiet) { Score = 300 },
new Move(Square.g1, Square.f3, MoveTypes.Quiet) { Score = 200 }
};

MoveOrdering.SortNextBestMove(moves, 0);

Assert.Equal(300, moves[0].Score);
}

boardState.GenerateMoves();
foreach (Move move in boardState.Moves)
[Fact]
public void ShouldNotChangeOrderIfAlreadySorted()
{
List<Move> moves = new()
{
MoveOrdering.PopulateMoveScore(move, boardState);
}
MoveOrdering.SortMoves(boardState);
new Move(Square.d2, Square.d4, MoveTypes.Quiet) { Score = 300 },
new Move(Square.g1, Square.f3, MoveTypes.Quiet) { Score = 200 },
new Move(Square.e2, Square.e4, MoveTypes.Quiet) { Score = 100 }
};

MoveOrdering.SortNextBestMove(moves, 1);

// TODO: Improve assertions, verify proper order as per MVV LVA
Assert.True(boardState.Moves[0].IsCapture());
Assert.Equal(300, moves[0].Score);
Assert.Equal(200, moves[1].Score);
Assert.Equal(100, moves[2].Score);
}
}
}
8 changes: 4 additions & 4 deletions Rudim.Test/UnitTest/Board/TraversalTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ public class TraversalTest
// This helps keep track if certain optimizations are good enough to make up for the extra time spent
// Compare time spent with and without the change before updating the keys
[Theory]
[InlineData(Helpers.StartingFEN, 475558, 7, 8)]
[InlineData(Helpers.EndgameFEN, 151145, 36, 9)]
[InlineData(Helpers.AdvancedMoveFEN, 1928455, 1750, 8)]
[InlineData(Helpers.KiwiPeteFEN, 3739155, -42, 8)]
[InlineData(Helpers.StartingFEN, 544945, 7, 8)]
[InlineData(Helpers.EndgameFEN, 152549, 36, 9)]
[InlineData(Helpers.AdvancedMoveFEN, 1381346, 1750, 8)]
[InlineData(Helpers.KiwiPeteFEN, 3524492, -42, 8)]
public void ShouldTraverseDeterministically(string position, int expectedNodes, int expectedScore, int depth)
{
Global.Reset();
Expand Down
19 changes: 13 additions & 6 deletions Rudim/Board/MoveOrdering.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,6 @@ public static void AddHistoryMove(int piece, Move move, int depth)
_historyMoves[piece, (int)move.Target] += depth * depth;
}

public static void SortMoves(BoardState boardState)
{
// TODO : Partially sort within the loop only to avoid sorting elements that are not going to be queried after beta cutoff?
boardState.Moves.Sort((a, b) => b.Score.CompareTo(a.Score));
}

public static void ResetMoveHeuristic()
{
_killerMoves = new Move[Constants.Sides, Constants.MaxPly];
Expand All @@ -84,5 +78,18 @@ public static void PopulateHashMove(Move move)
{
move.Score = 10_500;
}

public static void SortNextBestMove(List<Move> moves, int startingIndex)
{
int bestIndex = startingIndex;
for (int i = startingIndex + 1; i < moves.Count; ++i)
{
if (moves[i].Score >= moves[bestIndex].Score)
bestIndex = i;
}

if(bestIndex != startingIndex)
(moves[bestIndex], moves[startingIndex]) = (moves[startingIndex], moves[bestIndex]);
}
}
}
7 changes: 5 additions & 2 deletions Rudim/Search/Negamax.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Rudim.Board;
using Rudim.Common;
using System.Collections.Generic;
using System.Threading;

namespace Rudim.Search
Expand Down Expand Up @@ -53,11 +54,13 @@ private static int Search(BoardState boardState, int depth, int alpha, int beta,

boardState.GenerateMoves();
PopulateMoveScores(boardState, ply);
MoveOrdering.SortMoves(boardState);

int numberOfLegalMoves = 0;
foreach (Move move in boardState.Moves)
List<Move> moves = boardState.Moves;
for(int i = 0; i < moves.Count; ++i)
{
MoveOrdering.SortNextBestMove(moves, i);
Move move = moves[i];
if (cancellationToken.IsCancellationRequested)
break;
boardState.MakeMove(move);
Expand Down
10 changes: 6 additions & 4 deletions Rudim/Search/Quiescence.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Rudim.Board;
using Rudim.Common;
using System.Collections.Generic;
using System.Threading;

namespace Rudim.Search
Expand All @@ -26,11 +27,12 @@ public static int Search(BoardState boardState, int alpha, int beta, Cancellatio
{
MoveOrdering.PopulateMoveScore(move, boardState);
}
MoveOrdering.SortMoves(boardState);


foreach (var move in boardState.Moves)
List<Move> moves = boardState.Moves;

for(int i = 0; i < moves.Count; ++i)
{
MoveOrdering.SortNextBestMove(moves, i);
Move move = moves[i];
if (cancellationToken.IsCancellationRequested)
break;
if (!move.IsCapture())
Expand Down

0 comments on commit 4b57cb0

Please sign in to comment.