diff --git a/BoardAnalysis.cs b/BoardAnalysis.cs
index ec1ae55..98be9f7 100644
--- a/BoardAnalysis.cs
+++ b/BoardAnalysis.cs
@@ -9,6 +9,8 @@ namespace Shogi
{
public static class BoardAnalysis
{
+ private static readonly Random rng = new();
+
///
/// Determine whether a king can be reached by any of the opponents pieces
///
@@ -270,9 +272,10 @@ public PossibleMove(Point source, Point destination, double evaluatedFutureValue
/// Use to find the best possible move in the current state of the game
///
/// The maximum number of half-moves in the future to search
- public static async Task EstimateBestPossibleMove(ShogiGame game, int maxDepth, CancellationToken cancellationToken)
+ /// Whether or not to randomise the order of moves that have the same score
+ public static async Task EstimateBestPossibleMove(ShogiGame game, int maxDepth, bool randomise, CancellationToken cancellationToken)
{
- PossibleMove[] moves = await EvaluatePossibleMoves(game, maxDepth, cancellationToken);
+ PossibleMove[] moves = await EvaluatePossibleMoves(game, maxDepth, randomise, cancellationToken);
PossibleMove bestMove = new(default, default,
game.CurrentTurnSente ? double.NegativeInfinity : double.PositiveInfinity, false, false, 0, 0, false, new());
foreach (PossibleMove potentialMove in moves)
@@ -311,8 +314,9 @@ public static async Task EstimateBestPossibleMove(ShogiGame game,
/// Evaluate each possible move in the current state of the game
///
/// The maximum number of half-moves in the future to search
+ /// Whether or not to randomise the order of moves that have the same score
/// An array of all possible moves, with information on board value and ability to checkmate
- public static async Task EvaluatePossibleMoves(ShogiGame game, int maxDepth, CancellationToken cancellationToken)
+ public static async Task EvaluatePossibleMoves(ShogiGame game, int maxDepth, bool randomise, CancellationToken cancellationToken)
{
List> evaluationTasks = new();
@@ -410,8 +414,14 @@ public static async Task EvaluatePossibleMoves(ShogiGame game, i
}
try
{
+ IEnumerable moves =
+ (await Task.WhenAll(evaluationTasks)).Where(m => m.Source != m.Destination);
+ if (randomise)
+ {
+ return moves.OrderBy(_ => rng.Next()).ToArray();
+ }
// Remove default moves from return value
- return (await Task.WhenAll(evaluationTasks)).Where(m => m.Source != m.Destination).ToArray();
+ return moves.ToArray();
}
catch (TaskCanceledException)
{
diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs
index dc6b9aa..044499e 100644
--- a/MainWindow.xaml.cs
+++ b/MainWindow.xaml.cs
@@ -534,7 +534,7 @@ private void UpdateEvaluationMeter(BoardAnalysis.PossibleMove? bestMove, bool se
{
BoardAnalysis.PossibleMove? bestMove = null;
// Search deeper in minishogi games
- bestMove ??= await BoardAnalysis.EstimateBestPossibleMove(game, game.Board.GetLength(0) == 5 ? 4 : 3, cancellationToken);
+ bestMove ??= await BoardAnalysis.EstimateBestPossibleMove(game, game.Board.GetLength(0) == 5 ? 4 : 3, true, cancellationToken);
return bestMove.Value;
}