Esempio n. 1
0
        public void GetPossibleMovesOneMoveMade()
        {
            TTTBoard board = new TTTBoard();

            board.MakeMove(new TTTMove(1, 2));
            Assert.AreEqual(8, board.PossibleMoves().Count);
        }
Esempio n. 2
0
    //Debugging purposes
    protected void DebugBoard(TTTBoard gameBoard)
    {
        for (int i = 0; i < 3; ++i)
        {
            string line = "";

            for (int j = 0; j < 3; ++j)
            {
                switch (gameBoard.board[j][i].state)
                {
                case TTT.SquareState.Empty:
                    line += " ___ ";
                    break;

                default:
                    line += "  ";
                    line += gameBoard.board[j][i].state;
                    line += "  ";
                    break;
                }
            }

            Debug.Log(line);
        }
    }
Esempio n. 3
0
        public void InvariantTests0()
        {
            TTTBoard     board   = new TTTBoard(3);
            List <int[]> squares = board.GetEmptySquares();
            int          count   = squares.Count;

            Assert.AreEqual(9, count, "Empty squares");
        }
Esempio n. 4
0
    public override IEnumerator GetDecision(TTTBoard board)
    {
        currentTime = System.DateTime.Now;

        isDoneMoving = false;

        //Reset previous data
        anticipatedResult = new MoveScore(0, 0);
        statesSampled     = 0;
        culledStates      = 0;
        moveChoices.Clear();
        viableChoices.Clear();

        //Copy the board to avoid affecting the real one
        TTTBoard testBoard = new TTTBoard(board);

        //Get all free squares - the player may cheat, but the AI does not
        testBoard.PopulateMoveQueue(moveChoices);

        //Error checking for if we try to edit a board that's complete
        if (moveChoices.Count > 0)
        {
            chosenMove = moveChoices.Peek();
        }
        else
        {
            UnityEngine.Debug.LogError("TRYING TO PLAY ON ALREADY COMPLETE BOARD");
            isDoneMoving = true;
            chosenMove   = Vector2Int.one * -1;
        }

        //Allows us to check whether or not the following coroutine has finished, by saving a reference to a bool
        BoolCheck newBc = new BoolCheck();

        StartCoroutine(GetBestMovesRecursive(testBoard, playingAs, 0, anticipatedResult, newBc, 2));

        //Keep waiting for previous functions to complete before moving on
        while (!newBc.complete)
        {
            yield return(new WaitForEndOfFrame());
        }

        //Debug info
        Debug.Log("Computer player " + playingAs.ToString() + " processed " + statesSampled + " unique states, " +
                  "best case scenario: " + anticipatedResult.outcome + " after " + anticipatedResult.depth + " turns");

        string tot = "";

        for (int i = 0; i < viableChoices.Count; ++i)
        {
            Vector2Int vChoice = viableChoices.Dequeue();
            viableChoices.Enqueue(vChoice);
            tot += vChoice;
            tot += " ";
        }

        Debug.Log("Choices: " + tot);
    }
Esempio n. 5
0
    public override IEnumerator GetDecision(TTTBoard board)
    {
        isDoneMoving = false;

        //Keep doing the coroutine until a decision has been made
        while (!IsDoneMoving)
        {
            yield return(new WaitForEndOfFrame());

            hoverPiece.gameObject.SetActive(false);

            //reset alpha value
            if (lastHovered != null)
            {
                lastHovered.mr.material.color = new Color(1, 1, 1, 0);
            }

            //check the mouse's raycast into the scene and test if its colliding with a TicTacToe square
            //Also set the hovering piece to that location
            Ray ray = mainCam.ScreenPointToRay(Input.mousePosition);

            RaycastHit rch;
            if (Physics.Raycast(ray, out rch, 1000f, catchMouseLayer))
            {
                //If it hits a square, set the player's hovering game piece over that square
                hoverPiece.gameObject.SetActive(true);

                hoverPiece.transform.position = rch.collider.transform.position + new Vector3(0, 0.1f, 0);

                ClickableSquare cs;

                //Get a reference to the square
                if (rch.collider.TryGetComponent(out cs))
                {
                    //Set alpha of square so that players can tell where they are hovering over
                    lastHovered          = cs;
                    cs.mr.material.color = new Color(1, 1, 1, 0.1f);

                    //If the player has clicked that square, set the player's 'chosen move' to that square
                    //Deactivate the hovering game piece and set conditions to exit the while loop
                    if (hasClicked)
                    {
                        hoverPiece.gameObject.SetActive(false);

                        chosenMove   = new Vector2Int(cs.MySquareNumber / 3, cs.MySquareNumber % 3);
                        isDoneMoving = true;
                        hasClicked   = false;

                        //reset alpha values
                        if (lastHovered != null)
                        {
                            lastHovered.mr.material.color = new Color(1, 1, 1, 0);
                        }
                    }
                }
            }
        }
    }
