コード例 #1
0
 private void InitTT()
 {
     //Initialize TT with 2^20 entries, each one of them to null. 2^20 since 20 bits are used for the indeces
     TT = new TTEntry[1048576];
     for (int i = 0; i < TT.Length - 1; i++)
     {
         TT[i] = null;
     }
 }
コード例 #2
0
        public void SetEntry(TTEntry Entry)//Set entry using current hash
        {
            int Index = (int)(CurrentHash & (0xFFFFF));

            if (TT[Index] == null)//If the entry is null then the new one can be inserted without checking conditions
            {
                TT[Index] = Entry;
            }
            else if (TT[Index].SearchDepth <= Entry.SearchDepth)//Using Deep policy, store new ones only if they have a deeper subtree
            {
                TT[Index] = Entry;
            }
        }
コード例 #3
0
        public void SetEntry(TTEntry Entry, long ZH)//Overload of previous function to make it work by calculating every time the hash
        {
            int Index = (int)(ZH & (0xFFFFF));

            if (TT[Index] == null)//If the entry is null then the new one can be inserted without checking conditions
            {
                TT[Index] = Entry;
            }
            else if (TT[Index].SearchDepth <= Entry.SearchDepth)//Using Deep policy, store new ones only if they have a deeper subtree
            {
                TT[Index] = Entry;
            }
        }
コード例 #4
0
        public Tuple <int, Move> NegaMax(int Depth, int alpha, int beta)
        {
            Position.SearchStats.NumberOfNodes++;
            //---------------------Transposition Tables - Start First Phase-------------------------------//
            int     originalAlpha   = alpha;
            long    ZH              = Position.TranspositionTable.ZobristHash(Position.Board.Grid, Position.Turn.Player, Position.CanCapture());
            TTEntry entryOfPosition = Position.TranspositionTable.GetEntry(ZH);

            if (entryOfPosition != null && entryOfPosition.SearchDepth >= Depth)
            {
                Position.SearchStats.TTGeneralCounter++;
                if (entryOfPosition.Type == Const.EXACT)
                {
                    Position.SearchStats.TTExactCounter++;
                    return(new Tuple <int, Move>(entryOfPosition.Value, entryOfPosition.BestMove));
                }
                else if (entryOfPosition.Type == Const.LOWER_BOUND)
                {
                    Position.SearchStats.TTLowerBoundCounter++;
                    alpha = Math.Max(alpha, entryOfPosition.Value);
                }
                else if (entryOfPosition.Type == Const.UPPER_BOUND)
                {
                    Position.SearchStats.TTUpperBoundCounter++;
                    beta = Math.Min(beta, entryOfPosition.Value);
                }
                if (alpha >= beta)
                {
                    Position.SearchStats.PruningsCounter++;
                    return(new Tuple <int, Move>(entryOfPosition.Value, entryOfPosition.BestMove));
                }
            }
            //---------------------Transposition Tables - End First Phase-------------------------------//

            //---------------------Evaluation/Quiescence Evaluation - Start-------------------------------//
            if (Depth == 0 || Position.Terminal())
            {
                //MONTE CARLO EVALUATION CUSTOM(NOT SUITABLE FOR THIS GAME AS THE BRANCHING FACTOR IS TOO HIGH AND NOT MANY GAMES COULD BE PLAYED FOR EACH LEAF NODE )
                //Console.WriteLine(Position.MCEvaluator.Evaluate() * (Position.Turn.Player == Color.Silver ? -1 : 1));
                //return new Tuple<int, Move>(Position.MCEvaluator.Evaluate() * (Position.Turn.Player == Color.Silver ? -1 : 1), null);

                int Evaluation = Const.USE_QUISCENCE_EVALUATION ? Position.Evaluator.QuiscentEvaluation(Const.QUISCENCE_EVALUATION_DEPTH, Position.CanCapture() ? alpha : -beta, Position.CanCapture() ? beta : -alpha) : Position.Evaluator.Evaluate() * (Position.SilverTurn() ? -1 : 1);

                return(new Tuple <int, Move>(Evaluation, null));//null move since this is only an evaluation of the static board (actually there is a quiscence evaluation)
            }
            //---------------------Evaluation/QUiscence Evaluation - End-------------------------------//

            //---------------------AlphaBeta Search - Start-------------------------------//
            var         score           = int.MinValue + 1;
            Move        currentBestMove = null;
            List <Move> ListOfLegalMovesToBeUsed;

            //If root level then use root legal moves ordered from iterative deepening
            if (LMS.Count > 0 && DepthCounter == 0)
            {
                ListOfLegalMovesToBeUsed = LMS;
            }
            else //If not then use normal moves giving right of way to capture moves
            {
                ListOfLegalMovesToBeUsed = OrderMovesFirstCaptures(Position.Board.GetAllLegalMoves(Position.Turn.Player, Position.CanCapture(), Position.Turn.GetPreviouslyMovedPiece()));
            }

            ListOfLegalMovesToBeUsed = PutKillerMovesFirst(ListOfLegalMovesToBeUsed, Depth);

            foreach (var m in ListOfLegalMovesToBeUsed)
            {
                int newScore;

                //Make move to modify state of the board on order to simulate it
                Position.SimulateMove(m);

                //Increase current depth counter used for both evaluating paths and to return to previous states together with moves history
                DepthCounter++;

                //Decrease depth only when switching players, otherwise keep same depth
                if (!Position.CanCapture())
                {
                    newScore = NegaMax(Depth, alpha, beta).Item1;//This way 2 move is considered a ply
                    //newScore = NegaMax(Depth - 1, alpha, beta).Item1;//This way 1 move are considered a ply
                }
                else
                {
                    newScore = -NegaMax(Depth - 1, -beta, -alpha).Item1;
                }

                //Decrease current depth counter used for both evaluating paths and to return to previous states together with moves history
                DepthCounter--;

                //If using ordered legal moves than update the score needed for iterative deepening
                if (LMS.Count > 0 && InitialDepthID == Depth)
                {
                    m.IDScore = newScore;
                }

                //Update score if necessary
                if (newScore > score)
                {
                    score           = newScore;
                    currentBestMove = m;
                }

                //Update Alpha
                alpha = Math.Max(alpha, score);

                //Undo move to return the board to previous state
                Position.UndoMove(m);

                //Check for prunings
                if (alpha >= beta)
                {
                    Position.SearchStats.PruningsCounter++;
                    KillerMoves[DepthCounter, CurrentKM] = m;
                    CurrentKM = (CurrentKM + 1) % 2;
                    break;
                }
            }
            //---------------------AlphaBeta Search - End-------------------------------//

            //---------------------Transposition Table - Start Second Phase-------------------------------//
            int type;

            //Decide type of value stored
            if (score <= originalAlpha)
            {
                type = Const.UPPER_BOUND;
            }
            else if (score >= beta)
            {
                type = Const.LOWER_BOUND;
            }
            else
            {
                type = Const.EXACT;
            }

            //Store entry
            Position.TranspositionTable.SetEntry(new TTEntry(score, type, ZH, Depth, currentBestMove), ZH);
            //---------------------Transposition Table - End Second Phase-------------------------------//

            return(new Tuple <int, Move>(alpha, currentBestMove));
        }
