示例#1
0
        public void OrderMoves(List <Move> moves, Gameboard state, Move bestMove = null)
        {
            // Assign values to moves, if possible
            for (int i = 0; i < moves.Count; i++)
            {
                moves[i].Value = 0;

                // Check for best move from last iteration
                if (moves[i] == bestMove)
                {
                    // Best move is slightly better rated than other moves
                    moves[i].Value = 1;
                }

                Gameboard newState = (Gameboard)state.Clone();
                GameLogic newLogic = new GameLogic(newState);
                newLogic.ApplyMove(moves[i]);

                Int64 zHash = newState.GetZobristHash();
                if (transpositionTable.ContainsKey(zHash))
                {
                    Transposition transposition = transpositionTable[zHash];
                    if (transposition.Lowerbound == transposition.Upperbound)
                    {
                        moves[i].Value += transposition.Lowerbound;
                    }
                }
            }
            moves.Sort(MoveComparison);
        }
示例#2
0
        public override Move GetMove(Gameboard gameboard)
        {
            GameLogic   gameLogic = new GameLogic(gameboard);
            List <Move> bestMove  = new List <Move>();
            int         bestValue = int.MinValue;

            var possibleMoves = gameLogic.GetPossibleMoves();

            // Don't search if only one move possible
            if (possibleMoves.Count == 1)
            {
                // DEBUG
                n++;
                Console.WriteLine("Average Nodes: {0}, n={1}", iterationCounter / n, n);

                return(possibleMoves[0]);
            }

            OrderMoves(possibleMoves, gameboard);

            int alpha = GameLogic.LOSS_VALUE;
            int beta  = GameLogic.WIN_VALUE;

            foreach (Move move in possibleMoves)
            {
                // DEBUG
                iterationCounter++;

                Gameboard newState = (Gameboard)gameboard.Clone();
                GameLogic newLogic = new GameLogic(newState);
                newLogic.ApplyMove(move);

                int score = -AlphaBeta(newState, depth - 1, -beta, -alpha, false);

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

                if (score > bestValue)
                {
                    bestMove.Clear();
                    bestMove.Add(move);
                    bestValue = score;
                }
                else if (score == bestValue)
                {
                    bestMove.Add(move);
                }
            }

            // DEBUG
            n++;
            Console.WriteLine("Average Nodes: {0}, n={1}", iterationCounter / n, n);

            // Return one of the best moves
            return(bestMove[random.Next(bestMove.Count)]);
        }
示例#3
0
 public static HashSet<GamePosition> generateMoves(GameLogic gameLogic, int playerID, GamePosition gamePosition)
 {
     HashSet<Node> moves = gameLogic.GetPossibleMoves(playerID, gamePosition);
     HashSet<GamePosition> possibleMoves = new HashSet<GamePosition>();
     foreach(Node move in moves){
         possibleMoves.Add(gameLogic.ApplyMove(playerID, move, gamePosition));
     }
     return possibleMoves;
 }
示例#4
0
    public static HashSet <GamePosition> generateMoves(GameLogic gameLogic, int playerID, GamePosition gamePosition)
    {
        HashSet <Node>         moves         = gameLogic.GetPossibleMoves(playerID, gamePosition);
        HashSet <GamePosition> possibleMoves = new HashSet <GamePosition>();

        foreach (Node move in moves)
        {
            possibleMoves.Add(gameLogic.ApplyMove(playerID, move, gamePosition));
        }
        return(possibleMoves);
    }
