diff --git a/Assets/RealCode/GameBoard.cs b/Assets/RealCode/GameBoard.cs index 2d12bb5..98f893a 100644 --- a/Assets/RealCode/GameBoard.cs +++ b/Assets/RealCode/GameBoard.cs @@ -50,6 +50,8 @@ public class GameBoard : EntityBase, IAutoSerialize, IAutoDeserialize { // Tile timing private int TilesUntilActivator = 3; int nextActivator = -1; + private int ActivatorsUntilSpecial = 10; + int nextSpecial = -1; public float nextRootX = -1, nextRootY = 12; @@ -64,6 +66,11 @@ public class GameBoard : EntityBase, IAutoSerialize, IAutoDeserialize { activator = TileInfo.CreateRandomActivatorTile(); lastActivatorColor = activator.color; + + if (++nextSpecial >= ActivatorsUntilSpecial) { + nextSpecial = 0; + activator.kind = TileKind.Special; + } if (Random.value > 0.5f) { pair.left = activator; @@ -108,8 +115,9 @@ public class GameBoard : EntityBase, IAutoSerialize, IAutoDeserialize { case DelayState.Collapse: if (timeInState > airCollapseTime) { board = Collapse(board); // Remove air + board = SpecialActivation(board, out bool didSpecial); board = ActivateOnce(board, out bool didActivate); - if (didActivate) { + if (didActivate || didSpecial) { delayState = DelayState.Combo; ++Combo; } else { @@ -459,6 +467,48 @@ public class GameBoard : EntityBase, IAutoSerialize, IAutoDeserialize { return bs; } + // Activate all special tiles + BoardState SpecialActivation(BoardState bs, out bool didActivate) { + + didActivate = false; + //return bs; // Test short-circuit + + for (int x = 0; x < bs.Count; ++x) { + var col = bs[x]; + for (int y = 0; y < col.Count; ++y) { + var tile = col[y]; + if (tile.kind == TileKind.Special) { + if (y > 0) { + // Get the color of the tile we are on top of + var under = col[y - 1]; + tile.kind = TileKind.Activiting; + tile.color = under.color; + bs = ActivateAllColor(bs, under.color); + didActivate = true; + } else { + // Special tile is on the bottom, swap it to a random activating tile + tile = TileInfo.CreateRandomActivatorTile(); + } + } + } + } + return bs; + } + + BoardState ActivateAllColor(BoardState bs,TileColor tc) { + for (int x = 0; x < bs.Count; ++x) { + var col = bs[x]; + for (int y = 0; y < col.Count; ++y) { + var tile = col[y]; + if (tile.color == tc) { + tile.kind = TileKind.Activiting; + } + } + } + + return bs; + } + int CountActivations(BoardState bs) { int total = 0; foreach(var col in bs) { @@ -620,12 +670,16 @@ public class GameBoard : EntityBase, IAutoSerialize, IAutoDeserialize { public void Setup(){ board = BoardStateExtension.Initialize(); + StopAllCoroutines(); // Murder all coroutines :'D + // This is to reset the AI + // Build the list of possible placements the AI may use PossiblePlacements = GetAllPossibilities(); lastActivatorColor = TileInfo.CreateRandomActivatorTile().color; nextActivator = TilesUntilActivator; + nextSpecial = ActivatorsUntilSpecial; delayState = DelayState.None; timeInState = 0; @@ -690,6 +744,8 @@ public class GameBoard : EntityBase, IAutoSerialize, IAutoDeserialize { repeat = false; bs = Collapse(bs); bs = Activate(bs); + bs = SpecialActivation(bs, out bool didActivate); + var newActivations = CountActivations(bs); if (newActivations > 0) { comboLength += 1; @@ -811,14 +867,21 @@ public class GameBoard : EntityBase, IAutoSerialize, IAutoDeserialize { } [ContextMenu("Startup AI")] - public void StartAI() { + public void StartAIDefault() { + StartAI(); + } + + public void StartAI(float thinkTime = 0.5f) { AIEnabled = true; + AIMoveTime = thinkTime; StartCoroutine(AIThink()); } public bool AIEnabled = false; public float AIMoveTime = 0.5f; IEnumerator AIThink() { + yield return null; // Wait a frame before trying any shit + int totalMoves = 0; while (delayState != DelayState.Loss) { if (!AIEnabled) diff --git a/Assets/RealCode/GameBoardInstance.cs b/Assets/RealCode/GameBoardInstance.cs index cc6f553..bef26e9 100644 --- a/Assets/RealCode/GameBoardInstance.cs +++ b/Assets/RealCode/GameBoardInstance.cs @@ -14,6 +14,9 @@ public class GameBoardInstance : MonoBehaviour { public Sprite[] lit; public Sprite[] activators; + [Header("AI difficulty, 0(easy)-3(hardest)")] + public int AIDifficulty = 1; + private void Awake() { instance = this; } @@ -31,11 +34,13 @@ public class GameBoardInstance : MonoBehaviour { player2.Setup(); } else { player1.authorityID = -1; - player2.authorityID = -1; + player2.authorityID = -1; player1.Setup(); player2.Setup(); - } + + player2.StartAI(new[] { 0.5f, 0.2f, 0.1f, 0f }[AIDifficulty]); + } GameTransition.Instance.state = GameState.InGame; } diff --git a/Assets/RealCode/TileRender.cs b/Assets/RealCode/TileRender.cs index 0cfedfe..cc700d2 100644 --- a/Assets/RealCode/TileRender.cs +++ b/Assets/RealCode/TileRender.cs @@ -26,6 +26,10 @@ public class TileRender : MonoBehaviour { case TileKind.Activiting: sprites = GameBoardInstance.instance.lit; break; + case TileKind.Special: + int timeSprite = (int)(Time.time * 4); + renderer.sprite = GameBoardInstance.instance.activators[timeSprite % 4]; + return; default: sprites = null; Debug.LogErrorFormat(this.gameObject,"{0}, {1}, {2} not supported by tile display", tile.color, tile.kind, tile.counter);