예제 #1
0
    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");
    }
예제 #3
0
    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);
    }
예제 #4
0
    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
예제 #6
0
        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();
        }