Exemple #1
0
    /// <summary>
    /// Executes random actions with the next pieces over the state of node
    /// </summary>
    /// <param name="node"></param>
    /// <returns></returns>
    protected virtual float Rollout(MCTSNode node)
    {
        TetrisState newState = node.state.CloneState();

        int nPieces = 0;

        float totalScore  = node.state.GetScore();
        float weight      = 1f;
        float totalWeight = weight;

        //node.height identifies the height of the node in the MCTreeSearch, but also identifies the index of the piece inside the history of all the pieces played
        //So, if that node.height plus the number of pieces played in the rollout are bigger than the number of known pieces, then the rollout must stop.
        //Also it stops if an action has caused a game over
        while ((node.height + nPieces) < pieces.Count && !newState.IsTerminal())
        {
            weight      *= rolloutScoreWeightReduction;
            totalWeight += weight;

            PieceModel piece;
            piece = new PieceModel(pieces[node.height + nPieces]);

            newState.DoAction(piece, newState.GetRandomAction(piece));
            nPieces++;

            totalScore += newState.GetScore() * weight;
        }

        float score = totalScore / totalWeight;

        rollouts++;

        return(score);
    }
Exemple #2
0
    /// <summary>
    /// Uses also the budget in order to make a fair calculation: if the budget is consumed checking the Tetris, then it stops
    /// </summary>
    /// <param name="nextPiece"></param>
    /// <param name="currentTetrisState"></param>
    /// <param name="possibleActions"></param>
    /// <param name="budget"></param>
    /// <returns></returns>
    protected IEnumerator CheckTetris(PieceModel nextPiece, TetrisState currentTetrisState, List <PieceAction> possibleActions, float budget)
    {
        int i = 0;

        while (t0 < budget && i < possibleActions.Count)
        {
            if (!TBController.pausedGame)
            {
                t0 += Time.deltaTime;

                PieceAction action = possibleActions[i];
                if (action.rotationIndex == 0) //The I piece is horizontal, not vertical, so it can't be a Tetris
                {
                    i++;
                    continue;
                }

                TetrisState newState = currentTetrisState.CloneState();

                newState.DoAction(nextPiece, action);
                nextPiece.ResetCoordinates();

                if (newState.IsTetris())
                {
                    bestAction = action;
                }

                i++;
            }

            yield return(null);
        }
    }
Exemple #3
0
    /// <summary>
    /// Creates the children of this node with a given new piece
    /// </summary>
    /// <param name="newCurrentPiece"></param>
    public void ExtendNode(PieceModel newCurrentPiece)
    {
        List <PieceAction> actions = state.GetActions(newCurrentPiece);

        foreach (PieceAction action in actions) //Each child is related with one of the possible actions for the newCurrentPiece played in the state of this node
        {
            TetrisState newState = state.CloneState();
            newState.DoAction(newCurrentPiece, action);

            newCurrentPiece.ResetCoordinates();

            MCTSNode newNode = new MCTSNode(MCTreeSearch.nNodes, this, newState, action, newCurrentPiece);
            children.Add(newNode);
        }
    }
Exemple #4
0
    /// <summary>
    /// Main loop of the bot. It's based on the same method of TetrisBot, but with the add-on that checks if a Tetris can be played
    /// </summary>
    /// <param name="nextPieceType"></param>
    /// <param name="budget"></param>
    /// <returns></returns>
    public override IEnumerator ActCoroutine(PieceType nextPieceType, float budget)
    {
        t0 = 0.0f;

        PieceModel nextPiece = new PieceModel(nextPieceType);

        List <PieceAction> possibleActions = currentTetrisState.GetActions(nextPiece);

        bestAction = null;

        yield return(null);

        t0 += Time.deltaTime;

        //If the currentPiece is a I piece, the Tetris is checked since there is no possibility to make a Tetris with another type of piece
        if (nextPieceType == PieceType.I)
        {
            CheckTetris(nextPiece, currentTetrisState, possibleActions, budget);
        }

        //If there is no possibility of Tetris, the same algorithm than TetrisBot is played
        if (bestAction == null)
        {
            float bestScore = -float.MaxValue;

            int i            = Random.Range(0, possibleActions.Count);
            int initialIndex = i;
            while (t0 < budget)
            {
                if (!TBController.pausedGame)
                {
                    t0 += Time.deltaTime;

                    TetrisState newState = currentTetrisState.CloneState();

                    newState.DoAction(nextPiece, possibleActions[i]);
                    nextPiece.ResetCoordinates();

                    float score = newState.GetHumanizedScore();

                    if (score > bestScore)
                    {
                        bestScore  = score;
                        bestAction = possibleActions[i];
                    }

                    i++;

                    if (i == possibleActions.Count)
                    {
                        i = 0;
                    }
                    if (i == initialIndex)
                    {
                        break;
                    }
                }

                yield return(null);
            }
        }
        else
        {
            Debug.Log("BOOM! Tetris for bot");
        }

        //If there is no bestAction at this point, a random action is going to be played
        if (bestAction == null)
        {
            bestAction = currentTetrisState.GetRandomAction(nextPiece);
        }
        currentTetrisState.DoAction(nextPiece, bestAction);

        TBController.DoActionByBot(bestAction);
    }
Exemple #5
0
    /// <summary>
    /// Main bot method that searches for the best action to do with the current piece in the current state.
    /// It has a budget of time which is the max time it has to find that best action
    /// </summary>
    /// <param name="nextPieceType"></param>
    /// <param name="budget"></param>
    /// <returns></returns>
    public virtual IEnumerator ActCoroutine(PieceType nextPieceType, float budget)
    {
        float t0 = 0.0f;

        PieceModel nextPiece = new PieceModel(nextPieceType);

        List <PieceAction> possibleActions; //First of all, it gets the possible actions with the current piece in the current state

        if (!pieceActionDictionary.ContainsKey(nextPieceType))
        {
            possibleActions = emptyTetrisState.GetActions(nextPiece);
            pieceActionDictionary.Add(nextPieceType, possibleActions);
        }
        else
        {
            possibleActions = pieceActionDictionary[nextPieceType];
        }

        float       bestScore = -float.MaxValue;
        PieceAction bestAction;

        int i            = Random.Range(0, possibleActions.Count); //The first possible action to test is chosen randomly
        int initialIndex = i;

        bestAction = possibleActions[i];

        yield return(null);

        t0 += Time.deltaTime;

        //In a while loop that goes until the time ends
        while (t0 < budget && i < possibleActions.Count)
        {
            if (!TBController.pausedGame)
            {
                t0 += Time.deltaTime;

                TetrisState newState = currentTetrisState.CloneState(); //The TetrisState is cloned

                newState.DoAction(nextPiece, possibleActions[i]);       //One of the possible actions is played in the cloned state
                nextPiece.ResetCoordinates();

                float score = newState.GetScore(); //And its score is got

                if (score > bestScore)
                {
                    bestScore  = score;
                    bestAction = possibleActions[i];
                }

                i++;

                if (i == possibleActions.Count)
                {
                    i = 0;
                }
                if (i == initialIndex)
                {
                    break;                    //If all the possible actions have been tested, the while loop ends
                }
            }

            yield return(null);
        }

        currentTetrisState.DoAction(nextPiece, bestAction); //The bestAction is played in the real state

        TBController.DoActionByBot(bestAction);             //And also, it is said to the TetrisBoardController to play that action in the real board
    }