Esempio n. 6
0
        public void CanDrawBoardTest()
        {
            TTTBoard board = new TTTBoard();
            board.MakeMove(new Nought(), 0, 0);
            board.MakeMove(new Cross(), 2, 2);
            ConsoleBoardPainter painter = new ConsoleBoardPainter();

            board.PaintBoard(painter);
        }
 void Restart()
 {
     gameBoard = new TTTBoard(TTTBoard.TTTPiece.X);
     XTurn     = true;
     waiting   = false;
     minWait   = false;
     CancelInvoke("CancelMinWait");
     DrawBoard();
 }
 void ReceiveTurn(ITurn turn)
 {
     //Debug.Log (gameBoard.ToString());
     gameBoard = (TTTBoard)((TTTTurn)turn).ApplyTurn(gameBoard);
     XTurn     = !XTurn;
     //Debug.Log (gameBoard.ToString());
     DrawBoard();
     waiting = false;
 }
Esempio n. 9
0
        /// <summary>
        /// Called when the start button is pressed <para/>
        /// Initialises the <see cref="mcts"/> tree search object and instantiates the root node <para/>
        /// Also creates as many starting nodes as the user specified
        /// </summary>
        public void StartButtonPressed()
        {
            //Create an empty board instance, which will have whatever game the user chooses assigned to it
            Board board;

            //Assign whatever game board the user has chosen to the board instance
            switch (HashUIController.GetGameChoice)
            {
            case 0:
                board             = new TTTBoard();
                displayBoardModel = false;
                break;

            case 1:
                board             = new C4Board();
                displayBoardModel = true;

                //Create a C4 Board GameObject and obtain a reference to its BoardModelController Component
                GameObject boardModel = Instantiate(Resources.Load("C4 Board", typeof(GameObject))) as GameObject;
                boardModelController = boardModel.GetComponent <BoardModelController>();
                boardModelController.Initialise();
                break;

            case 2:
                board             = new OthelloBoard();
                displayBoardModel = false;
                break;

            default:
                throw new System.Exception("Unknown game type index has been input");
            }

            mcts = new TreeSearch <Node>(board);

            //Calculate the position of the root node and add an object for it to the scene
            Vector3    rootNodePosition = BoardToPosition(mcts.Root.GameBoard);
            GameObject rootNode         = Instantiate(Resources.Load("HashNode"), rootNodePosition, Quaternion.identity) as GameObject;

            rootNode.transform.parent = transform;
            rootNode.GetComponent <HashNode>().AddNode(null, mcts.Root, false);
            rootNode.GetComponent <HashNode>().Initialise(rootNodePosition);

            //Add the root node to the position and object map
            nodePositionMap.Add(rootNodePosition, rootNode);
            nodeObjectMap.Add(mcts.Root, rootNode);

            //Create the amount of starting nodes specified by the user
            for (int i = 0; i < HashUIController.GetStartingNodeInput(); i++)
            {
                PerformStep(true);
            }

            //Swap out the current menu panels
            HashUIController.SetMenuPanelActive(false);
            HashUIController.SetNavigationPanelActive(true);
        }
