Esempio n. 1
0
        public moveData generateTree(int maxDepth, string[] newGameBoard, int piece, Piece[] currentPieces)
        {
            totalGamestates = 0;
            Node newNode = new Node();

            newNode.gameBoard   = newGameBoard;
            newNode.pieceToPlay = piece;
            root = newNode;

            Node currentNode = root;
            Node parentNode;
            Node sibling = null;

            parentNode          = currentNode;
            currentNode.sibling = null;
            currentNode.pieces  = currentPieces;

            generateChildrenGamestate(currentNode, parentNode, piece, sibling, maxDepth, 0);

            winningMove move = searchForBestPlay(currentNode, 0, maxDepth, 0);

            Console.Write("Total moves generated: ");
            Console.WriteLine(totalGamestates);
            printBoard(move.winningNode);

            // This is bad but it works.
            string pieceOnDeck = move.winningNode.pieceToPlay == NULLPIECE?
                                 NULLPIECE.ToString() : move.winningNode.pieces[move.winningNode.pieceToPlay].piece;

            return(new moveData {
                lastMoveOnBoard = move.winningNode.pieces[move.winningNode.moveOnBoard].piece,
                pieceToPlay = pieceOnDeck
            });
        }
Esempio n. 2
0
        // Only selects a random piece and position when there is no plays better than the one originally selected
        public static winningMove RandomPlay(winningMove winChoice)
        {
            int        rand;
            var        rnd = new Random();
            List <int> playablePieces;
            List <int> playablePositions;

            if (winChoice.heuristicValue == 0)
            {
                playablePositions = AIFunctions.makePlayablePositionList(winChoice.winningNode.gameBoard);
                if (playablePositions.Count() == 0)
                {
                    return(winChoice);
                }
                else if (playablePositions.Count() - 1 == 0)
                {
                    rand = 0;
                }
                else
                {
                    rand = rnd.Next(0, playablePositions.Count() - 1);
                }
                winChoice.winningNode.moveOnBoard = playablePositions[rand];

                playablePieces = AIFunctions.makePlayablePiecesOnly(winChoice.winningNode.pieces);
                if (playablePieces.Count() == 0)
                {
                    return(winChoice);
                }
                else if (playablePieces.Count() - 1 == 0)
                {
                    rand = 0;
                }
                else
                {
                    rand = rnd.Next(0, playablePieces.Count() - 1);
                }
                winChoice.winningNode.pieceToPlay = playablePieces[rand];
            }

            return(winChoice);
        }