コード例 #5
0
        public Tuple <int, Move> NegaMax(int Depth, int alpha, int beta)
        {
            Position.SearchStats.NumberOfNodes++;
            //---------------------Transposition Tables - Start First Phase-------------------------------//
            int     originalAlpha   = alpha;
            long    ZH              = Position.TranspositionTable.ZobristHash(Position.Board.Grid, Position.Turn.Player, Position.CanCapture());
            TTEntry entryOfPosition = Position.TranspositionTable.GetEntry(ZH);

            if (entryOfPosition != null && entryOfPosition.SearchDepth >= Depth)
            {
                Position.SearchStats.TTGeneralCounter++;
                if (entryOfPosition.Type == Const.EXACT)
                {
                    Position.SearchStats.TTExactCounter++;
                    return(new Tuple <int, Move>(entryOfPosition.Value, entryOfPosition.BestMove));
                }
                else if (entryOfPosition.Type == Const.LOWER_BOUND)
                {
                    Position.SearchStats.TTLowerBoundCounter++;
                    alpha = Math.Max(alpha, entryOfPosition.Value);
                }
                else if (entryOfPosition.Type == Const.UPPER_BOUND)
                {
                    Position.SearchStats.TTUpperBoundCounter++;
                    beta = Math.Min(beta, entryOfPosition.Value);
                }
                if (alpha >= beta)
                {
                    Position.SearchStats.PruningsCounter++;
                    return(new Tuple <int, Move>(entryOfPosition.Value, entryOfPosition.BestMove));
                }
            }
            //---------------------Transposition Tables - End First Phase-------------------------------//

            //---------------------Evaluation/Quiescence Evaluation - Start-------------------------------//
            if (Depth == 0 || Position.Terminal())
            {
                //MONTE CARLO EVALUATION CUSTOM(NOT SUITABLE FOR THIS GAME AS THE BRANCHING FACTOR IS TOO HIGH AND NOT MANY GAMES COULD BE PLAYED FOR EACH LEAF NODE )
                //Console.WriteLine(Position.MCEvaluator.Evaluate() * (Position.Turn.Player == Color.Silver ? -1 : 1));
                //return new Tuple<int, Move>(Position.MCEvaluator.Evaluate() * (Position.Turn.Player == Color.Silver ? -1 : 1), null);

                int Evaluation = Const.USE_QUISCENCE_EVALUATION ? Position.Evaluator.QuiscentEvaluation(Const.QUISCENCE_EVALUATION_DEPTH, Position.CanCapture() ? alpha : -beta, Position.CanCapture() ? beta : -alpha) : Position.Evaluator.Evaluate() * (Position.SilverTurn() ? -1 : 1);

                return(new Tuple <int, Move>(Evaluation, null));//null move since this is only an evaluation of the static board (actually there is a quiscence evaluation)
            }
            //---------------------Evaluation/QUiscence Evaluation - End-------------------------------//

            //---------------------AlphaBeta Search - Start-------------------------------//
            var         score           = int.MinValue + 1;
            Move        currentBestMove = null;
            List <Move> ListOfLegalMovesToBeUsed;

            //If root level then use root legal moves ordered from iterative deepening
            if (LMS.Count > 0 && DepthCounter == 0)
            {
                ListOfLegalMovesToBeUsed = LMS;
            }
            else //If not then use normal moves giving right of way to capture moves
            {
                ListOfLegalMovesToBeUsed = OrderMovesFirstCaptures(Position.Board.GetAllLegalMoves(Position.Turn.Player, Position.CanCapture(), Position.Turn.GetPreviouslyMovedPiece()));
            }

            ListOfLegalMovesToBeUsed = PutKillerMovesFirst(ListOfLegalMovesToBeUsed, Depth);

            Move firstMove = ListOfLegalMovesToBeUsed[0];

            ListOfLegalMovesToBeUsed.RemoveAt(0);

            score = RecursiveCall(firstMove, Depth, alpha, beta);

            //If using ordered legal moves than update the score needed for iterative deepening
            if (LMS.Count > 0 && InitialDepthID == Depth)
            {
                firstMove.IDScore = score;
            }

            //Attempt to implement NegaScout but not working properly
            if (score < beta)
            {
                foreach (var m in ListOfLegalMovesToBeUsed)
                {
                    int LBound = Math.Max(alpha, score);
                    int UBound = LBound + 1;

                    int newScore;

                    newScore = RecursiveCall(m, Depth, LBound, UBound);

                    if (newScore >= UBound && newScore < beta)
                    {
                        newScore = RecursiveCall(m, Depth, newScore, beta);
                    }

                    //If using ordered legal moves than update the score needed for iterative deepening
                    if (LMS.Count > 0 && InitialDepthID == Depth)
                    {
                        m.IDScore = newScore;
                    }

                    //Update score if necessary
                    if (newScore > score)
                    {
                        score           = newScore;
                        currentBestMove = m;
                    }

                    //Check for prunings
                    if (newScore >= beta)
                    {
                        Position.SearchStats.PruningsCounter++;
                        KillerMoves[DepthCounter, CurrentKM] = m;
                        CurrentKM = (CurrentKM + 1) % 2;
                        break;
                    }
                }
            }


            //---------------------AlphaBeta Search - End-------------------------------//

            //---------------------Transposition Table - Start Second Phase-------------------------------//
            int type;

            //Decide type of value stored
            if (score <= originalAlpha)
            {
                type = Const.UPPER_BOUND;
            }
            else if (score >= beta)
            {
                type = Const.LOWER_BOUND;
            }
            else
            {
                type = Const.EXACT;
            }

            //Store entry
            Position.TranspositionTable.SetEntry(new TTEntry(score, type, ZH, Depth, currentBestMove), ZH);
            //---------------------Transposition Table - End Second Phase-------------------------------//

            return(new Tuple <int, Move>(alpha, currentBestMove));
        }