/// <summary> /// Start a new game from the specified FEN string position. For internal use only. /// </summary> /// <param name="fenString"> The str fen. </param> private static void NewInternal(string fenString) { if (fenString == string.Empty) { if (!Is960) { fenString = Fen.GameStartPosition; } else { fenString = Fen.GameStartPosition960; } } Fen.Validate(fenString); HashTable.Clear(); HashTablePawn.Clear(); HashTableCheck.Clear(); KillerMoves.Clear(); HistoryHeuristic.Clear(); UndoAllMovesInternal(); MoveRedoList.Clear(); saveGameFileName = string.Empty; Fen.SetBoardPosition(fenString); PlayerWhite.Clock.Reset(); PlayerBlack.Clock.Reset(); }
public void SameKillerMoveWithHigherScoreReplacesSlotEntry() { const int Ply = 10; KillerMoves.Clear(); Piece piece = new Piece(); PiecePawn piecePawn = new PiecePawn(piece); piece.Top = piecePawn; Move move1 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(0), Board.GetSquare(1), null, 0, 20); // Add a move KillerMoves.RecordPossibleKillerMove(Ply, move1); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move1); Assert.IsTrue(KillerMoves.RetrieveA(Ply).Score == 20); Assert.IsNull(KillerMoves.RetrieveB(Ply)); // Add same move AGAIN, but with higher score. Move should be replaced, using higher score. Move move2 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(0), Board.GetSquare(1), null, 0, 30); KillerMoves.RecordPossibleKillerMove(Ply, move2); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move2); Assert.IsTrue(KillerMoves.RetrieveA(Ply).Score == 30); Assert.IsNull(KillerMoves.RetrieveB(Ply)); // Add same move AGAIN, but with LOWER score. No killer moves should be changed Move move3 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(0), Board.GetSquare(1), null, 0, 10); KillerMoves.RecordPossibleKillerMove(Ply, move3); Assert.IsTrue(Move.MovesMatch(KillerMoves.RetrieveA(Ply), move2)); Assert.IsTrue(KillerMoves.RetrieveA(Ply).Score == 30); Assert.IsNull(KillerMoves.RetrieveB(Ply)); // Now add a different move, and check it goes in slot B Move move4 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(2), Board.GetSquare(3), null, 0, 5); KillerMoves.RecordPossibleKillerMove(Ply, move4); Assert.IsTrue(Move.MovesMatch(KillerMoves.RetrieveA(Ply), move3)); Assert.IsTrue(KillerMoves.RetrieveA(Ply).Score == 30); Assert.IsTrue(Move.MovesMatch(KillerMoves.RetrieveB(Ply), move4)); Assert.IsTrue(KillerMoves.RetrieveB(Ply).Score == 5); // Now improve score of the move that is in slot B. // Slot B's score should be updated. Slot A should stay the same. // Slot's A & B should be SWAPPED. Move move5 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(2), Board.GetSquare(3), null, 0, 100); KillerMoves.RecordPossibleKillerMove(Ply, move5); Assert.IsTrue(Move.MovesMatch(KillerMoves.RetrieveA(Ply), move5)); Assert.IsTrue(KillerMoves.RetrieveA(Ply).Score == 100); Assert.IsTrue(Move.MovesMatch(KillerMoves.RetrieveB(Ply), move3)); Assert.IsTrue(KillerMoves.RetrieveB(Ply).Score == 30); }
public void Optimize(int Iterations) { // Determine size of parameter space. var parameterSpace = 1d; var firstParticleInFirstSwarm = this[0].Particles[0]; for (var index = 0; index < firstParticleInFirstSwarm.Parameters.Count; index++) { var parameter = firstParticleInFirstSwarm.Parameters[index]; parameterSpace *= parameter.MaxValue - parameter.MinValue + 1; } _writeMessageLine($"Optimizing {firstParticleInFirstSwarm.Parameters.Count} parameters in a space of {parameterSpace:e2} discrete parameter combinations."); // Create game objects for each particle swarm. var boards = new Board[Count]; var searches = new Search[Count]; var evaluations = new Evaluation[Count]; for (var index = 0; index < Count; index++) { var board = new Board(_writeMessageLine); boards[index] = board; var cache = new Cache(1, board.ValidateMove); var killerMoves = new KillerMoves(Search.MaxHorizon); var moveHistory = new MoveHistory(); var evaluation = new Evaluation(board.IsRepeatPosition, () => false, _writeMessageLine); evaluations[index] = evaluation; searches[index] = new Search(cache, killerMoves, moveHistory, evaluation, () => false, _writeMessageLine); } var tasks = new Task[Count]; var bestEvaluationError = double.MaxValue; for (var iteration = 1; iteration <= Iterations; iteration++) { // Run iteration tasks on threadpool. _iterations = iteration; for (var index = 0; index < Count; index++) { var particleSwarm = this[index]; var board = boards[index]; var search = searches[index]; var evaluation = evaluations[index]; tasks[index] = Task.Run(() => particleSwarm.Iterate(board, search, evaluation)); } // Wait for all particle swarms to complete an iteration. Task.WaitAll(tasks); var bestParticle = GetBestParticle(); if (bestParticle.EvaluationError < bestEvaluationError) { bestEvaluationError = bestParticle.BestEvaluationError; } UpdateVelocity(); UpdateStatus(); } }
public ParticleSwarms(string pgnFilename, int particleSwarms, int particlesPerSwarm, int winScale, Delegates.DisplayStats displayStats, Core.Delegates.WriteMessageLine writeMessageLine) { _displayStats = displayStats; _writeMessageLine = writeMessageLine; // Load games. writeMessageLine("Loading games."); var stopwatch = new Stopwatch(); stopwatch.Start(); var board = new Board(writeMessageLine, UciStream.NodesInfoInterval); var pgnGames = new PgnGames(); pgnGames.Load(board, pgnFilename, writeMessageLine); stopwatch.Stop(); // Count positions. long positions = 0; for (var gameIndex = 0; gameIndex < pgnGames.Count; gameIndex++) { var pgnGame = pgnGames[gameIndex]; positions += pgnGame.Moves.Count; } var positionsPerSecond = (int)(positions / stopwatch.Elapsed.TotalSeconds); writeMessageLine($"Loaded {pgnGames.Count:n0} games with {positions:n0} positions in {stopwatch.Elapsed.TotalSeconds:0.000} seconds ({positionsPerSecond:n0} positions per second)."); stopwatch.Restart(); writeMessageLine("Creating data structures."); // Create parameters and particle swarms. var parameters = CreateParameters(); for (var particleSwarmsIndex = 0; particleSwarmsIndex < particleSwarms; particleSwarmsIndex++) { var particleSwarm = new ParticleSwarm(pgnGames, parameters, particlesPerSwarm, winScale); Add(particleSwarm); // Set parameter values of all particles in swarm to known best. for (var particleIndex = 0; particleIndex < particleSwarm.Particles.Count; particleIndex++) { SetDefaultParameters(particleSwarm.Particles[particleIndex].Parameters); } } var stats = new Stats(); var cache = new Cache(1, stats, board.ValidateMove); var killerMoves = new KillerMoves(Search.MaxHorizon); var moveHistory = new MoveHistory(); var eval = new Eval(stats, board.IsRepeatPosition, () => false, writeMessageLine); var search = new Search(stats, cache, killerMoves, moveHistory, eval, () => false, displayStats, writeMessageLine); var firstParticleInFirstSwarm = this[0].Particles[0]; firstParticleInFirstSwarm.CalculateEvaluationError(board, search, winScale); _originalEvaluationError = firstParticleInFirstSwarm.EvaluationError; stopwatch.Stop(); writeMessageLine($"Created data structures in {stopwatch.Elapsed.TotalSeconds:0.000} seconds."); }
public PVSearch(ArtemisEngine engine, GameState gameState, TranspositionTable transpositionTable, KillerMoves killerMoves, PositionEvaluator evaluator, MoveEvaluator moveEvaluator, QuiescenceSearch quietSearch, ConcurrentDictionary <ulong, bool> searchedNodes, IEngineConfig config) { this.engine = engine; this.gameState = gameState; this.transpositionTable = transpositionTable; this.killerMoves = killerMoves; this.evaluator = evaluator; this.moveEvaluator = moveEvaluator; this.quietSearch = quietSearch; this.searchedNodes = searchedNodes; this.config = config; }
public void RecordPossibleKillerMoveTest() { int Ply = 10; KillerMoves.Clear(); Piece piece = new Piece(); PiecePawn piecePawn = new PiecePawn(piece); piece.Top = piecePawn; Move move1 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(0), Board.GetSquare(1), null, 0, 20); KillerMoves.RecordPossibleKillerMove(Ply, move1); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move1); Assert.IsNull(KillerMoves.RetrieveB(Ply)); Move move2 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(2), Board.GetSquare(3), null, 0, 10); KillerMoves.RecordPossibleKillerMove(Ply, move2); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move1); Assert.IsTrue(KillerMoves.RetrieveB(Ply) == move2); Move move3 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(4), Board.GetSquare(5), null, 0, 15); KillerMoves.RecordPossibleKillerMove(Ply, move3); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move1); Assert.IsTrue(KillerMoves.RetrieveB(Ply) == move3); Move move4 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(6), Board.GetSquare(7), null, 0, 30); KillerMoves.RecordPossibleKillerMove(Ply, move4); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move4); Assert.IsTrue(KillerMoves.RetrieveB(Ply) == move1); // Start again KillerMoves.Clear(); Move move5 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(16), Board.GetSquare(17), null, 0, 200); KillerMoves.RecordPossibleKillerMove(Ply, move5); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move5); Assert.IsNull(KillerMoves.RetrieveB(Ply)); Move move6 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(18), Board.GetSquare(19), null, 0, 300); KillerMoves.RecordPossibleKillerMove(Ply, move6); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move6); Assert.IsTrue(KillerMoves.RetrieveB(Ply) == move5); }
public ParticleSwarms(string PgnFilename, int ParticleSwarms, int ParticlesPerSwarm, int WinPercentScale, Delegates.WriteMessageLine WriteMessageLine) { _writeMessageLine = WriteMessageLine; // Load games. WriteMessageLine("Loading games."); var stopwatch = new Stopwatch(); stopwatch.Start(); var board = new Board(WriteMessageLine); var pgnGames = new PgnGames(); pgnGames.Load(board, PgnFilename); stopwatch.Stop(); // Count positions. long positions = 0; for (var gameIndex = 0; gameIndex < pgnGames.Count; gameIndex++) { var pgnGame = pgnGames[gameIndex]; positions += pgnGame.Moves.Count; } var positionsPerSecond = (int)(positions / stopwatch.Elapsed.TotalSeconds); WriteMessageLine($"Loaded {pgnGames.Count:n0} games with {positions:n0} positions in {stopwatch.Elapsed.TotalSeconds:0.000} seconds ({positionsPerSecond:n0} positions per second)."); stopwatch.Restart(); WriteMessageLine("Creating data structures."); // Create parameters and particle swarms. var parameters = CreateParameters(); for (var index = 0; index < ParticleSwarms; index++) { Add(new ParticleSwarm(pgnGames, parameters, ParticlesPerSwarm, WinPercentScale)); } // Set parameter values of first particle in first swarm to known best. var firstParticleInFirstSwarm = this[0].Particles[0]; SetDefaultParameters(firstParticleInFirstSwarm.Parameters); var cache = new Cache(1, board.ValidateMove); var killerMoves = new KillerMoves(Search.MaxHorizon); var moveHistory = new MoveHistory(); var evaluation = new Evaluation(board.IsRepeatPosition, () => false, WriteMessageLine); var search = new Search(cache, killerMoves, moveHistory, evaluation, () => false, WriteMessageLine); firstParticleInFirstSwarm.CalculateEvaluationError(board, search, WinPercentScale); _originalEvaluationError = firstParticleInFirstSwarm.EvaluationError; stopwatch.Stop(); WriteMessageLine($"Created data structures in {stopwatch.Elapsed.TotalSeconds:0.000} seconds."); }