Esempio n. 3
0
        // Searches tree generated for the best play. Selects the best move from the move given by the opponent.
        public static winningMove searchForBestPlay(QuartoSearchTree.Node currentNode, int depth, int minimax, int alpha, int beta, bool maxPlayer)
        {
            int         j = 0;
            string      pieceString;
            int         boardPosition = 0;
            int         minimaxCompare;
            winningMove winChoice  = new winningMove();
            winningMove winChoice2 = new winningMove();

            winChoice.winningNode = new QuartoSearchTree.Node();

            // If only root in tree
            if (currentNode.parent == null && currentNode.children[0] == null)
            {
            }

            // Detects for win
            if (currentNode.parent == null)
            {
                for (int i = 0; i < QuartoSearchTree.MAXGAMEBOARD && currentNode.children[i] != null; i++)
                {
                    if (currentNode.pieceToPlay == QuartoSearchTree.NULLPIECE)
                    {
                        pieceString = null;
                    }
                    else
                    {
                        pieceString = currentNode.pieces[currentNode.pieceToPlay].piece;
                    }

                    while (currentNode.gameBoard[boardPosition] != null)
                    {
                        boardPosition++;
                    }
                    bool win = Heuristic.isWin(currentNode.gameBoard, pieceString, boardPosition);

                    if (win)
                    {
                        winChoice.winningNode    = currentNode.children[i];
                        winChoice.heuristicValue = 0;
                        return(winChoice);
                    }
                    boardPosition++;
                }
            }

            // If it is the bottom of the tree
            if (currentNode.children[0] == null)
            {
                int value;

                for (int i = 0; i < QuartoSearchTree.MAXGAMEBOARD && currentNode.parent.children[i] != null; i++)
                {
                    if (currentNode.parent.children[i].pieceToPlay == QuartoSearchTree.NULLPIECE)
                    {
                        pieceString = null;
                    }
                    else
                    {
                        pieceString = currentNode.parent.children[i].pieces[currentNode.parent.children[i].pieceToPlay].piece;
                    }

                    minimaxCompare = Heuristic.calculateHeuristic(currentNode.parent.children[i].gameBoard, pieceString);

                    if (i == 0)
                    {
                        minimax = Heuristic.calculateHeuristic(currentNode.parent.children[i].gameBoard, pieceString);
                        winChoice.winningNode    = currentNode.parent.children[i];
                        winChoice.heuristicValue = minimax;
                        totalSearch++;
                    }
                    else if ((minimaxCompare > minimax && maxPlayer == true) || (minimaxCompare < minimax && maxPlayer == false))
                    {
                        minimax = minimaxCompare;
                        winChoice.winningNode    = currentNode.parent.children[i];
                        winChoice.heuristicValue = minimax;
                        totalSearch++;
                    }

                    //prunes the rest of children if they can be pruned
                    if (maxPlayer)
                    {
                        value = -INFINITY;
                        if (winChoice.heuristicValue > value)
                        {
                            value = winChoice.heuristicValue;
                        }
                        if (value > alpha)
                        {
                            alpha = value;
                        }
                        if (alpha >= beta)
                        {
                            break;
                        }
                    }

                    else
                    {
                        value = INFINITY;
                        if (winChoice.heuristicValue < value)
                        {
                            value = winChoice.heuristicValue;
                        }
                        if (value < beta)
                        {
                            beta = value;
                        }
                        if (alpha >= beta)
                        {
                            break;
                        }
                    }

                    j++;
                }
            }

            // Iterates through all children nodes
            else
            {
                int value;

                while (j < QuartoSearchTree.MAXGAMEBOARD && currentNode.children[j] != null)
                {
                    if (j == 0)
                    {
                        winChoice = searchForBestPlay(currentNode.children[j], depth, minimax, alpha, beta, !maxPlayer);

                        if (currentNode.parent == null || currentNode.parent.parent == null)
                        {
                        }

                        // When it is evaluating the next move from the root
                        else if (currentNode.parent.parent.parent == null)
                        {
                            winChoice.winningNode = currentNode;
                            totalSearch++;
                        }
                    }

                    else
                    {
                        winChoice2 = searchForBestPlay(currentNode.children[j], depth, minimax, alpha, beta, !maxPlayer);

                        if ((winChoice2.heuristicValue > winChoice.heuristicValue && maxPlayer == true) || (winChoice2.heuristicValue < winChoice.heuristicValue && maxPlayer == false))
                        {
                            winChoice.heuristicValue = winChoice2.heuristicValue;

                            if (currentNode.parent == null)
                            {
                                winChoice.winningNode = winChoice2.winningNode;
                                totalSearch++;
                            }
                            else if (currentNode.parent.parent == null)
                            {
                                winChoice.heuristicValue = winChoice2.heuristicValue;
                                winChoice.winningNode    = winChoice2.winningNode;
                                totalSearch++;
                            }

                            // When it is evaluating the next move from the root
                            else if (currentNode.parent.parent.parent == null)
                            {
                                winChoice.winningNode    = currentNode;
                                winChoice.heuristicValue = winChoice2.heuristicValue;
                                totalSearch++;
                            }
                        }
                    }

                    //prunes the rest of children if they can be pruned
                    if (maxPlayer)
                    {
                        value = -INFINITY;
                        if (winChoice.heuristicValue > value)
                        {
                            value = winChoice.heuristicValue;
                        }
                        if (value > alpha)
                        {
                            alpha = value;
                        }
                        if (alpha >= beta)
                        {
                            break;
                        }
                    }

                    else
                    {
                        value = INFINITY;
                        if (winChoice.heuristicValue < value)
                        {
                            value = winChoice.heuristicValue;
                        }
                        if (value < beta)
                        {
                            beta = value;
                        }
                        if (alpha >= beta)
                        {
                            break;
                        }
                    }
                    j++;
                }
            }

            if (currentNode.parent == null)
            {
                RandomPlay(winChoice);
            }

            return(winChoice);
        }
