Beispiel #1
0
        private int SEE(Player player, int alpha, int beta, Square squareCaptured)
        {
            // Static Exchange Evaluator

            int val             = int.MinValue;
            int intScoreAtEntry = 0;

            Move moveThis = null;

            // Generate moves
            Moves movesPossible = new Moves();

            squareCaptured.AttackerMoveList(movesPossible, player);

            if (movesPossible.Count == 0)
            {
                //	alpha = this.Score;
                alpha = -player.OtherPlayer.SEEScore;
            }
            else
            {
                // Sort moves
                foreach (Move movex in movesPossible)
                {
                    movex.Score = (movex.PieceTaken.Value - movex.Piece.Value / 10);
                }
                movesPossible.SortByScore();

                foreach (Move move in movesPossible)
                {
                    moveThis = move.Piece.SEEMove(move.Name, move.To);

                    if (moveThis.IsInCheck)
                    {
                        Move.SEEUndo(moveThis); continue;
                    }

                    val = -SEE(player.OtherPlayer, -beta, -alpha, squareCaptured);

                    if (val < intScoreAtEntry)
                    {
                        val = intScoreAtEntry;
                    }

                    Move.SEEUndo(moveThis);

                    if (val >= beta)
                    {
                        return(beta);
                    }

                    if (val > alpha)
                    {
                        alpha = val;
                    }
                }
            }

            return(alpha);
        }
Beispiel #2
0
        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);
        }