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)); }
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}"); }