示例#5
0
        /// <summary>
        /// Returns a move chosen by the player
        /// </summary>
        public override Move GetMove(Gameboard gameboard)
        {
            GameLogic   gameLogic = new GameLogic(gameboard);
            List <Move> bestMove  = new List <Move>();
            int         bestValue = int.MinValue;

            var possibleMoves = gameLogic.GetPossibleMoves();

            // Don't search if only one move possible
            if (possibleMoves.Count == 1)
            {
                return(possibleMoves[0]);
            }

            OrderMoves(possibleMoves, gameboard);

            int alpha = GameLogic.LOSS_VALUE;
            int beta  = GameLogic.WIN_VALUE;

            // The root level is searched in this function, for other levels, the AlphaBeta function is used
            foreach (Move move in possibleMoves)
            {
                // Apply move
                Gameboard newState = (Gameboard)gameboard.Clone();
                GameLogic newLogic = new GameLogic(newState);
                newLogic.ApplyMove(move);

                // Search deeper
                int score = -AlphaBeta(newState, depth - 1, -beta, -alpha, false);

                // Only alpha value can be adjusted at root level
                if (score > alpha)
                {
                    alpha = score;
                }

                if (score > bestValue)
                {
                    // Store new best move
                    bestMove.Clear();
                    bestMove.Add(move);
                    bestValue = score;
                }
                else if (score == bestValue)
                {
                    // Add move to other currently best moves
                    bestMove.Add(move);
                }
            }

            // Return one of the best moves
            return(bestMove[random.Next(bestMove.Count)]);
        }
示例#6
0
        public int QuiescenceSearch(Gameboard state, int alpha, int beta, bool myMove)
        {
            // DEBUG
            iterationCounter++;

            int score = int.MinValue;

            GameLogic gameLogic            = new GameLogic(state);
            var       possibleCaptureMoves = gameLogic.GetPossibleCaptureMoves();

            // If there are no capture moves possible, use evaluation function and return value
            if (possibleCaptureMoves.Count == 0)
            {
                score = myMove ? evaluation.Evaluate(state) : -evaluation.Evaluate(state);
            }
            // If there are capture moves, continue iterating
            else
            {
                foreach (Move move in possibleCaptureMoves)
                {
                    Gameboard newState = (Gameboard)state.Clone();
                    GameLogic newLogic = new GameLogic(newState);
                    newLogic.ApplyMove(move);

                    int value = -QuiescenceSearch(newState, -beta, -alpha, !myMove);
                    if (value > score)
                    {
                        score = value;
                        if (score >= beta)
                        {
                            break;
                        }
                        if (score > alpha)
                        {
                            alpha = score;
                        }
                    }
                }
            }

            return(score);
        }
示例#7
0
        public int AlphaBeta(Gameboard state, int depth, int alpha, int beta, bool myMove)
        {
            // DEBUG
            iterationCounter++;

            GameLogic gameLogic = new GameLogic(state);

            if (depth <= 0 || gameLogic.IsFinished())
            {
                return(-QuiescenceSearch(state, -beta, -alpha, !myMove));
            }

            int score         = int.MinValue;
            var possibleMoves = gameLogic.GetPossibleMoves();

            foreach (Move move in possibleMoves)
            {
                Gameboard newState = (Gameboard)state.Clone();
                GameLogic newLogic = new GameLogic(newState);
                newLogic.ApplyMove(move);

                int value = -AlphaBeta(newState, depth - 1, -beta, -alpha, !myMove);
                if (value > score)
                {
                    score = value;
                }
                if (score > alpha)
                {
                    alpha = score;
                }
                if (score >= beta)
                {
                    break;
                }
            }

            return(score);
        }
示例#8
0
        public override Move GetMove(Gameboard gameboard)
        {
            GameLogic   gameLogic = new GameLogic(gameboard);
            List <Move> bestMove  = new List <Move>();
            int         bestValue = int.MinValue;

            var possibleMoves = gameLogic.GetPossibleMoves();

            foreach (Move move in possibleMoves)
            {
                // DEBUG
                iterationCounter++;

                Gameboard newState = (Gameboard)gameboard.Clone();
                GameLogic newLogic = new GameLogic(newState);
                newLogic.ApplyMove(move);

                int score = MiniMax(newState, depth - 1, false);

                if (score > bestValue)
                {
                    bestMove.Clear();
                    bestMove.Add(move);
                    bestValue = score;
                }
                else if (score == bestValue)
                {
                    bestMove.Add(move);
                }
            }

            // DEBUG
            n++;
            Console.WriteLine("Average Nodes: {0}, n={1}", iterationCounter / n, n);

            // Return one of the best moves
            return(bestMove[random.Next(bestMove.Count)]);
        }