Esempio n. 10
0
        public void MakeMoveInNonEmptyCell()
        {
            TTTBoard board = new TTTBoard();

            //Make a move on this board
            board.MakeMove(new TTTMove(2, 2));

            //Attempt to make another move in the same place as the last move, which should throw an InvalidMoveException
            Assert.Throws <InvalidMoveException>(() => board.MakeMove(new TTTMove(2, 2)));
        }
Esempio n. 11
0
        public void NoWinnerTest()
        {
            TTTBoard board = new TTTBoard();

            //Make a move, if there is a winner, the winner flag will be set, but there is no winner, so it shouldn't
            board.MakeMove(new TTTMove(0, 0));

            //Check that the winner flag has not been set, as there is no winner
            Assert.AreEqual(-1, board.Winner);
        }
Esempio n. 12
0
    public TTTBoard(TTTBoard oldBoard)
    {
        Size  = oldBoard.Size;
        board = new TTTPiece[Size];

        for (int i = 0; i < board.Length; i++)
        {
            board[i] = oldBoard.board[i];
        }
        player = oldBoard.player;
    }
Esempio n. 13
0
        public void TTboardClone()
        {
            TTTBoard board    = new TTTBoard(3);
            TTTBoard newBoard = board.Clone();

            board.Move(0, 0, Player.PLAYERX);
            board.Move(0, 1, Player.PLAYERO);
            int emptyBoard    = board.GetEmptySquares().Count;
            int emptyNewBoard = newBoard.GetEmptySquares().Count;

            Assert.AreNotEqual(emptyNewBoard, emptyBoard, "Bad clone");
        }
Esempio n. 14
0
        public void GetPossibleMovesFullBoard()
        {
            TTTBoard board = new TTTBoard();

            for (int y = 0; y < board.Height; y++)
            {
                for (int x = 0; x < board.Width; x++)
                {
                    board.MakeMove(new TTTMove(x, y));
                }
            }
            Assert.AreEqual(0, board.PossibleMoves().Count);
        }
Esempio n. 15
0
        public void WinTestHorizontal()
        {
            TTTBoard board = new TTTBoard();

            //Make moves such that player 1 should win with a horizontal victory
            board.MakeMove(new TTTMove(0, 2));
            board.MakeMove(new TTTMove(0, 0));
            board.MakeMove(new TTTMove(1, 2));
            board.MakeMove(new TTTMove(2, 0));
            board.MakeMove(new TTTMove(2, 2));

            //Player 1 should have won the game
            Assert.AreEqual(1, board.Winner);
        }
Esempio n. 16
0
        public void WinTestDownwardsDiagonal()
        {
            TTTBoard board = new TTTBoard();

            //Make moves such that player 1 should win with a downwards diagonal victory
            board.MakeMove(new TTTMove(0, 0));
            board.MakeMove(new TTTMove(0, 1));
            board.MakeMove(new TTTMove(1, 1));
            board.MakeMove(new TTTMove(2, 0));
            board.MakeMove(new TTTMove(2, 2));

            //Player 1 should have won the game
            Assert.AreEqual(1, board.Winner);
        }
    public IGameState ApplyTurn(IGameState state)
    {
        TTTBoard board = (TTTBoard)state;

        board.SetPiece(x, player);
        if (board.player == TTTBoard.TTTPiece.X)
        {
            board.player = TTTBoard.TTTPiece.O;
        }
        else
        {
            board.player = TTTBoard.TTTPiece.X;
        }
        return(board);
    }
Esempio n. 18
0
        public void TTboardCheckWin()
        {
            TTTBoard board    = new TTTBoard(3);
            TTTBoard newBoard = board.Clone();

            Assert.AreEqual(Player.NONE, board.CheckWin(), "Check Win game in progres 1");
            board.Move(0, 0, Player.PLAYERO);
            board.Move(0, 1, Player.PLAYERX);
            Assert.AreEqual(Player.NONE, board.CheckWin(), "Check Win game in progres 2");
            board.Move(1, 0, Player.PLAYERO);
            board.Move(0, 2, Player.PLAYERX);
            Assert.AreEqual(Player.NONE, board.CheckWin(), "Check Win game in progres 3");
            board.Move(2, 0, Player.PLAYERO);
            Assert.AreEqual(Player.PLAYERO, board.CheckWin(), "Check Win should be game winner  4");
        }