Esempio n. 4
0
        public moveData generateTree(string[] newGameBoard, int piece, Piece[] currentPieces, int difficulty)
        {
            int    piecesOnBoard;
            int    maxDepth;
            int    positionToBlock;
            bool   boardBlockable = false;
            string moveToSend;
            string pieceOnDeck;

            Node newNode = new Node();

            newNode.gameBoard   = newGameBoard;
            newNode.pieceToPlay = piece;
            root = newNode;
            Node currentNode = root;
            Node parentNode;

            parentNode         = currentNode;
            currentNode.pieces = currentPieces;

            positionToBlock = AIFunctions.findWinningPositionToBlock(newGameBoard, currentPieces[piece].piece);
            if (difficulty == 3 && positionToBlock != -1 && Heuristic.calculateHeuristic(newGameBoard, currentPieces[piece].piece) > 0)
            {
                boardBlockable = true;
            }

            // Sets tree depth according to how many pieces are on the board
            piecesOnBoard = AIFunctions.countPiecesOnBoard(newGameBoard);
            maxDepth      = AIFunctions.setTreeDepth(piecesOnBoard, difficulty);

            // Generates game tree
            generateChildrenGamestate(currentNode, parentNode, piece, maxDepth, 0);

            // Finds the best move in the game tree based on a heuristic.
            winningMove move = NegaMax.searchForBestPlay(currentNode, maxDepth, 0, -MAXGAMEBOARD, MAXGAMEBOARD, true);

            if (boardBlockable && !move.isWin && piecesOnBoard != MAXGAMEBOARD - 1)
            {
                // Erases old winning move then adds new move to board.
                // Also sets old piece to playable again.
                move.winningNode.gameBoard[move.winningNode.moveOnBoard] = null;
                move.winningNode.gameBoard[positionToBlock] = currentPieces[piece].piece;
                move.winningNode.pieces[move.winningNode.pieceToPlay].setPlayable(true);

                move.winningNode = AIFunctions.checkForOpponentWin(move.winningNode, currentPieces[piece].piece);

                pieceOnDeck = move.winningNode.pieceToPlay == NULLPIECE?
                              NULLPIECE.ToString() : move.winningNode.pieces[move.winningNode.pieceToPlay].piece;

                moveToSend = move.winningNode.pieces[positionToBlock].piece;
            }
            else
            {
                if (piecesOnBoard != 0 && move.winningNode.pieceToPlay != NULLPIECE)
                {
                    move.winningNode = AIFunctions.checkForOpponentWin(move.winningNode, null);
                }

                moveToSend = move.winningNode.pieces[move.winningNode.moveOnBoard].piece;
                //Checks for win by opponent, given the piece chosen
                //If win it makes it equal to the next child and so on
                pieceOnDeck = move.winningNode.pieceToPlay == NULLPIECE?
                              NULLPIECE.ToString() : move.winningNode.pieces[move.winningNode.pieceToPlay].piece;
            }

            return(new moveData
            {
                lastMoveOnBoard = moveToSend,
                pieceToPlay = pieceOnDeck
            });
        }