示例#9
0
        public int MiniMax(Gameboard state, int depth, bool max)
        {
            // DEBUG
            iterationCounter++;

            GameLogic gameLogic = new GameLogic(state);

            if (depth <= 0 || gameLogic.IsFinished())
            {
                return(Evaluate(state));
            }

            int score;

            score = max?int.MinValue:int.MaxValue;
            var possibleMoves = gameLogic.GetPossibleMoves();

            foreach (Move move in possibleMoves)
            {
                Gameboard newState = (Gameboard)state.Clone();
                GameLogic newLogic = new GameLogic(newState);
                newLogic.ApplyMove(move);

                int value = MiniMax(newState, depth - 1, !max);
                if (max && value > score)
                {
                    score = value;
                }
                else if (!max && value < score)
                {
                    score = value;
                }
            }

            return(score);
        }
示例#10
0
        public int AlphaBeta(Gameboard state, int depth, int alpha, int beta, bool myMove)
        {
            Int64 zHash    = state.GetZobristHash();
            Move  bestMove = null;

            // Check transposition table
            if (transpositionTable.ContainsKey(zHash))
            {
                Transposition transposition = transpositionTable[zHash];

                bestMove = transposition.BestMove;

                if (transposition.Depth >= depth)
                {
                    if (transposition.Lowerbound == transposition.Upperbound)
                    {
                        return(transposition.Lowerbound);
                    }

                    if (transposition.Lowerbound >= beta)
                    {
                        return(transposition.Lowerbound);
                    }
                    if (transposition.Upperbound <= alpha)
                    {
                        return(transposition.Upperbound);
                    }
                    alpha = Math.Max(alpha, transposition.Lowerbound);
                    beta  = Math.Min(beta, transposition.Upperbound);
                }
            }

            GameLogic gameLogic = new GameLogic(state);
            int       score;

            // Evaluate
            if (depth <= 0 || gameLogic.IsFinished())
            {
                score = myMove ? evaluation.Evaluate(state) : -evaluation.Evaluate(state);
            }
            // Search deeper
            else
            {
                score = int.MinValue;
                var possibleMoves = gameLogic.GetPossibleMoves();

                OrderMoves(possibleMoves, state, bestMove);
                // Reset best move
                bestMove = null;

                foreach (Move move in possibleMoves)
                {
                    Gameboard newState = (Gameboard)state.Clone();
                    GameLogic newLogic = new GameLogic(newState);
                    newLogic.ApplyMove(move);

                    // Continue search
                    int value = -AlphaBeta(newState, depth - 1, -beta, -alpha, !myMove);

                    // Adjust alpha and beta
                    if (value > score)
                    {
                        bestMove = move;
                        score    = value;
                    }
                    if (score > alpha)
                    {
                        alpha = score;
                    }
                    if (score >= beta)
                    {
                        break;
                    }
                }
            }


            // Store values in transposition table
            if (score <= alpha)
            {
                if (!transpositionTable.ContainsKey(zHash))
                {
                    Transposition transposition = new Transposition(alpha, score, depth, bestMove);
                    transpositionTable.Add(state.GetZobristHash(), transposition);
                }
                else
                {
                    Transposition transposition = transpositionTable[zHash];
                    transposition.Upperbound = score;
                    transposition.Depth      = depth;
                    transposition.BestMove   = bestMove;
                }
            }
            else if (score > alpha && score < beta)
            {
                if (!transpositionTable.ContainsKey(zHash))
                {
                    Transposition transposition = new Transposition(score, score, depth, bestMove);
                    transpositionTable.Add(state.GetZobristHash(), transposition);
                }
                else
                {
                    Transposition transposition = transpositionTable[zHash];
                    transposition.Lowerbound = score;
                    transposition.Upperbound = score;
                    transposition.Depth      = depth;
                    transposition.BestMove   = bestMove;
                }
            }
            else if (score >= beta)
            {
                if (!transpositionTable.ContainsKey(zHash))
                {
                    Transposition transposition = new Transposition(score, beta, depth, bestMove);
                    transpositionTable.Add(state.GetZobristHash(), transposition);
                }
                else
                {
                    Transposition transposition = transpositionTable[zHash];
                    transposition.Lowerbound = score;
                    transposition.Depth      = depth;
                    transposition.BestMove   = bestMove;
                }
            }

            return(score);
        }
