Example #1
0
    // This gets called it "manual" is false. It's where the AI is actually given the reigns.
    public override void DoMove()
    {
        VBoard     internalVBoard = new VBoard(bm, playerNumber);
        Vector3Int bestMove       = new Vector3Int(-1, -1, -1);
        bool       doesWin        = false;

        bestMove = internalVBoard.PickMove(numFutureTurnsCalculated, priorWeight, ref doesWin);
        // now, if the player does win, we have to make them win in the least number of possible moves.
        Debug.Log("Does Win? " + doesWin);
        if (!doesWin)
        {
            for (int i = numFutureTurnsCalculated - 1; i >= 0; i--)
            {
                doesWin = false;
                Vector3Int newBestMove = internalVBoard.PickMove(i, priorWeight, ref doesWin);
                if (!doesWin)
                {
                    break;
                }
                else
                {
                    bestMove = newBestMove;
                }
            }
        }
        if (bestMove.x < 0)
        {
            Debug.Log("Error with the AI - couldn't find a valid move!");
        }
        pieces[bestMove.x].RealizeMove(new Vector2Int(bestMove.y, bestMove.z));
        bm.hasFinishedMove = true;
    }
Example #2
0
        // evaluates the board from player1's perspective
        // we maximize iff curPlayer is true
        // doesn't work if n<0!
        float EvaluateBoard(int n, float priorWeight, ref bool doesWin)
        {
            if (n == 0)
            {
                return(EvaluateBoard(ref doesWin));
            }
            CheckIfWin(ref doesWin);
            if (doesWin == true)
            {
                return(0);
            }
            // short-circuit if you are going to win in fewer moves!
            float optimalValue = curPlayer ? Mathf.NegativeInfinity : Mathf.Infinity;

            Vector2Int[] myPieces = curPlayer ? player1Pieces : player2Pieces;
            for (int i = 0; i < myPieces.Length; i++)
            {
                if (doesWin)
                {
                    break;
                }
                Vector2Int piece = myPieces[i];
                foreach (Vector2Int moveToPos in GetMoves(piece))
                {
                    if (doesWin)
                    {
                        break;
                    }
                    VBoard newBoard = new VBoard(this);
                    newBoard.boardArr[piece.x, piece.y]         = false;
                    newBoard.boardArr[moveToPos.x, moveToPos.y] = true;
                    (curPlayer ? newBoard.player1Pieces : newBoard.player2Pieces)[i] = moveToPos;
                    float newValue = newBoard.EvaluateBoard(n - 1, priorWeight, ref doesWin);
                    if (doesWin || (curPlayer ? (newValue > optimalValue) : (newValue < optimalValue)))
                    {
                        optimalValue = newValue;
                    }
                }
            }
            float currentValue = EvaluateBoard(ref doesWin);

            return(currentValue * priorWeight + optimalValue * (1 - priorWeight));
        }
Example #3
0
        // HERE we finally produce an optimal move for the AI.
        // The Vector3Int is really just a hack - the first coordinate is the
        // id of the marble to move, and the second and third coordinates are the new position.
        // if the first coordinate is negative, an error has occured.
        // just like with EvaluateBoard(int), we maximize iff we are player1
        public Vector3Int PickMove(int n, float priorWeight, ref bool doesWin)
        {
            Vector3Int ret = new Vector3Int(-1, -1, -1);

            if (n == 0)
            {
                return(ret);
            }
            float optimalValue = curPlayer ? Mathf.NegativeInfinity : Mathf.Infinity;

            Vector2Int[] myPieces = curPlayer ? player1Pieces : player2Pieces;
            for (int i = 0; i < myPieces.Length; i++)
            {
                if (doesWin)
                {
                    break;
                }
                Vector2Int piece = myPieces[i];
                foreach (Vector2Int moveToPos in GetMoves(piece))
                {
                    if (doesWin)
                    {
                        break;
                    }
                    VBoard newBoard = new VBoard(this);
                    newBoard.boardArr[piece.x, piece.y]         = false;
                    newBoard.boardArr[moveToPos.x, moveToPos.y] = true;
                    (curPlayer ? newBoard.player1Pieces : newBoard.player2Pieces)[i] = moveToPos;
                    float newValue = newBoard.EvaluateBoard(n - 1, priorWeight, ref doesWin);
                    if (doesWin || (curPlayer ? (newValue > optimalValue) : (newValue < optimalValue)))
                    {
                        ret          = new Vector3Int(i, moveToPos.x, moveToPos.y);
                        optimalValue = newValue;
                    }
                }
            }

            Debug.Log("Optimal Value: " + optimalValue);
            return(ret);
        }
Example #4
0
        // use this to copy a VBoard, e.g. to test out certain moves:
        public VBoard(VBoard original)
        {
            boardArr = new bool[width, height];
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    boardArr[i, j] = original.boardArr[i, j];
                }
            }
            player1Pieces = new Vector2Int[original.player1Pieces.Length];
            for (int i = 0; i < original.player1Pieces.Length; i++)
            {
                player1Pieces[i] = original.player1Pieces[i];
            }
            player2Pieces = new Vector2Int[original.player2Pieces.Length];
            for (int i = 0; i < original.player2Pieces.Length; i++)
            {
                player2Pieces[i] = original.player2Pieces[i];
            }

            curPlayer      = !original.curPlayer;
            originalPlayer = original.originalPlayer;
        }