Esempio n. 19
0
        public void MakeMoveTest()
        {
            //Create a new board and make a move in it
            TTTBoard board = new TTTBoard();

            board.MakeMove(new TTTMove(1, 0));

            //Check that the move was made correctly
            Assert.AreEqual(1, board.GetCell(1, 0));

            //Make a move on the board for the second player
            board.MakeMove(new TTTMove(2, 1));

            //Check that the move was made correctly
            Assert.AreEqual(2, board.GetCell(2, 1));
        }
Esempio n. 20
0
    public float Evaluate(IGameState state)
    {
        TTTBoard board = (TTTBoard)state;

        if (board.Winner(player))
        {
            return(maxValue);
        }
        else if (board.Loser(player))
        {
            return(minValue);
        }
        else
        {
            return(0);
        }
    }
Esempio n. 21
0
        public void DrawTest()
        {
            TTTBoard board = new TTTBoard();

            //Make moves on the board until it is full and there is no winner
            board.MakeMove(new TTTMove(0, 0));
            board.MakeMove(new TTTMove(1, 1));
            board.MakeMove(new TTTMove(2, 2));
            board.MakeMove(new TTTMove(0, 1));
            board.MakeMove(new TTTMove(0, 2));
            board.MakeMove(new TTTMove(2, 0));
            board.MakeMove(new TTTMove(2, 1));
            board.MakeMove(new TTTMove(1, 2));
            board.MakeMove(new TTTMove(1, 0));

            //Check that the game has ended in a draw
            Assert.AreEqual(0, board.Winner);
        }
Esempio n. 22
0
        public void CreateBoardTest()
        {
            TTTBoard board = new TTTBoard();

            //Check that the current player is player 1
            Assert.AreEqual(1, board.CurrentPlayer);

            //Ensure that the created board is empty
            for (int y = 0; y < board.Height; y++)
            {
                for (int x = 0; x < board.Width; x++)
                {
                    Assert.AreEqual(0, board.GetCell(x, y));
                }
            }

            //Ensure that the winner value is - 1
            Assert.AreEqual(-1, board.Winner);
        }
Esempio n. 23
0
        public void TTboardCheckWin2()
        {
            TTTBoard board    = new TTTBoard(3);
            TTTBoard newBoard = board.Clone();

            Assert.AreEqual(Player.NONE, board.CheckWin(), "Check Win game in progres 1");
            board.Move(0, 0, Player.PLAYERO);
            board.Move(0, 1, Player.PLAYERO);
            Assert.AreEqual(Player.NONE, board.CheckWin(), "Check Win game in progres 2");
            board.Move(1, 0, Player.PLAYERX);
            board.Move(1, 1, Player.PLAYERX);
            Assert.AreEqual(Player.NONE, board.CheckWin(), "Check Win game in progres 3");
            board.Move(1, 2, Player.PLAYERO);
            board.Move(0, 2, Player.PLAYERX);
            Assert.AreEqual(Player.NONE, board.CheckWin(), "heck Win game in progres 4");
            board.Move(2, 0, Player.PLAYERO);
            board.Move(2, 1, Player.PLAYERO);
            board.Move(2, 2, Player.PLAYERX);
            Assert.AreEqual(Player.DRAW, board.CheckWin(), "heck Win game DRAW");
        }
