public static void UndoMove() { if (m_movesHistory.Count > 0) { Move moveUndo = m_movesHistory.Item(m_movesHistory.Count - 1); m_playerToPlay.Clock.Revert(); m_movesRedoList.Add(moveUndo); Move.Undo(moveUndo); m_playerToPlay = m_playerToPlay.OtherPlayer; if (m_movesHistory.Count > 1) { Move movePenultimate = m_movesHistory.Item(m_movesHistory.Count - 2); m_playerToPlay.Clock.TimeElapsed = movePenultimate.TimeStamp; } else { m_playerToPlay.Clock.TimeElapsed = new TimeSpan(0); } m_playerToPlay.Clock.Start(); } }
public static void RedoMove() { if (m_movesRedoList.Count > 0) { Move moveRedo = m_movesRedoList.Item(m_movesRedoList.Count - 1); m_playerToPlay.Clock.Revert(); moveRedo.Piece.Move(moveRedo.Name, moveRedo.To); m_playerToPlay.Clock.TimeElapsed = moveRedo.TimeStamp; m_movesHistory.Last.TimeStamp = moveRedo.TimeStamp; m_playerToPlay = m_playerToPlay.OtherPlayer; m_movesRedoList.RemoveLast(); m_playerToPlay.Clock.Start(); } }
public void GenerateLazyMoves(int depth, Moves moves, Moves.enmMovesType movesType, Square squareAttacking) { // if (squareAttacking==null) // { // All moves as defined by movesType foreach (Piece piece in this.m_colPieces) { piece.GenerateLazyMoves(moves, movesType); if (movesType != Moves.enmMovesType.All) { Move move; int intIndex; for (intIndex = moves.Count - 1; intIndex >= 0; intIndex--) { move = moves.Item(intIndex); if (!( move.Name == Move.enmName.PawnPromotion || move.To.Ordinal == squareAttacking.Ordinal // || // (depth>=-2 && move.From.Piece.BasicValue<move.To.Piece.BasicValue) || (depth >= -4 && !move.To.CanBeMovedToBy(move.Piece.Player.OtherPlayer)) // && ) ) { moves.Remove(move); } } } } // } // else // { // // Just re-capture moves // squareAttacking.AttackerMoveList(moves, this); // } /* * */ }
public Move ComputeBestMove() { m_blnIsThinking = true; Player player = this; m_moveBest = null; Move moveHash = null; int alpha_start = this.Score; /* Uncomment to switch-on opening book moves, once we have a decent opening book! * // Query Opening Book * if ((m_moveBest = OpeningBook.SearchForGoodMove(Board.HashKey, this.Colour) )!=null) * { * m_moveCurrent = m_moveBest; * this.MoveConsidered(); * return m_moveBest.Piece.Move(m_moveBest.Name, m_moveBest.To); * } */ Move moveDepthBest = null; int alpha = MIN_SCORE; int beta = MAX_SCORE; m_intRootScore = this.Score; m_tsnThinkingTimeAllotted = new TimeSpan(this.m_PlayerClock.TimeRemaining.Ticks / Math.Max(m_intGameMoves - (Game.TurnNo / 2), 1)); m_tsnThinkingTimeMaxAllowed = new TimeSpan(m_tsnThinkingTimeAllotted.Ticks * 3); m_tsnThinkingTimeHalved = new TimeSpan(m_tsnThinkingTimeAllotted.Ticks / 3); m_intEvaluations = 0; m_intPositionsSearched = 0; HashTable.ResetStats(); // HashTable.Clear(); Uncomment this to clear the hashtable at the beginning of each move HashTableCheck.ResetStats(); HashTablePawn.ResetStats(); History.Clear(); for (m_intSearchDepth = m_intMinSearchDepth; m_intSearchDepth <= m_intMaxSearchDepth; m_intSearchDepth++) { if (Game.DisplayMoveAnalysisTree) { Game.MoveAnalysis = new Moves(); } m_intMaxQDepth = m_intSearchDepth; // Get last iteration's best move from the HashTable moveHash = HashTable.ProbeForBestMove(player.Colour); // Generate and sort moves Moves movesPossible = new Moves(); player.GenerateLegalMoves(movesPossible); m_intTotalMoves = movesPossible.Count; // If only one move is available, then just play it! if (movesPossible.Count == 1) { moveDepthBest = m_moveCurrent = movesPossible.Item(0); goto MoveSelected; } // Sort moves foreach (Move movex in movesPossible) { movex.Score = 0; if (moveHash != null && movex.From.Ordinal == moveHash.From.Ordinal && movex.To.Ordinal == moveHash.To.Ordinal) { movex.Score += 1000000; } if (movex.Name == Move.enmName.PawnPromotion) { movex.Score += 10000; } if (movex.PieceTaken != null) { Move moveSee = movex.Piece.SEEMove(movex.Name, movex.To); movex.Score += -SEE(player.OtherPlayer, int.MinValue, int.MaxValue, movex.To); Move.SEEUndo(moveSee); } else { movex.Score += History.Retrieve(player.Colour, movex.From.Ordinal, movex.To.Ordinal); } } movesPossible.SortByScore(); alpha = MIN_SCORE; beta = MAX_SCORE; m_intCurrentMoveNo = 0; foreach (Move move in movesPossible) { m_moveCurrent = move.Piece.Move(move.Name, move.To); if (m_moveCurrent.IsInCheck) { Move.Undo(m_moveCurrent); continue; } move.Score = m_moveCurrent.Score = -AlphaBeta(player.OtherPlayer, m_intSearchDepth - 1, -alpha - 1, -alpha, true, ref m_moveCurrent); if ((DateTime.Now - m_PlayerClock.TurnStartTime) > m_tsnThinkingTimeMaxAllowed) { Move.Undo(m_moveCurrent); goto TimeExpired; } if ((move.Score > alpha) && (move.Score < beta)) /* fail */ { move.Score = m_moveCurrent.Score = -AlphaBeta(player.OtherPlayer, m_intSearchDepth - 1, -beta, -alpha, true, ref m_moveCurrent); if ((DateTime.Now - m_PlayerClock.TurnStartTime) > m_tsnThinkingTimeMaxAllowed) { Move.Undo(m_moveCurrent); goto TimeExpired; } } this.MoveConsidered(); if (Game.DisplayMoveAnalysisTree) { Game.MoveAnalysis.Add(m_moveCurrent); } Move.Undo(m_moveCurrent); m_intCurrentMoveNo++; if (m_moveCurrent.Score > alpha) { alpha = m_moveCurrent.Score; moveDepthBest = m_moveCurrent; History.Record(player.Colour, m_moveCurrent.From.Ordinal, m_moveCurrent.To.Ordinal, alpha - alpha_start, 1 << (m_intSearchDepth + 6)); // Update history heuristic data } m_moveCurrent.Alpha = alpha; m_moveCurrent.Beta = beta; } MoveSelected: m_moveBest = moveDepthBest; // Record best move HashTable.RecordHash(Board.HashCodeA, Board.HashCodeB, m_intSearchDepth, m_moveBest.Score, HashTable.enmHashType.Exact, m_moveBest.From.Ordinal, m_moveBest.To.Ordinal, m_moveBest.Name, player.Colour); this.MoveConsidered(); if ((DateTime.Now - m_PlayerClock.TurnStartTime) > m_tsnThinkingTimeHalved && m_intSearchDepth >= m_intMinimumPlys) { goto TimeExpired; } if (m_moveBest.Score > 99999) { break; // Checkmate found so dont bother searching any deeper } } TimeExpired: this.MoveConsidered(); m_blnIsThinking = false; this.MoveConsidered(); return(m_moveBest); }