public void GenerateChunk(int xStart, int yStart, Chunk chunk) { Tilemap tilemap = chunk.ChunkTilemap; chunk.transform.position = new Vector3(xStart, yStart, 0); for (int x = 0; x < ChunkSize; x++) { for (int y = 0; y < ChunkSize; y++) { DestructibleTile toSet = null; int baseOre = 0; float perlin = MainPerlin.GetPerlin(x + xStart, y + yStart); float solidThreshold = SolidThresholdPerlin.GetPerlin(x + xStart, y + yStart); //if we're generating a solid tile: if (perlin > solidThreshold) { //check whether it should be explosive if (ShouldBeExplosive(x + xStart, y + yStart)) { toSet = ExplosiveTiles[0]; //tilemap.SetTile(new Vector3Int(x, y, 0), newTile); } else { //determine how much ore the tile should have float normOre = Mathf.InverseLerp(solidThreshold, 1, perlin); normOre = Mathf.InverseLerp(.5f, 1, normOre); int oreAmount = Mathf.FloorToInt(normOre / (1.0f / OreTiles.Length)); oreAmount = Mathf.Clamp(oreAmount, 0, OreTiles.Length); baseOre = oreAmount; //set the tile to the normal tile thing toSet = TerrainTiles[0]; //tilemap.SetTile(new Vector3Int(x, y, 0), newTile); } } else { //tilemap.SetTile(new Vector3Int(x, y, 0), null); //chunk.ForegroundTilemap.SetTile(new Vector3Int(x, y, 0), null); //chunk.OreAmount[x, y] = 0; } chunk.SetTile(x, y, toSet, baseOre); } } chunk.ApplyTiles(); chunk.Caverns = Cavern.GetChunkCaverns(chunk, chunk.MinCavernSize); if (chunk.Caverns.Count > 0) { chunk.BiggestCavern = chunk.Caverns.Aggregate((i1, i2) => i1.AirTiles.Count > i2.AirTiles.Count ? i1 : i2); } else { chunk.BiggestCavern = null; } GenerateLevelFeatures(chunk); }
} // <3 private void CreatePath(Cavern caveA, Cavern caveB, PreciseTileChecker tileA, PreciseTileChecker tileB) { Cavern.ConnectCaves(caveA, caveB); //Debug.Log("Tile A ID:" + mapTiles[col * tileA.tileX + tileA.tileY].TileID + " Tile B ID:" + mapTiles[col * tileB.tileX + tileB.tileY].TileID); //Debug.Log("Tile A X:" + tileA.tileX + " Tile A Y:" + tileA.tileY + " Tile B X:" + tileB.tileX + " Tile B Y:" + tileB.tileY); //Debug.Log("Begin Line"); List <PreciseTileChecker> line = GetPassageTiles(tileA, tileB); foreach (PreciseTileChecker t in line) { //Debug.Log("Tile X: " + t.tileX + " Tile Y: " + t.tileY + " Tile ID: " + (col * t.tileX + t.tileY)); DrawPassage(t, 1); } //Debug.Log("End Line"); }
public static List <Cavern> GetChunkCaverns(Chunk chunk, int minCavernSize = 0) { List <Cavern> result = new List <Cavern>(); Tilemap tilemap = chunk.ChunkTilemap; int[,] visitedTiles = new int[chunk.ChunkSize, chunk.ChunkSize]; for (int x = 0; x < chunk.ChunkSize; x++) { for (int y = 0; y < chunk.ChunkSize; y++) { //if we haven't visited this yet, check it if (visitedTiles[x, y] == 0) { Vector3Int coord = new Vector3Int(x, y, 0); TileBase tile = tilemap.GetTile(coord); //empty tile if (tile == null) { Cavern newCavern = FloodfillCavern(coord, tilemap, ref visitedTiles); if (newCavern.AirTiles.Count > minCavernSize) { result.Add(newCavern); } } else { visitedTiles[x, y] = 1; //mark the tile if it isn't an empty one } } //don't need to do anything if we have visited, just continue } } return(result); }
private static Cavern FloodfillCavern(Vector3Int start, Tilemap tilemap, ref int[,] visitedTiles) { Cavern result = new Cavern(); Queue <Vector3Int> toCheck = new Queue <Vector3Int>(); toCheck.Enqueue(start); while (toCheck.Count > 0) { Vector3Int curCoord = toCheck.Dequeue(); result.AddTile(curCoord); visitedTiles[curCoord.x, curCoord.y] = 1; Vector3Int nextLoc = curCoord; bool addToOutline = false; bool addToWall = false; //can check left if (curCoord.x > 0) { nextLoc.x = curCoord.x - 1; if (tilemap.GetTile(nextLoc) == null) { //check if not visited if (visitedTiles[nextLoc.x, nextLoc.y] == 0) { toCheck.Enqueue(nextLoc); } } else { addToOutline = true; addToWall = true; } visitedTiles[nextLoc.x, nextLoc.y] = 1; } //can check right if (curCoord.x < visitedTiles.GetUpperBound(0)) { nextLoc.x = curCoord.x + 1; if (tilemap.GetTile(nextLoc) == null) { //check if not visited if (visitedTiles[nextLoc.x, nextLoc.y] == 0) { toCheck.Enqueue(nextLoc); } } else { addToOutline = true; addToWall = true; } visitedTiles[nextLoc.x, nextLoc.y] = 1; } //can check above if (curCoord.y < visitedTiles.GetUpperBound(0)) { nextLoc.x = curCoord.x; nextLoc.y = curCoord.y + 1; if (tilemap.GetTile(nextLoc) == null) { //check if not visited if (visitedTiles[nextLoc.x, nextLoc.y] == 0) { toCheck.Enqueue(nextLoc); } } else { addToOutline = true; result.CeilingTiles.Add(curCoord); } visitedTiles[nextLoc.x, nextLoc.y] = 1; } //can check below if (curCoord.y > 0) { nextLoc.x = curCoord.x; nextLoc.y = curCoord.y - 1; if (tilemap.GetTile(nextLoc) == null) { //check if not visited if (visitedTiles[nextLoc.x, nextLoc.y] == 0) { toCheck.Enqueue(nextLoc); } } else { addToOutline = true; result.FloorTiles.Add(curCoord); } visitedTiles[nextLoc.x, nextLoc.y] = 1; } if (addToOutline) { result.CavernOutlineCoordinates.Add(curCoord); } else { result.AirTiles.Add(curCoord); } if (addToWall) { result.WallTiles.Add(curCoord); } } return(result); }
private void ConnectCaverns(List <Cavern> Caves, bool forceAccessibilityFromMain = false) { List <Cavern> caveListA = new List <Cavern>(); List <Cavern> caveListB = new List <Cavern>(); if (forceAccessibilityFromMain) { foreach (Cavern cave in Caves) { if (cave.isAccessibleFromMainCavern) { caveListB.Add(cave); } else { caveListA.Add(cave); } } } else { caveListA = Caves; caveListB = Caves; } int closestDistance = 0; PreciseTileChecker bestTileA = new PreciseTileChecker(); PreciseTileChecker bestTileB = new PreciseTileChecker(); Cavern bestCaveA = new Cavern(); Cavern bestCaveB = new Cavern(); bool connectonFound = false; foreach (Cavern caveA in caveListA) { if (!forceAccessibilityFromMain) { connectonFound = false; if (caveA.connectedCaverns.Count > 0) { continue; } } foreach (Cavern caveB in caveListB) { if (caveA == caveB || caveA.IsConnected(caveB)) { continue; } for (int tileIndexA = 0; tileIndexA < caveA.edges.Count; tileIndexA++) { for (int tileIndexB = 0; tileIndexB < caveB.edges.Count; tileIndexB++) { PreciseTileChecker tileA = caveA.edges[tileIndexA]; PreciseTileChecker tileB = caveB.edges[tileIndexB]; int distance = (int)(Mathf.Pow((tileA.tileX - tileB.tileX), 2) + Mathf.Pow((tileA.tileY - tileB.tileY), 2)); if (distance < closestDistance || !connectonFound) { closestDistance = distance; connectonFound = true; bestTileA = tileA; bestTileB = tileB; bestCaveA = caveA; bestCaveB = caveB; } } } } if (connectonFound && !forceAccessibilityFromMain) { CreatePath(bestCaveA, bestCaveB, bestTileA, bestTileB); } } if (connectonFound && forceAccessibilityFromMain) { CreatePath(bestCaveA, bestCaveB, bestTileA, bestTileB); ConnectCaverns(Caves, true); } if (!forceAccessibilityFromMain) { ConnectCaverns(Caves, true); } } // <3
public static void Run() { var lines = File.ReadAllLines("input.txt"); var initialState = lines[0].Substring(15); var rules = new List <Rule>(); for (int l = 2; l < lines.Length; l++) { var rule = new Rule(lines[l]); rules.Add(rule); } cavern = new Cavern(initialState); //Console.WriteLine(cavern.ToString(cavern.CurrentGeneration, -3, 35)); for (int g = 1; g <= 20; g++) { var instructions = new List <Instruction>(); var currentGeneration = cavern.Generations[cavern.CurrentGeneration]; var currentGenerationString = currentGeneration.ToString(); var generationString = currentGenerationString; int minRange = currentGeneration.MinRange; int maxRange = currentGeneration.MaxRange; //if (currentGenerationString.StartsWith("#")) { minRange -= 3; generationString = "..." + generationString; //} //if (currentGenerationString.EndsWith("#")) { maxRange += 3; generationString = generationString + "..."; //} foreach (var rule in rules) { var result = rule.Valid(minRange, generationString); if (result.Count > 0) { foreach (int potId in result) { instructions.Add(new Instruction { PotId = potId, CreatesAPlant = rule.CreatesAPlant }); } } } var generation = new Generation(minRange, new string('.', maxRange - minRange)); foreach (var instruction in instructions) { var pot = generation.Pots[instruction.PotId]; pot.HasPlant = instruction.CreatesAPlant; generation.Pots[instruction.PotId] = pot; } cavern.NextGeneration(minRange, generation.ToString()); //Console.WriteLine(cavern.ToString(cavern.CurrentGeneration, -3, 35)); } var lastGeneration = cavern.Generations[20]; int sum = 0; foreach (var kvp in lastGeneration.Pots) { if (kvp.Value.HasPlant) { sum += kvp.Key; } } //Console.WriteLine(lastGeneration.ToString()); Console.WriteLine(sum); //AssertMockInput(); }