Esempio n. 24
0
        public void DuplicateTest()
        {
            //Create a new board and make a move in it
            TTTBoard boardA = new TTTBoard();

            boardA.MakeMove(new TTTMove(1, 1));

            //Duplicate the board and store it in a new board instance
            TTTBoard boardB = (TTTBoard)boardA.Duplicate();

            //Ensure the move made before duplication is present in both boards
            Assert.AreEqual(1, boardA.GetCell(1, 1));
            Assert.AreEqual(1, boardB.GetCell(1, 1));

            //These two board instances should share no memory, lets prove it by making moves in each of them and checking the other
            boardA.MakeMove(new TTTMove(2, 0));
            Assert.AreEqual(2, boardA.GetCell(2, 0));
            Assert.AreEqual(0, boardB.GetCell(2, 0));

            boardB.MakeMove(new TTTMove(1, 2));
            Assert.AreEqual(0, boardA.GetCell(1, 2));
            Assert.AreEqual(2, boardB.GetCell(1, 2));
        }
Esempio n. 25
0
        public void GetPossibleMovesEmptyBoard()
        {
            TTTBoard board = new TTTBoard();

            Assert.AreEqual(9, board.PossibleMoves().Count);
        }
Esempio n. 26
0
 //Repeatedly called until the player moves
 //Makes a function call to AI's logic algorithm in ComputerPlayer
 public abstract IEnumerator GetDecision(TTTBoard board);
Esempio n. 27
0
        /// <summary>
        /// Called when the start/stop button is pressed <para/>
        /// If MCTS is not running, then it will be started <para/>
        /// If MCTS is running, this will make it finish early
        /// </summary>
        public void StartStopButtonPressed()
        {
            //Starts or ends MCTS depending on when the button is pressed
            if (mcts == null)
            {
                //Create an empty board instance, which will have whatever game the user chooses assigned to it
                Board board;

                //Assign whatever game board the user has chosen to the board instance
                switch (TreeUIController.GetGameChoice)
                {
                case 0:
                    displayBoardModel = false;
                    board             = new TTTBoard();
                    break;

                case 1:
                    displayBoardModel = true;
                    board             = new C4Board();

                    //Create a C4 Board GameObject and obtain a reference to its BoardModelController Component
                    GameObject boardModel = Instantiate(Resources.Load("C4 Board", typeof(GameObject))) as GameObject;
                    boardModelController = boardModel.GetComponent <BoardModelController>();
                    boardModelController.Initialise();
                    break;

                case 2:
                    displayBoardModel = false;
                    board             = new OthelloBoard();
                    break;

                default:
                    throw new System.Exception("Unknown game type index has been input");
                }

                //Assign whatever visualisation type the user has chosen
                switch (TreeUIController.GetVisualisationChoice)
                {
                case 0:
                    visualisationType = VisualisationType.Standard3D;
                    break;

                case 1:
                    visualisationType = VisualisationType.Disk2D;
                    break;

                case 2:
                    visualisationType = VisualisationType.Cone;
                    break;

                default:
                    throw new System.Exception("Unknown visualisation type: encountered");
                }

                //Initialise MCTS on the given game board
                mcts = new TreeSearch <NodeObject>(board);

                //Obtain the time to run mcts for from the input user amount
                timeToRunFor = TreeUIController.GetTimeToRunInput;
                timeLeft     = timeToRunFor;

                //Run mcts asyncronously
                RunMCTS(mcts);
                TreeUIController.StartButtonPressed();
            }
            else
            {
                //Stop the MCTS early
                mcts.Finish();
            }
        }
