Example #1
0
        public int MakeMove(IGameboard gameboard)
        {
            var mySymbol = gameboard.ActiveSymbol;
            var rootNode = new MinimaxNode(gameboard, -1);

            return Minimax(rootNode, true, -1, mySymbol).Move;
        }
Example #2
0
 public static Heuristic GetBestNode(MinimaxNode node, int depth)
 {
     if (node == null)
     {
         return(null);
     }
     return(alphaBeta(node, depth, double.MinValue, double.MaxValue, true));
 }
Example #3
0
    /// <summary>
    /// Have the AI calculate its next move
    /// </summary>
    public void MakeMove()
    {
        //Set player = 1 as human generated current board state
        MinimaxNode rootNode = new MinimaxNode {
            Player = 1, GameState = Gameboard.BoardArray.Clone() as byte[, ]
        };

        GenerateNode(ref rootNode);
        rootNode.Evaluate(out var bestNode, int.MinValue, int.MaxValue);

        //Get the index of the button in the board
        var index           = bestNode.ModifiedCoordinate.Item2 * 3 + bestNode.ModifiedCoordinate.Item1;
        var childGameObject = GbO.transform.GetChild(index).gameObject;

        Gameboard.UpdateGameboard(childGameObject, 2);
    }
Example #4
0
 private int? EvaluateNode(MinimaxNode minimaxNode, string mySymbol)
 {
     if (IsWinner(mySymbol, minimaxNode.Board))
     {
         return WIN;
     }
     if (IsWinner(GetOpponentsSymbol(mySymbol), minimaxNode.Board))
     {
         return LOSS;
     }
     if (IsBoardComplete(minimaxNode.Board))
     {
         return DRAW;
     }
     return null;
 }
Example #5
0
        private Evaluation Minimax(MinimaxNode node, bool maximizing, int firstMove, string mySymbol)
        {
            var eval = EvaluateNode(node, mySymbol);
            if (eval != null)
            {
                return new Evaluation() { Value = eval.Value, Move = firstMove };
            }

            if (maximizing)
            {
                var best = new Evaluation() { Value = int.MinValue, Move = -1 };
                for (int i = 0; i < 9; i++)
                {
                    if (IsEmpty(node.Board.Tiles[i]))
                    {
                        var child = new MinimaxNode(node.Board, i);
                        var val = Minimax(child, false, firstMove == -1 ? i : firstMove, mySymbol);
                        if (val.Value > best.Value)
                        {
                            best = val;
                        }
                    }
                }
                return best;
            }
            else
            {
                var best = new Evaluation() { Value = int.MaxValue, Move = -1 };
                for (int i = 0; i < 9; i++)
                {
                    if (IsEmpty(node.Board.Tiles[i]))
                    {
                        var child = new MinimaxNode(node.Board, i);
                        var val = Minimax(child, true, firstMove == -1 ? i : firstMove, mySymbol);
                        if (val.Value < best.Value)
                        {
                            best = val;
                        }
                    }
                }
                return best;
            }
        }
Example #6
0
    /// <summary>
    /// Recursively populates the tree using the parent node as a base
    /// </summary>
    /// <param name="parentNode">current perm of the board</param>
    void GenerateNode(ref MinimaxNode parentNode)
    {
        //generate all possible perm of board and assign to nodes
        //check current depth of the current node, if = limit break, if !- limit recurse generate node on new node

        if (parentNode.Depth == DepthCap)
        {
            return;
        }

        for (var x = 0; x < 3; x++)
        {
            for (var y = 0; y < 3; y++)
            {
                if (parentNode.GameState[x, y] != 0)
                {
                    continue;
                }

                MinimaxNode childNode = new MinimaxNode();
                childNode.GameState = parentNode.GameState.Clone() as byte[, ];

                if (childNode.GameState == null)
                {
                    throw new Exception("Cannot clone Game State");
                }

                childNode.GameState[x, y]    = (byte)(parentNode.Player == 1 ? 2 : 1);
                childNode.Player             = (byte)(parentNode.Player == 1 ? 2 : 1);
                childNode.ModifiedCoordinate = ((byte)x, (byte)y);
                childNode.Parent             = parentNode;

                //Don't generate permutations of children that generate win conditions
                if (!(childNode.CheckForWinningMove(1) || childNode.CheckForWinningMove(2)))
                {
                    GenerateNode(ref childNode);
                }
                parentNode.Children.Add(childNode);
            }
        }
    }