示例#11
0
        public int AlphaBeta(Gameboard state, int depth, int alpha, int beta, bool myMove)
        {
            // DEBUG
            iterationCounter++;

            Int64 zHash    = state.GetZobristHash();
            Move  bestMove = null;

            if (transpositionTable.ContainsKey(zHash))
            {
                Transposition transposition = transpositionTable[zHash];

                bestMove = transposition.BestMove;

                if (transposition.Depth >= depth)
                {
                    if (transposition.Lowerbound == transposition.Upperbound)
                    {
                        return(transposition.Lowerbound);
                    }

                    if (transposition.Lowerbound >= beta)
                    {
                        return(transposition.Lowerbound);
                    }
                    if (transposition.Upperbound <= alpha)
                    {
                        return(transposition.Upperbound);
                    }
                    alpha = Math.Max(alpha, transposition.Lowerbound);
                    beta  = Math.Min(beta, transposition.Upperbound);
                }
            }

            GameLogic gameLogic = new GameLogic(state);
            int       score;

            if (depth <= 0 || gameLogic.IsFinished())
            {
                score = myMove ? evaluation.Evaluate(state) : -evaluation.Evaluate(state);
            }
            else
            {
                score = int.MinValue;
                var possibleMoves = gameLogic.GetPossibleMoves();

                OrderMoves(possibleMoves, state);
                // Reset best move
                bestMove = null;

                // Calculate score for PVS
                {
                    Move pvsMove = possibleMoves[0];

                    Gameboard newState = (Gameboard)state.Clone();
                    GameLogic newLogic = new GameLogic(newState);
                    newLogic.ApplyMove(pvsMove);

                    score = -AlphaBeta(newState, depth - 1, -beta, -alpha, !myMove);

                    bestMove = pvsMove;
                }

                if (score < beta)
                {
                    for (int i = 1; i < possibleMoves.Count; i++)
                    {
                        Move move       = possibleMoves[i];
                        int  lowerbound = Math.Max(alpha, score);
                        int  upperbound = lowerbound + 1;

                        Gameboard newState = (Gameboard)state.Clone();
                        GameLogic newLogic = new GameLogic(newState);
                        newLogic.ApplyMove(move);

                        int value = -AlphaBeta(newState, depth - 1, -upperbound, -lowerbound, !myMove);

                        // Fail high
                        if (value >= upperbound && value < beta)
                        {
                            value = -AlphaBeta(newState, depth - 1, -beta, -value, !myMove);
                        }

                        if (value > score)
                        {
                            bestMove = move;
                            score    = value;
                        }
                        if (score >= beta)
                        {
                            break;
                        }
                    }
                }
            }

            if (score <= alpha)
            {
                if (!transpositionTable.ContainsKey(zHash))
                {
                    Transposition transposition = new Transposition(alpha, score, depth, bestMove);
                    transpositionTable.Add(state.GetZobristHash(), transposition);
                }
                else
                {
                    Transposition transposition = transpositionTable[zHash];
                    transposition.Upperbound = score;
                    transposition.Depth      = depth;
                    transposition.BestMove   = bestMove;
                }
            }
            else if (score > alpha && score < beta)
            {
                if (!transpositionTable.ContainsKey(zHash))
                {
                    Transposition transposition = new Transposition(score, score, depth, bestMove);
                    transpositionTable.Add(state.GetZobristHash(), transposition);
                }
                else
                {
                    Transposition transposition = transpositionTable[zHash];
                    transposition.Lowerbound = score;
                    transposition.Upperbound = score;
                    transposition.Depth      = depth;
                    transposition.BestMove   = bestMove;
                }
            }
            else if (score >= beta)
            {
                if (!transpositionTable.ContainsKey(zHash))
                {
                    Transposition transposition = new Transposition(score, beta, depth, bestMove);
                    transpositionTable.Add(state.GetZobristHash(), transposition);
                }
                else
                {
                    Transposition transposition = transpositionTable[zHash];
                    transposition.Lowerbound = score;
                    transposition.Depth      = depth;
                    transposition.BestMove   = bestMove;
                }
            }

            return(score);
        }