Esempio n. 28
0
    //Takes in the board, the type of symbol (X, O) to simulate being placed, the level of recursion,
    //  a reference to the outcome to return, a check to say if it completed or was interrupted, and a previous best for AlphaBeta pruning
    private IEnumerator GetBestMovesRecursive(TTTBoard board, SquareState toPlace, int functionDepth, MoveScore returnOutcome, BoolCheck bc, int previousBest)
    {
        statesSampled += 1;
        //Outcome determines if the end result is a win, loss or tie.
        //It gets set to be the state we expect to get overriden, with 1 meaning a win and -1 meaning a loss
        //Because we expect the AI to only make moves that improve its odds of winning, we initialize it to -2 if it's the AI's turn
        //That way, it will get overriden immediately
        //The opposite is true for if it's the player's turn
        int outcome = ((toPlace == playingAs) ? -2 : 2);

        //Estimate of how long before the end of the game
        int movesUntilEndgame = 0;

        //Used to determine if the rest of the loop is garbage, due to alpha-beta pruning
        //The reason this is used as opposed to break; is to ensure that the list of move choices is kept consistent
        //The queue should be unaltered once the function passes to a higher recursion
        bool skipRestOfLoop = false;

        for (int i = 0; i < moveChoices.Count; ++i)
        {
            //For if alpha-beta determines all proceeding tests to be obsolete
            if (skipRestOfLoop)
            {
                //cycles through the queue until it returns to its starting arrangement
                moveChoices.Enqueue(moveChoices.Dequeue());
                continue;
            }

            //Take a move from the queue to test
            Vector2Int testMove = moveChoices.Dequeue();

            //Checks if the square is worth testing according to symmetry pruning - if it's not, skip the square and continue
            if (SymmetryPrune)
            {
                if (board.board[testMove.x][testMove.y].CheckIfCulled())
                {
                    moveChoices.Enqueue(testMove);
                    culledStates += 1;
                    continue;
                }
            }

            //Sets the square of the simulated board
            board.SetSquareState(testMove, toPlace);

            MoveScore moveScore = new MoveScore(0, 0);

            SquareState isVictory = board.CheckWin();

            if (isVictory == SquareState.Empty)
            {
                //Nobody one, continue simulation if possible
                if (moveChoices.Count > 0)
                {
                    //Set move score, which indicates (GameResult, GameLength).
                    //Passes the current best outcome to conduct AlphaBeta
                    BoolCheck   newBc     = new BoolCheck();
                    IEnumerator getReturn = GetBestMovesRecursive(board, (toPlace == SquareState.O) ? SquareState.X : SquareState.O, functionDepth + 1, moveScore, newBc, outcome);
                    StartCoroutine(getReturn);

                    //Do not continue until the inner function has succeeded
                    while (!newBc.complete)
                    {
                        yield return(new WaitForEndOfFrame());
                    }

                    //If moveScore is marked as invalid, it means to prune it
                    //Move to the next iteration
                    if (moveScore.invalid)
                    {
                        moveChoices.Enqueue(testMove);
                        board.SetSquareState(testMove, SquareState.Empty);
                        continue;
                    }

                    //Keeps track of how long the game will last, with the leaf node starting at 1 and counting up
                    moveScore.depth += 1;
                }
                else
                {
                    //Tie
                    moveScore = new MoveScore(0, 1);
                }
            }
            else if (isVictory == playingAs)
            {
                //you won
                moveScore = new MoveScore(1, 1);
            }
            else
            {
                //Opponent won
                moveScore = new MoveScore(-1, 1);
            }

            moveChoices.Enqueue(testMove);
            board.SetSquareState(testMove, SquareState.Empty);

            if (AlphaBetaPrune && functionDepth > 0)
            {
                //AlphaBeta
                //The root function should not alpha-beta prune, only receive a series of possible moves
                if (playingAs == toPlace)
                {
                    //If it's simulating your move and you can do better than the current best, your opponent will move to stop it
                    //Mark the return as invalid to tell the outer function to skip it
                    if (previousBest < moveScore.outcome)
                    {
                        culledStates         += 1;
                        returnOutcome.invalid = true;
                        skipRestOfLoop        = true;
                        continue;
                    }
                }
                else
                {
                    //Opposite logic for opponent's turn
                    if (previousBest > moveScore.outcome)
                    {
                        culledStates         += 1;
                        returnOutcome.invalid = true;
                        skipRestOfLoop        = true;
                        continue;
                    }
                }
            }

            if (playingAs == toPlace)
            {
                //If the move proposes a better result, then we overwrite our existing best move and options
                //If the result is net positive, we want a smaller MovesUntilEndgame. If net negative, we'll take the bigger.
                //If it's a tie, we don't care due to the fact that all tie games take the same amount of moves
                if (moveScore.outcome > outcome)
                {
                    outcome           = moveScore.outcome;
                    movesUntilEndgame = moveScore.depth;

                    if (functionDepth == 0)
                    {
                        viableChoices.Clear();
                        Debug.Log("VIABLE CHOICE: " + testMove + " AT DEPTH " + moveScore.depth + " RESULTING IN BETTER SCORE OF " + moveScore.outcome);
                        viableChoices.Enqueue(testMove);
                    }
                }
                else if (moveScore.outcome == outcome)
                {
                    //Delay the game if losing, quicken the game if winning
                    if (outcome > 0)
                    {
                        if (moveScore.depth < movesUntilEndgame)
                        {
                            movesUntilEndgame = moveScore.depth;

                            if (functionDepth == 0)
                            {
                                viableChoices.Clear();
                                Debug.Log("VIABLE CHOICE: " + testMove + " AT DEPTH " + moveScore.depth + " RESULTING IN SCORE OF " + moveScore.outcome);
                                viableChoices.Enqueue(testMove);
                            }
                        }
                        else if (moveScore.depth == movesUntilEndgame)
                        {
                            if (functionDepth == 0)
                            {
                                Debug.Log("VIABLE CHOICE: " + testMove + " AT DEPTH " + moveScore.depth + " RESULTING IN SCORE OF " + moveScore.outcome);
                                viableChoices.Enqueue(testMove);
                            }
                        }
                    }
                    else
                    {
                        if (moveScore.depth > movesUntilEndgame)
                        {
                            movesUntilEndgame = moveScore.depth;

                            if (functionDepth == 0)
                            {
                                viableChoices.Clear();
                                Debug.Log("VIABLE CHOICE: " + testMove + " AT DEPTH " + moveScore.depth + " RESULTING IN SCORE OF " + moveScore.outcome);
                                viableChoices.Enqueue(testMove);
                            }
                        }
                        else if (moveScore.depth == movesUntilEndgame)
                        {
                            if (functionDepth == 0)
                            {
                                Debug.Log("VIABLE CHOICE: " + testMove + " AT DEPTH " + moveScore.depth + " RESULTING IN SCORE OF " + moveScore.outcome);
                                viableChoices.Enqueue(testMove);
                            }
                        }
                    }
                }
            }
            else
            {
                //Invert the checks during the Opponent's turn
                //The recursive function always starts on the AI's turn, so we can remove the isRoot checks during the opponent's logic
                if (moveScore.outcome < outcome)
                {
                    outcome           = moveScore.outcome;
                    movesUntilEndgame = moveScore.depth;
                }
                else if (moveScore.outcome == outcome)
                {
                    //Delay the game if losing, quicken the game if winning - but for the Opponent
                    if (outcome < 0)
                    {
                        if (moveScore.depth < movesUntilEndgame)
                        {
                            movesUntilEndgame = moveScore.depth;
                        }
                    }
                    else
                    {
                        if (moveScore.depth > movesUntilEndgame)
                        {
                            movesUntilEndgame = moveScore.depth;
                        }
                    }
                }
            }
        }

        //Return the best options we saved
        returnOutcome.outcome = outcome;
        returnOutcome.depth   = movesUntilEndgame;

        //forces the program to stop for now, if the coroutine is taking too long to respond
        if (NonBlocking && (System.DateTime.Now - currentTime).Milliseconds >= millisecondsPerCycle)
        {
            yield return(new WaitForEndOfFrame());

            currentTime = System.DateTime.Now;
        }

        //Tell the outer function that you have finished
        bc.complete = true;

        //Choose a square from the viable options once all the functions have completed
        if (functionDepth == 0)
        {
            isDoneMoving = true;
            currentTime  = System.DateTime.Now;

            int toChoose = Random.Range(0, viableChoices.Count);

            for (int i = 0; i < toChoose; ++i)
            {
                viableChoices.Enqueue(viableChoices.Dequeue());
            }

            chosenMove = viableChoices.Peek();
        }
    }
Esempio n. 29
0
        public void SimulateTest()
        {
            TTTBoard board = new TTTBoard();

            board.SimulateUntilEnd();
        }