Example #1
0
        public IEnumerable <MapInfo> GenerationSteps(int width, int height, string seed)
        {
            Map map = new Map(width, height, Layers.Effects + 1, Distance.MANHATTAN);

            LightMap lightMap = new LightMap(width, height, map.TransparencyView);

            MapInfo mapInfo = new MapInfo(map, lightMap);

            ResettableRandom rng = new ResettableRandom(seed);

            return(_biome.GenerateOn(new Floor(0, _timeline, mapInfo, new Spawner(map), new GoalMapStore(map), _messageBus), new Rectangle(0, 0, width, height), rng));
        }
Example #2
0
        public IEnumerable <MapInfo> GenerateOn(Floor floor, Rectangle area, ResettableRandom rng)
        {
            GenerationContext context = new GenerationContext(rng);
            MapInfo           mapInfo = floor.MapInfo;

            Bag <RoomConnection> pendingConnections = new Bag <RoomConnection>(rng);
            List <IRoom>         rooms = new List <IRoom>();

            Rectangle initialRoomRect = new Rectangle(new Coord(20, 20), 3, 3);
            SourceCursor <IRoomGenerator> initialSourceCursor = _rootRoomSource.Pull(context);
            IRoomGenerator initialRoomGenerator = initialSourceCursor.Value;

            initialSourceCursor.Use();

            IRoom initialRoom = initialRoomGenerator.Generate(floor, new RoomConnection(new Coord(area.Width / 4, area.Height / 2), Direction.NONE, null, false), rng);

            floor.Entrance = initialRoom.Area.Bounds.Center;

            pendingConnections.PutRange(initialRoom.PotentialConnections);

            yield return(mapInfo);

            int n = 0;

            while (pendingConnections.Count > 0 && n < 1000)
            {
                RoomConnection nextConnection = pendingConnections.Get(true);

                Coord hallEnd = nextConnection.Position +
                                new Coord(nextConnection.Direction.DeltaX, nextConnection.Direction.DeltaY) * rng.Next(1, 8);

                RoomConnection hallConnection = new RoomConnection(hallEnd, nextConnection.Direction, null, false);

                if (nextConnection.Possibilities.IsEmpty())
                {
                    n += 1;
                    continue;
                }

                SourceCursor <IRoomGenerator> generatorCursor = nextConnection.Possibilities.Pull(context);

                IRoomGenerator generator = generatorCursor.Value;

                int[] rngState = rng.GetState();

                if (!generator.CanGenerate(floor, hallConnection, rng))
                {
                    pendingConnections.Put(nextConnection);
                    n += 1;
                    continue;
                }

                rng.LoadState(rngState);

                IRoom room = generator.Generate(floor, hallConnection, rng);
                rooms.Add(room);

                generatorCursor.Use();

                pendingConnections.PutRange(room.PotentialConnections);

                yield return(mapInfo);


                SourceCursor <IHallGenerator> hallGeneratorCursor = _hallGenerators.Pull(context);;
                IHallGenerator hallGenerator = hallGeneratorCursor.Value;

                if (!hallGenerator.CanGenerate(floor, nextConnection.Position, hallEnd, rng))
                {
                    continue;
                }

                IRoom hall = hallGenerator.Generate(floor, nextConnection.Position, hallEnd, rng);
                hallGeneratorCursor.Use();

                yield return(mapInfo);

                n += 1;
            }

            while (pendingConnections.Count > 0)
            {
                RoomConnection nextConnection = pendingConnections.Get(true);
                Coord          hit            = Trace(mapInfo.Map, nextConnection.Position, nextConnection.Direction);

                if (hit == Coord.NONE)
                {
                    continue;
                }

                if (Distance.MANHATTAN.Calculate(nextConnection.Position, hit) > 10)
                {
                    continue;
                }

                if (mapInfo.Map.AStar.ShortestPath(nextConnection.Position, hit) is Path shortestPath && shortestPath.Length < 40)
                {
                    continue;
                }

                SourceCursor <IHallGenerator> hallGeneratorCursor = _hallGenerators.Pull(context);;
                IHallGenerator hallGenerator = hallGeneratorCursor.Value;

                if (!hallGenerator.CanGenerate(floor, nextConnection.Position, hit, rng))
                {
                    continue;
                }

                IRoom hall = hallGenerator.Generate(floor, nextConnection.Position, hit, rng);
                hallGeneratorCursor.Use();


                yield return(mapInfo);
            }

            foreach (Coord pos in area.Positions())
            {
                if (mapInfo.Map.GetTerrain(pos) == null)
                {
                    mapInfo.Map.SetTerrain(SolidRock(pos));
                }
            }

            Console.WriteLine($"num rooms: {rooms.Count}");

            foreach (IRoom room in rooms)
            {
                room.GeneratedBy.Populate(floor, room, rng);
            }



            // place exit
            while (true)
            {
                IRoom randomRoom = rooms.RandomItem(rng);
                Coord randomPos  = randomRoom.Area.Perimeter().ToList().RandomItem(rng);

                if (mapInfo.Map.WalkabilityView[randomPos] == false &&
                    mapInfo.Map.AStar.ShortestPath(floor.Entrance, randomPos) is Path shortestPath && shortestPath.Length > 50 &&
                    mapInfo.Map.GetObject(randomPos, mapInfo.Map.LayerMasker.Mask(Layers.Main)) == null)
                {
                    mapInfo.Map.SetTerrain(Exit(floor, randomPos));
                    floor.Exit = randomPos;
                    break;
                }
            }

            Console.WriteLine($"leftover connections = {pendingConnections.Count}");
        }