Esempio n. 5
0
        public winningMove searchForBestPlay(Node currentNode, int depthCounter, int depth, int negaMax)
        {
            int         j = 0;
            string      pieceString;
            int         boardPosition = 0;
            int         negaMaxCompare;
            winningMove winChoice  = new winningMove();
            winningMove winChoice2 = new winningMove();

            winChoice.heuristicValue = -1;
            winChoice.winningNode    = new Node();

            // If only root in tree
            if (currentNode.parent == null && currentNode.children[0] == null)
            {
                Console.WriteLine("Search Failed: Tree only contains root");
            }

            // Detects for win
            if (currentNode.parent == null)
            {
                for (int i = 0; i < MAXGAMEBOARD && currentNode.children[i] != null; i++)
                {
                    if (currentNode.pieceToPlay == NULLPIECE)
                    {
                        pieceString = null;
                    }
                    else
                    {
                        pieceString = currentNode.pieces[currentNode.pieceToPlay].piece;
                    }

                    while (currentNode.gameBoard[boardPosition] != null)
                    {
                        boardPosition++;
                    }
                    bool win = Heuristic.isWin(currentNode.gameBoard, pieceString, boardPosition);

                    if (win)
                    {
                        winChoice.winningNode    = currentNode.children[i];
                        winChoice.heuristicValue = 0;
                        return(winChoice);
                    }
                    boardPosition++;
                }
            }

            // If it is the bottom of the tree
            if (currentNode.children[0] == null)
            {
                for (int i = 0; i < MAXGAMEBOARD && currentNode.parent.children[i] != null; i++)
                {
                    if (currentNode.parent.children[i].pieceToPlay == NULLPIECE)
                    {
                        pieceString = null;
                    }
                    else
                    {
                        pieceString = currentNode.parent.children[i].pieces[currentNode.parent.children[i].pieceToPlay].piece;
                    }

                    negaMaxCompare = Heuristic.calculateHeuristic(currentNode.parent.children[i].gameBoard, pieceString);

                    if (i == 0)
                    {
                        negaMax = Heuristic.calculateHeuristic(currentNode.parent.children[i].gameBoard, pieceString);
                        winChoice.winningNode    = currentNode.parent.children[i];
                        winChoice.heuristicValue = negaMax;
                    }
                    else if (-negaMaxCompare > -negaMax)
                    {
                        negaMax = -negaMaxCompare;
                        winChoice.winningNode    = currentNode.parent.children[i];
                        winChoice.heuristicValue = negaMax;
                    }
                }
            }

            // Iterates through all children nodes
            else
            {
                while (j < MAXGAMEBOARD && currentNode.children[j] != null)
                {
                    if (j == 0)
                    {
                        winChoice = searchForBestPlay(currentNode.children[j], depthCounter++, depth, negaMax);

                        if (currentNode.parent == null || currentNode.parent.parent == null)
                        {
                        }
                        else if (currentNode.parent.parent.parent == null)
                        {
                            winChoice.winningNode = currentNode;
                        }
                    }
                    else
                    {
                        winChoice2 = searchForBestPlay(currentNode.children[j], depthCounter++, depth, negaMax);
                        if (-winChoice2.heuristicValue > -winChoice.heuristicValue)
                        {
                            winChoice.heuristicValue = -winChoice2.heuristicValue;

                            if (currentNode.parent == null)
                            {
                            }
                            else if (currentNode.parent.parent == null)
                            {
                                winChoice.heuristicValue = winChoice2.heuristicValue;
                            }
                            else if (currentNode.parent.parent.parent == null)
                            {
                                winChoice.winningNode    = currentNode;
                                winChoice.heuristicValue = winChoice2.heuristicValue;
                            }
                        }
                    }
                    j++;
                }
            }
            //printBoard(winChoice.winningNode);
            Console.WriteLine(winChoice.heuristicValue);
            return(winChoice);
        }
Esempio n. 6
0
        public moveData generateTree(string[] newGameBoard, int piece, Piece[] currentPieces, int difficulty)
        {
            // hashing function would go here
            // Followed by a lookup in the transposition table
            //HashFunction.ZobristHash zash = new HashFunction.ZobristHash();
            //zash.init_zobristHash();


            totalGamestates = 0;
            int    piecesOnBoard;
            int    maxDepth;
            int    positionToBlock;
            bool   boardBlockable = false;
            string moveToSend;

            positionToBlock = AIFunctions.findWinningPositionToBlock(newGameBoard, currentPieces[piece].piece);
            if (difficulty == 3 && positionToBlock != -1 && Heuristic.calculateHeuristic(newGameBoard, currentPieces[piece].piece) > 0)
            {
                boardBlockable = true;
            }

            Node newNode = new Node();

            newNode.gameBoard   = newGameBoard;
            newNode.pieceToPlay = piece;
            root = newNode;

            Node currentNode = root;
            Node parentNode;

            parentNode         = currentNode;
            currentNode.pieces = currentPieces;

            // Sets tree depth according to how many pieces are on the board
            piecesOnBoard = AIFunctions.countPiecesOnBoard(newGameBoard);
            maxDepth      = AIFunctions.setTreeDepth(piecesOnBoard, difficulty);

            generateChildrenGamestate(currentNode, parentNode, piece, maxDepth, 0);

            winningMove move = NegaMax.searchForBestPlay(currentNode, maxDepth, 0, -MAXGAMEBOARD, MAXGAMEBOARD, true);

            //Checks for win by opponent, given the piece chosen
            //If win it makes it equal to the next child and so on
            if (piecesOnBoard != 0 && move.winningNode.pieceToPlay != NULLPIECE && difficulty > 1)
            {
                move.winningNode = AIFunctions.checkForOpponentWin(move.winningNode);
            }

            // This is bad but it works.
            string pieceOnDeck = move.winningNode.pieceToPlay == NULLPIECE?
                                 NULLPIECE.ToString() : move.winningNode.pieces[move.winningNode.pieceToPlay].piece;

            if (boardBlockable)
            {
                moveToSend = move.winningNode.pieces[positionToBlock].piece;
            }
            else
            {
                moveToSend = move.winningNode.pieces[move.winningNode.moveOnBoard].piece;
            }

            return(new moveData
            {
                lastMoveOnBoard = moveToSend,
                pieceToPlay = pieceOnDeck
            });
        }