示例#12
0
        public int AlphaBeta(Gameboard state, int depth, int alpha, int beta, bool myMove)
        {
            // DEBUG
            iterationCounter++;

            Int64 zHash = state.GetZobristHash();

            Move bestMove = null;

            if (transpositionTable.ContainsKey(zHash))
            {
                Transposition transposition = transpositionTable[zHash];

                bestMove = transposition.BestMove;

                if (transposition.Depth >= depth)
                {
                    if (transposition.Lowerbound == transposition.Upperbound)
                    {
                        return(transposition.Lowerbound);
                    }

                    if (transposition.Lowerbound >= beta)
                    {
                        return(transposition.Lowerbound);
                    }
                    if (transposition.Upperbound <= alpha)
                    {
                        return(transposition.Upperbound);
                    }
                    alpha = Math.Max(alpha, transposition.Lowerbound);
                    beta  = Math.Min(beta, transposition.Upperbound);
                }
            }

            GameLogic gameLogic = new GameLogic(state);
            int       score;

            if (depth <= 0 || gameLogic.IsFinished())
            {
                score = myMove ? evaluation.Evaluate(state) : -evaluation.Evaluate(state);
            }
            else
            {
                score = int.MinValue;
                var possibleMoves = gameLogic.GetPossibleMoves();

                OrderMoves(possibleMoves, state);
                // Reset best move
                bestMove = null;

                // Multi-Cut
                {
                    Move move = possibleMoves[0];

                    Gameboard newState = (Gameboard)state.Clone();
                    GameLogic newLogic = new GameLogic(newState);
                    newLogic.ApplyMove(move);

                    int c = 0;
                    int m = 0;

                    while (newState != null && m < 10)
                    {
                        int value = -AlphaBeta(newState, depth - 1 - 2, GameLogic.LOSS_VALUE, GameLogic.WIN_VALUE, false);

                        if (value >= beta)
                        {
                            c++;
                            if (c > 3)
                            {
                                return(beta);
                            }
                        }

                        m++;

                        if (m < possibleMoves.Count)
                        {
                            move = possibleMoves[m];

                            newState = (Gameboard)state.Clone();
                            newLogic = new GameLogic(newState);
                            newLogic.ApplyMove(move);
                        }
                        else
                        {
                            newState = null;
                        }
                    }
                }

                foreach (Move move in possibleMoves)
                {
                    Gameboard newState = (Gameboard)state.Clone();
                    GameLogic newLogic = new GameLogic(newState);
                    newLogic.ApplyMove(move);

                    int value = -AlphaBeta(newState, depth - 1, -beta, -alpha, !myMove);
                    if (value > score)
                    {
                        bestMove = move;
                        score    = value;
                    }
                    if (score > alpha)
                    {
                        alpha = score;
                    }
                    if (score >= beta)
                    {
                        break;
                    }
                }
            }

            if (score <= alpha)
            {
                if (!transpositionTable.ContainsKey(zHash))
                {
                    Transposition transposition = new Transposition(alpha, score, depth, bestMove);
                    transpositionTable.Add(state.GetZobristHash(), transposition);
                }
                else
                {
                    Transposition transposition = transpositionTable[zHash];
                    transposition.Upperbound = score;
                    transposition.Depth      = depth;
                    transposition.BestMove   = bestMove;
                }
            }
            else if (score > alpha && score < beta)
            {
                if (!transpositionTable.ContainsKey(zHash))
                {
                    Transposition transposition = new Transposition(score, score, depth, bestMove);
                    transpositionTable.Add(state.GetZobristHash(), transposition);
                }
                else
                {
                    Transposition transposition = transpositionTable[zHash];
                    transposition.Lowerbound = score;
                    transposition.Upperbound = score;
                    transposition.Depth      = depth;
                    transposition.BestMove   = bestMove;
                }
            }
            else if (score >= beta)
            {
                if (!transpositionTable.ContainsKey(zHash))
                {
                    Transposition transposition = new Transposition(score, beta, depth, bestMove);
                    transpositionTable.Add(state.GetZobristHash(), transposition);
                }
                else
                {
                    Transposition transposition = transpositionTable[zHash];
                    transposition.Lowerbound = score;
                    transposition.Depth      = depth;
                    transposition.BestMove   = bestMove;
                }
            }

            return(score);
        }