Example #7
0
    int AlphaBeta(ChessBoardSnapshot boardPosition, int depth, int alpha, int beta, bool maximizingPlayer)
    {
        int         origAlpha = alpha;
        int         origBeta  = beta;
        MinimaxNode node      = new MinimaxNode();

        // Transposition Table Lookup; node is the lookup key for ttEntry
        ulong hash = boardPosition.board.ToZobristHash();

        if (tTable.ContainsKey(hash))
        {
            node = tTable[hash];

            if (node.depth >= depth)
            {
                switch (node.flag)
                {
                case MinimaxNodeFlag.Exact:
                    return(node.eval);

                case MinimaxNodeFlag.LowerBound:
                    if (node.eval > alpha)
                    {
                        alpha = node.eval;
                    }
                    break;

                case MinimaxNodeFlag.UpperBound:
                    if (node.eval < beta)
                    {
                        beta = node.eval;
                    }
                    break;
                }

                if (beta <= alpha)
                {
                    return(node.eval);
                }
            }
        }

        // Minimax + Alpha Beta Pruning
        if (depth <= 0 || boardPosition.IsEndGame())
        {
            return(GameManager.Instance.CalculateScore(boardPosition, playerType));
        }

        int val = 0;

        if (maximizingPlayer)
        {
            val = int.MinValue;
            ChessBoardSnapshot[] nextBoardPositions = FindPossibleMoves(boardPosition, playerType);

            for (int i = 0; i < nextBoardPositions.Length; i++)
            {
                int newValue = AlphaBeta(nextBoardPositions[i], depth - 1, alpha, beta, false);

                if (newValue > val)
                {
                    val = newValue;
                }
                if (val > alpha)
                {
                    alpha = val;
                }
                if (beta <= alpha)
                {
                    break;
                }
            }
        }
        else
        {
            val = int.MaxValue;
            ChessBoardSnapshot[] nextBoardPositions = FindPossibleMoves(boardPosition, playerType.ToOpposite());

            for (int i = 0; i < nextBoardPositions.Length; i++)
            {
                int newValue = AlphaBeta(nextBoardPositions[i], depth - 1, alpha, beta, true);

                if (newValue < val)
                {
                    val = newValue;
                }
                if (val < beta)
                {
                    beta = val;
                }
                if (beta <= alpha)
                {
                    break;
                }
            }
        }

        // Transposition Table Store; node is the lookup key for ttEntry
        node.hash = hash;
        node.eval = val;

        if (val <= origAlpha)
        {
            node.flag = MinimaxNodeFlag.UpperBound;
        }
        else if (val >= origBeta)
        {
            node.flag = MinimaxNodeFlag.LowerBound;
        }
        else
        {
            node.flag = MinimaxNodeFlag.Exact;
        }

        node.depth = depth;

        if (tTable.ContainsKey(hash))
        {
            tTable[hash] = node;
        }
        else
        {
            tTable.Add(hash, node);
        }

        return(val);
    }
Example #8
0
        private static Heuristic alphaBeta(MinimaxNode node, int depth, double alpha, double beta, bool maximizingPlayer)
        {
            if (node.IsTerminal() || depth < 1)
            {
                return(new Heuristic {
                    node = node, value = node.GetHeuristic()
                });
            }
            List <MinimaxNode> subNodes = node.GetSubNodes();

            if (maximizingPlayer)
            {
                Heuristic abNode = new Heuristic {
                    value = double.MinValue
                };
                Heuristic newAbNode;
                for (int i = 0; i < subNodes.Count; i++)
                {
                    newAbNode = alphaBeta(subNodes[i], depth - 1, alpha, beta, false);
                    if (newAbNode.value > abNode.value)
                    {
                        abNode = new Heuristic {
                            node = subNodes[i], value = newAbNode.value
                        }
                    }
                    ;
                    if (abNode.value > alpha)
                    {
                        alpha = abNode.value;
                    }
                    if (alpha >= beta)
                    {
                        break;
                    }
                }
                return(abNode);
            }
            else
            {
                Heuristic abNode = new Heuristic {
                    value = double.MaxValue
                };
                Heuristic newAbNode;
                for (int i = 0; i < subNodes.Count; i++)
                {
                    newAbNode = alphaBeta(subNodes[i], depth - 1, alpha, beta, true);
                    if (newAbNode.value < abNode.value)
                    {
                        abNode = new Heuristic {
                            node = subNodes[i], value = newAbNode.value
                        }
                    }
                    ;
                    if (abNode.value < beta)
                    {
                        beta = abNode.value;
                    }
                    if (beta <= alpha)
                    {
                        break;
                    }
                }
                return(abNode);
            }
        }
    }