/** * Resets the grid and creates a new path. The higher the * difficulty, the shorter the generated path will be. */ public void GeneratePath(GameState.Difficulty diff) { UpdateDimension(Width, Length); Position pos = (Position)startPos.Clone(); Position waypoint = (Position)startPos.Clone(); Direction dir = Direction.right; int tilesToExpand = 0; while (true) { // reached the end, done if (pos == endPos) { return; } // figure out how many tiles we CAN expand in the current direction int availableTiles = pos.AvailableUnitsUntilBorder(this, dir); Debug.Assert(availableTiles > 0); Debug.Assert(dir != Direction.up); // should not go up! // figure out how many tiles we WILL expand based on difficulty switch (diff) { case (GameState.Difficulty.easy): if (dir == Direction.right || dir == Direction.left) { tilesToExpand = UnityEngine.Random.Range( Math.Min(1, (int)(availableTiles * 0.9f)), availableTiles + 1); // +1 because Random.Range is exclusive for end } else { tilesToExpand = 2; // go down two at a time to ensure maximum length } break; case (GameState.Difficulty.medium): if (dir == Direction.right || dir == Direction.left) { tilesToExpand = UnityEngine.Random.Range( Math.Min(1, (int)(availableTiles * 0.4f)), Math.Min(1, (int)(availableTiles * 0.8f)) + 1); } else { tilesToExpand = UnityEngine.Random.Range(2, 4); } break; case (GameState.Difficulty.hard): if (dir == Direction.right || dir == Direction.left) { tilesToExpand = UnityEngine.Random.Range( Math.Min(1, (int)(availableTiles * 0.4f)), Math.Min(1, (int)(availableTiles * 0.2f)) + 1); } else { tilesToExpand = 3; } break; default: Debug.LogError("Invalid difficulty received: " + diff.ToString()); return; } tilesToExpand = Math.Min(tilesToExpand, availableTiles); // move the waypoint to the destination waypoint.Move(tilesToExpand, dir); // double check that all assumptions are valid // Debug.Log("# tiles to expand: " + tilesToExpand + ", destination: " + waypoint.ToString() + ", direction: " + dir.ToString()); Debug.Assert(!waypoint.IsOnBorder(this)); Debug.Assert(!waypoint.OutOfBound(this)); Debug.Assert( state[waypoint.X, waypoint.Y] == TileType.terrain || state[waypoint.X, waypoint.Y] == TileType.end); Debug.Assert(waypoint.X <= endPos.X); Debug.Assert(waypoint.Y <= endPos.Y); // if at the bottom-most row and moving right, then bring the path to the finish line if (waypoint.Y == endPos.Y && waypoint.X != endPos.X && dir == Direction.right) { waypoint.UpdatePosition(endPos.X, endPos.Y); } // if one or two units above end point, bring the path to finish line if (endPos.Y - waypoint.Y <= 2 && waypoint.X == endPos.X && dir == Direction.down) { waypoint.UpdatePosition(endPos.X, endPos.Y); } // save the waypoint waypoints.Add((Position)waypoint.Clone()); // update the state to build the path while (true) { pos.Move(1, dir); if (pos == endPos) { break; } state[pos.X, pos.Y] = TileType.path; if (pos == waypoint) { break; } } // ============================================ // figure out direction for the next iteration // ============================================ // if at the bottom row, just go right next time so it will hit the end if (pos.Y == length - 2) { dir = Direction.right; continue; } if (dir == Direction.right || dir == Direction.left) { dir = Direction.down; continue; } if (dir == Direction.down) { // if current row is one above the end point, go down one more if (pos.Y + 1 == endPos.Y) { dir = Direction.down; continue; } int leftRoom = pos.AvailableUnitsUntilBorder(this, Direction.left); int rightRoom = pos.AvailableUnitsUntilBorder(this, Direction.right); dir = leftRoom > rightRoom ? Direction.left : Direction.right; continue; } } }
public void GenerateMaze(GameState.Difficulty difficulty) { currentGrid.GeneratePath(difficulty); DrawTiles(); }