/// <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); } }
public int height; //Identifies in which height of the tree search is public MCTSNode(int id, MCTSNode parent, TetrisState state, PieceAction action, PieceModel currentPiece) { this.id = id; this.parent = parent; this.state = state; this.action = action; this.currentPiece = currentPiece; children = new List <MCTSNode>(); if (parent != null) { height = parent.height + 1; } else { height = 0; } MCTreeSearch.nNodes++; if (height > MCTreeSearch.currentHeight) { MCTreeSearch.currentHeight = height; } }
private void Awake() { // init all pieces allBeforeAttack = new PieceAction(() => { }); allAttack = new PieceAction(() => { }); allReset = new PieceAction(() => { }); }
/// <summary> /// Giving a TetrisState and a PieceAction, the piece model reproduces this action /// </summary> /// <param name="action"></param> /// <param name="tetrisState"></param> public void DoAction(PieceAction action, TetrisState tetrisState) { for (int i = 0; i < action.rotationIndex; i++) { Rotate(); } Move(new Vector2Int(action.xCoord - tileCoordinates[0].x, 0), tetrisState); }
public void PermanantRemovePiece(Piece p) { if (piecesGrid.ContainsKey(p.boardIdx)) { piecesGrid.Remove(p.boardIdx); } allAttack -= p.AutoAttack; allReset -= p.ResetAfterTurnEnd; allBeforeAttack -= p.BeforeAttack; pieceList.Remove(p); p.PieceDestroy(); Destroy(p.gameObject); }
/// <summary> /// It executes the action chosen by the bot /// </summary> /// <param name="action"></param> public void DoActionByBot(PieceAction action, bool debug = false) { /*if (debugMode && !debug) nextPieceAction = action; * else * {*/ for (int i = 0; i < action.rotationIndex; i++) { currentPiece.RotatePiece(true, true); } currentPiece.MovePiece(new Vector2Int(action.xCoord - currentPiece.tiles[0].Coordinates.x, 0)); currentPiece.DropPiece(true); //} }
public IEnumerator ShowPossibleActionCoroutine(PieceAction action) { for (int i = 0; i < action.rotationIndex; i++) { currentPiece.RotatePiece(true, true); } Vector2Int direction = new Vector2Int(action.xCoord - currentPiece.tiles[0].Coordinates.x, 0); currentPiece.MovePiece(direction); yield return(new WaitForSeconds(0.1f)); currentPiece.DropPiece(true, true); yield return(new WaitForSeconds(0.3f)); }
public void AddPiece(Piece p) { var idx = PosToNearIndex(p.transform.position.x, p.transform.position.z); if (CheckPiece(idx)) { Debug.LogError("[ERR-AddPiece] already piece on " + idx); } else { piecesGrid.Add(idx, p); p.boardIdx = idx; pieceList.Add(p); allAttack += p.AutoAttack; allReset += p.ResetAfterTurnEnd; allBeforeAttack += p.BeforeAttack; } }
public void FullyLoad() { PieceActions = new List <PieceAction>(); //Debug.Log("actions "+Actions); string[] s = Regex.Split(Actions, ", "); for (int j = 0; j < s.Length; j++) { for (int i = 0; i < ResourcesMaster.PieceActions.Count; i++) { PieceAction pa = ResourcesMaster.PieceActions[i]; if (pa != null && pa.Name.Equals(s[j])) { PieceActions.Add(pa); } else { //Debug.Log("Null Action"); } } } }
public PieceCommand(Piece piece, PieceAction pieceAction) { _piece = piece; _pieceAction = pieceAction; }
/// <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); }