public override void DrawOnMap(T map) { for (int x = 0; x < this.Draw.Size.X; x++) { for (int y = 0; y < this.Draw.Size.Y; y++) { map.SetTile(new Loc(this.Draw.X + x, this.Draw.Y + y), map.RoomTerrain.Copy()); } } GenContextDebug.DebugProgress("Room Rect"); Loc blockSize = new Loc(Math.Min(this.BlockWidth.Pick(map.Rand), this.Draw.Size.X - 2), Math.Min(this.BlockHeight.Pick(map.Rand), this.Draw.Size.Y - 2)); Loc blockStart = new Loc(this.Draw.X + map.Rand.Next(1, this.Draw.Size.X - blockSize.X - 1), this.Draw.Y + map.Rand.Next(1, this.Draw.Size.Y - blockSize.Y - 1)); for (int x = 0; x < blockSize.X; x++) { for (int y = 0; y < blockSize.Y; y++) { map.SetTile(new Loc(blockStart.X + x, blockStart.Y + y), this.BlockTerrain.Copy()); } } GenContextDebug.DebugProgress("Block Rect"); // hall restrictions this.SetRoomBorders(map); }
public override void ApplyToPath(IRandom rand, FloorPlan floorPlan) { int amount = this.Amount.Pick(rand); for (int kk = 0; kk < amount; kk++) { FloorPathBranch <T> .ListPathBranchExpansion?expansionResult = this.ChooseRoomExpansion(rand, floorPlan); if (!expansionResult.HasValue) { continue; } var expansion = expansionResult.Value; RoomHallIndex from = expansion.From; if (expansion.Hall != null) { floorPlan.AddHall(expansion.Hall, this.HallComponents.Clone(), from); from = new RoomHallIndex(floorPlan.HallCount - 1, true); } floorPlan.AddRoom(expansion.Room, this.RoomComponents.Clone(), from); GenContextDebug.DebugProgress("Extended with Room"); } }
private (int area, int rooms) ExpandPath(IRandom rand, FloorPlan floorPlan, bool branch) { ListPathBranchExpansion?expansionResult = this.ChooseRoomExpansion(rand, floorPlan, branch); if (!expansionResult.HasValue) { return(0, 0); } var expansion = expansionResult.Value; int tilesCovered = 0; int roomsAdded = 0; RoomHallIndex from = expansion.From; if (expansion.Hall != null) { floorPlan.AddHall(expansion.Hall, this.HallComponents.Clone(), from); from = new RoomHallIndex(floorPlan.HallCount - 1, true); tilesCovered += expansion.Hall.Draw.Area; roomsAdded++; } floorPlan.AddRoom(expansion.Room, this.RoomComponents.Clone(), from); tilesCovered += expansion.Room.Draw.Area; roomsAdded++; GenContextDebug.DebugProgress(branch ? "Branched Path" : "Extended Path"); // report the added area coverage return(tilesCovered, roomsAdded); }
public override void ApplyToPath(IRandom rand, GridPlan floorPlan) { List <int> candidates = new List <int>(); for (int ii = 0; ii < floorPlan.RoomCount; ii++) { if (!floorPlan.GetRoomPlan(ii).Immutable) { List <int> adjacents = floorPlan.GetAdjacentRooms(ii); if (adjacents.Count > 1) { candidates.Add(ii); } } } // our candidates are all rooms except immutables and terminals int amountToDefault = this.DefaultRatio.Pick(rand) * candidates.Count / 100; for (int ii = 0; ii < amountToDefault; ii++) { int randIndex = rand.Next(candidates.Count); GridRoomPlan plan = floorPlan.GetRoomPlan(candidates[randIndex]); plan.RoomGen = new RoomGenDefault <T>(); plan.PreferHall = true; candidates.RemoveAt(randIndex); GenContextDebug.DebugProgress("Defaulted Room"); } }
// an initial create-map method public T GenMap(ulong seed) { // may not need floor ID T map = (T)Activator.CreateInstance(typeof(T)); map.InitSeed(seed); GenContextDebug.DebugInit(map); // postprocessing steps: StablePriorityQueue <Priority, IGenStep> queue = new StablePriorityQueue <Priority, IGenStep>(); foreach (Priority priority in this.GenSteps.GetPriorities()) { foreach (IGenStep genStep in this.GenSteps.GetItems(priority)) { queue.Enqueue(priority, genStep); } } ApplyGenSteps(map, queue); map.FinishGen(); return(map); }
public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns) { List <Loc> freeTiles = new List <Loc>(); for (int xx = 0; xx < map.Width; xx++) { for (int yy = 0; yy < map.Height; yy++) { ITile tile = map.GetTile(new Loc(xx, yy)); if (tile.TileEquivalent(this.Terrain)) { freeTiles.Add(new Loc(xx, yy)); } } } for (int ii = 0; ii < spawns.Count && freeTiles.Count > 0; ii++) { TSpawnable item = spawns[ii]; int randIndex = map.Rand.Next(freeTiles.Count); map.PlaceItem(freeTiles[randIndex], item); freeTiles.RemoveAt(randIndex); GenContextDebug.DebugProgress("Placed Object"); } }
public virtual void SpawnRandInCandRooms(TGenContext map, SpawnList <RoomHallIndex> spawningRooms, List <TSpawnable> spawns, int successPercent) { while (spawningRooms.Count > 0 && spawns.Count > 0) { int randIndex = spawningRooms.PickIndex(map.Rand); RoomHallIndex roomIndex = spawningRooms.GetSpawn(randIndex); // try to spawn the item if (this.SpawnInRoom(map, roomIndex, spawns[spawns.Count - 1])) { GenContextDebug.DebugProgress("Placed Object"); // remove the item spawn spawns.RemoveAt(spawns.Count - 1); if (successPercent <= 0) { spawningRooms.RemoveAt(randIndex); } else { int newRate = Math.Max(1, spawningRooms.GetSpawnRate(randIndex) * successPercent / 100); spawningRooms.SetSpawnRate(randIndex, newRate); } } else { spawningRooms.RemoveAt(randIndex); } } }
public override void Apply(TGenContext map) { Loc defaultLoc = Loc.Zero; for (int ii = 0; ii < this.Entrance.Count; ii++) { Loc start = GetOutlet <TEntrance>(map); if (start == new Loc(-1)) { start = defaultLoc; } else { defaultLoc = start; } ((IPlaceableGenContext <TEntrance>)map).PlaceItem(start, this.Entrance[ii]); GenContextDebug.DebugProgress(nameof(this.Entrance)); } for (int ii = 0; ii < this.Exit.Count; ii++) { Loc end = GetOutlet <TExit>(map); if (end == new Loc(-1)) { end = defaultLoc; } ((IPlaceableGenContext <TExit>)map).PlaceItem(end, this.Exit[ii]); GenContextDebug.DebugProgress(nameof(this.Exit)); } }
public override void ApplyToPath(IRandom rand, GridPlan floorPlan) { // choose certain rooms in the list to be special rooms // special rooms are required; so make sure they don't overlap List <int> room_indices = new List <int>(); for (int ii = 0; ii < floorPlan.RoomCount; ii++) { GridRoomPlan plan = floorPlan.GetRoomPlan(ii); if (!plan.Immutable && !plan.CountsAsHall()) { room_indices.Add(ii); } } if (room_indices.Count > 0) { int ind = rand.Next(room_indices.Count); GridRoomPlan plan = floorPlan.GetRoomPlan(room_indices[ind]); plan.RoomGen = this.Rooms.Pick(rand).Copy(); plan.Immutable = true; room_indices.RemoveAt(ind); GenContextDebug.DebugProgress("Set Special Room"); } }
public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns) { for (int ii = 0; ii < spawns.Count && ii < this.SpawnLocs.Count; ii++) { TSpawnable item = spawns[ii]; map.PlaceItem(this.SpawnLocs[ii], item); GenContextDebug.DebugProgress("Placed Object"); } }
public static void UnsafeAddHall(LocRay4 locRay, GridPlan floorPlan, IPermissiveRoomGen hallGen, ComponentCollection components) { floorPlan.SetHall(locRay, hallGen, components.Clone()); GenContextDebug.DebugProgress("Hall"); if (floorPlan.GetRoomPlan(locRay.Loc) == null || floorPlan.GetRoomPlan(locRay.Traverse(1)) == null) { floorPlan.Clear(); throw new InvalidOperationException("Can't create a hall without rooms to connect!"); } }
protected static void ApplyGenSteps(T map, StablePriorityQueue <Priority, IGenStep> queue) { while (queue.Count > 0) { IGenStep postProc = queue.Dequeue(); GenContextDebug.StepIn(postProc.ToString()); postProc.Apply(map); GenContextDebug.StepOut(); } }
public override void ApplyToPath(IRandom rand, FloorPlan floorPlan) { List <RoomHallIndex> candBranchPoints = new List <RoomHallIndex>(); for (int ii = 0; ii < floorPlan.RoomCount; ii++) { if (!BaseRoomFilter.PassesAllFilters(floorPlan.GetRoomPlan(ii), this.Filters)) { continue; } candBranchPoints.Add(new RoomHallIndex(ii, false)); } // compute a goal amount of terminals to connect // this computation ignores the fact that some terminals may be impossible int connectionsLeft = this.ConnectFactor.Pick(rand) * candBranchPoints.Count / 2 / 100; while (candBranchPoints.Count > 0 && connectionsLeft > 0) { // choose random point to connect from int randIndex = rand.Next(candBranchPoints.Count); var chosenDestResult = ChooseConnection(rand, floorPlan, candBranchPoints); if (chosenDestResult is ListPathTraversalNode chosenDest) { // connect PermissiveRoomGen <T> hall = (PermissiveRoomGen <T>) this.GenericHalls.Pick(rand).Copy(); hall.PrepareSize(rand, chosenDest.Connector.Size); hall.SetLoc(chosenDest.Connector.Start); floorPlan.AddHall(hall, this.Components.Clone(), chosenDest.From, chosenDest.To); candBranchPoints.RemoveAt(randIndex); connectionsLeft--; GenContextDebug.DebugProgress("Added Connection"); // check to see if connection destination was also a candidate, // counting this as a double if so for (int jj = 0; jj < candBranchPoints.Count; jj++) { if (candBranchPoints[jj] == chosenDest.To) { candBranchPoints.RemoveAt(jj); connectionsLeft--; break; } } } else { // remove the list anyway, but don't call it a success candBranchPoints.RemoveAt(randIndex); } } }
public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns) { List <Loc> freeTiles = map.GetAllFreeTiles(); for (int ii = 0; ii < spawns.Count && freeTiles.Count > 0; ii++) { TSpawnable item = spawns[ii]; int randIndex = map.Rand.Next(freeTiles.Count); map.PlaceItem(freeTiles[randIndex], item); freeTiles.RemoveAt(randIndex); GenContextDebug.DebugProgress("Placed Object"); } }
protected bool ExpandPath(IRandom rand, GridPlan floorPlan, bool branch) { LocRay4 chosenRay = this.ChooseRoomExpansion(rand, floorPlan, branch); if (chosenRay.Dir == Dir4.None) { return(false); } floorPlan.SetHall(chosenRay, this.GenericHalls.Pick(rand)); floorPlan.AddRoom(chosenRay.Traverse(1), this.GenericRooms.Pick(rand)); GenContextDebug.DebugProgress(branch ? "Branched Path" : "Extended Path"); return(true); }
public override void ApplyToPath(IRandom rand, FloorPlan floorPlan) { List <List <RoomHallIndex> > candBranchPoints = GetBranchArms(floorPlan); // compute a goal amount of branches to connect // this computation ignores the fact that some terminals may be impossible var randBin = new RandBinomial(candBranchPoints.Count, this.ConnectPercent); int connectionsLeft = randBin.Pick(rand); while (candBranchPoints.Count > 0 && connectionsLeft > 0) { // choose random point to connect from int randIndex = rand.Next(candBranchPoints.Count); var chosenDestResult = ChooseConnection(rand, floorPlan, candBranchPoints[randIndex]); if (chosenDestResult is ListPathTraversalNode chosenDest) { // connect PermissiveRoomGen <T> hall = (PermissiveRoomGen <T>) this.GenericHalls.Pick(rand).Copy(); hall.PrepareSize(rand, chosenDest.Connector.Size); hall.SetLoc(chosenDest.Connector.Start); floorPlan.AddHall(hall, chosenDest.From, chosenDest.To); candBranchPoints.RemoveAt(randIndex); connectionsLeft--; GenContextDebug.DebugProgress("Added Connection"); // check to see if connection destination was also a candidate, // counting this as a double if so for (int ii = candBranchPoints.Count - 1; ii >= 0; ii--) { for (int jj = 0; jj < candBranchPoints[ii].Count; jj++) { if (candBranchPoints[ii][jj] == chosenDest.To) { candBranchPoints.RemoveAt(ii); connectionsLeft--; break; } } } } else { // remove the list anyway, but don't call it a success candBranchPoints.RemoveAt(randIndex); } } }
public override void Apply(T map) { Loc start = map.RoomPlan.Size; Loc end = Loc.Zero; foreach (IRoomPlan plan in map.RoomPlan.GetAllPlans()) { Rect roomRect = plan.RoomGen.Draw; start = new Loc(Math.Min(start.X, roomRect.Start.X), Math.Min(start.Y, roomRect.Start.Y)); end = new Loc(Math.Max(end.X, roomRect.End.X), Math.Max(end.Y, roomRect.End.Y)); } map.RoomPlan.Resize(end, Dir8.DownRight, Dir8.UpLeft); map.RoomPlan.Resize(end, Dir8.UpLeft, Dir8.DownRight); GenContextDebug.DebugProgress("Clamped Floor"); }
public override void Apply(TGenContext map) { List <int> room_indices = new List <int>(); for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { if (!BaseRoomFilter.PassesAllFilters(map.RoomPlan.GetRoomPlan(ii), this.Filters)) { continue; } room_indices.Add(ii); } List <int> used_indices = new List <int>(); Loc defaultLoc = Loc.Zero; for (int ii = 0; ii < this.Entrances.Count; ii++) { int startRoom = NextRoom(map.Rand, room_indices, used_indices); Loc start = GetOutlet <TEntrance>(map, startRoom); if (start == new Loc(-1)) { start = defaultLoc; } else { defaultLoc = start; } ((IPlaceableGenContext <TEntrance>)map).PlaceItem(start, this.Entrances[ii]); GenContextDebug.DebugProgress(nameof(this.Entrances)); } for (int ii = 0; ii < this.Exits.Count; ii++) { int endRoom = NextRoom(map.Rand, room_indices, used_indices); Loc end = GetOutlet <TExit>(map, endRoom); if (end == new Loc(-1)) { end = defaultLoc; } ((IPlaceableGenContext <TExit>)map).PlaceItem(end, this.Exits[ii]); GenContextDebug.DebugProgress(nameof(this.Exits)); } }
public override void Apply(T map) { // draw on map map.CreateNew( map.RoomPlan.DrawRect.Width + (2 * this.Padding), map.RoomPlan.DrawRect.Height + (2 * this.Padding)); for (int ii = 0; ii < map.Width; ii++) { for (int jj = 0; jj < map.Height; jj++) { map.SetTile(new Loc(ii, jj), map.WallTerrain.Copy()); } } map.RoomPlan.MoveStart(new Loc(this.Padding)); GenContextDebug.DebugProgress("Moved Floor"); map.RoomPlan.DrawOnMap(map); }
public void DrawOnMap(ITiledGenContext map) { GenContextDebug.StepIn("Main Rooms"); for (int ii = 0; ii < this.Rooms.Count; ii++) { // take in the broad fulfillables from adjacent rooms that have not yet drawn IFloorRoomPlan plan = this.Rooms[ii]; foreach (RoomHallIndex adj in plan.Adjacents) { if (adj.IsHall || adj.Index > ii) { IRoomGen adjacentGen = this.GetRoomHall(adj).RoomGen; plan.RoomGen.ReceiveFulfillableBorder(adjacentGen, GetDirAdjacent(plan.RoomGen, adjacentGen)); } } plan.RoomGen.DrawOnMap(map); this.TransferBorderToAdjacents(new RoomHallIndex(ii, false)); GenContextDebug.DebugProgress("Draw Room"); } GenContextDebug.StepOut(); GenContextDebug.StepIn("Connecting Halls"); for (int ii = 0; ii < this.Halls.Count; ii++) { // take in the broad fulfillables from adjacent rooms that have not yet drawn IFloorRoomPlan plan = this.Halls[ii]; foreach (RoomHallIndex adj in plan.Adjacents) { if (adj.IsHall && adj.Index > ii) { IRoomGen adjacentGen = this.GetRoomHall(adj).RoomGen; plan.RoomGen.ReceiveFulfillableBorder(adjacentGen, GetDirAdjacent(plan.RoomGen, adjacentGen)); } } plan.RoomGen.DrawOnMap(map); this.TransferBorderToAdjacents(new RoomHallIndex(ii, true)); GenContextDebug.DebugProgress("Draw Hall"); } GenContextDebug.StepOut(); }
/// <summary> /// Draws a hall in a straight cardinal direction, starting with one point and ending with another (inclusive). /// </summary> /// <param name="map"></param> /// <param name="point1"></param> /// <param name="point2"></param> /// <param name="vertical"></param> private void DrawHall(ITiledGenContext map, Loc point1, Loc point2, bool vertical) { if (point1 == point2) { this.Brush.DrawHallBrush(map, this.Draw, point1, vertical); } else if (point1.X == point2.X) { if (point2.Y > point1.Y) { for (int ii = point1.Y; ii <= point2.Y; ii++) { this.Brush.DrawHallBrush(map, this.Draw, new Loc(point1.X, ii), vertical); } } else if (point2.Y < point1.Y) { for (int ii = point1.Y; ii >= point2.Y; ii--) { this.Brush.DrawHallBrush(map, this.Draw, new Loc(point1.X, ii), vertical); } } } else if (point1.Y == point2.Y) { if (point2.X > point1.X) { for (int ii = point1.X; ii <= point2.X; ii++) { this.Brush.DrawHallBrush(map, this.Draw, new Loc(ii, point1.Y), vertical); } } else if (point2.X < point1.X) { for (int ii = point1.X; ii >= point2.X; ii--) { this.Brush.DrawHallBrush(map, this.Draw, new Loc(ii, point1.Y), vertical); } } } GenContextDebug.DebugProgress("Hall Line"); }
public override void ApplyToPath(IRandom rand, FloorPlan floorPlan) { int amount = this.Amount.Pick(rand); for (int ii = 0; ii < amount; ii++) { // choose a room RoomGen <T> room = this.GenericRooms.Pick(rand).Copy(); // decide on acceptable border/size/fulfillables Loc size = room.ProposeSize(rand); if (size.X > floorPlan.DrawRect.Width) { size.X = floorPlan.DrawRect.Width; } if (size.Y > floorPlan.DrawRect.Height) { size.Y = floorPlan.DrawRect.Height; } room.PrepareSize(rand, size); for (int jj = 0; jj < 30; jj++) { // place in a random location Loc testStart = new Loc( rand.Next(floorPlan.DrawRect.Left, floorPlan.DrawRect.Right - room.Draw.Width + 1), rand.Next(floorPlan.DrawRect.Top, floorPlan.DrawRect.Bottom - room.Draw.Height + 1)); Rect tryRect = new Rect(testStart, room.Draw.Size); tryRect.Inflate(1, 1); List <RoomHallIndex> collisions = floorPlan.CheckCollision(tryRect); if (collisions.Count == 0) { room.SetLoc(testStart); floorPlan.AddRoom(room, this.Components.Clone()); GenContextDebug.DebugProgress("Place Disconnected Room"); break; } } } }
/// <summary> /// Draws a hall in a straight cardinal direction, starting with one point and ending with another (inclusive). /// </summary> /// <param name="map"></param> /// <param name="point1"></param> /// <param name="point2"></param> /// <param name="terrain"></param> private static void DrawHall(ITiledGenContext map, Loc point1, Loc point2, ITile terrain) { if (point1 == point2) { map.SetTile(point1, terrain.Copy()); } else if (point1.X == point2.X) { if (point2.Y > point1.Y) { for (int ii = point1.Y; ii <= point2.Y; ii++) { map.SetTile(new Loc(point1.X, ii), terrain.Copy()); } } else if (point2.Y < point1.Y) { for (int ii = point1.Y; ii >= point2.Y; ii--) { map.SetTile(new Loc(point1.X, ii), terrain.Copy()); } } } else if (point1.Y == point2.Y) { if (point2.X > point1.X) { for (int ii = point1.X; ii <= point2.X; ii++) { map.SetTile(new Loc(ii, point1.Y), terrain.Copy()); } } else if (point2.X < point1.X) { for (int ii = point1.X; ii >= point2.X; ii--) { map.SetTile(new Loc(ii, point1.Y), terrain.Copy()); } } } GenContextDebug.DebugProgress("Hall Line"); }
public override void ApplyToPath(IRandom rand, GridPlan floorPlan) { if (floorPlan.GridWidth != this.SpecificVHalls.Length || floorPlan.GridWidth - 1 != this.SpecificHHalls.Length || floorPlan.GridHeight - 1 != this.SpecificVHalls[0].Length || floorPlan.GridHeight != this.SpecificHHalls[0].Length) { throw new InvalidOperationException("Incorrect hall path sizes."); } foreach (var chosenRoom in this.SpecificRooms) { floorPlan.AddRoom(chosenRoom.Bounds, chosenRoom.RoomGen, chosenRoom.Components.Clone(), chosenRoom.PreferHall); GenContextDebug.DebugProgress("Room"); } // place halls for (int x = 0; x < this.SpecificVHalls.Length; x++) { for (int y = 0; y < this.SpecificHHalls[0].Length; y++) { if (x > 0) { if (this.SpecificHHalls[x - 1][y] != null) { UnsafeAddHall(new LocRay4(new Loc(x, y), Dir4.Left), floorPlan, this.SpecificHHalls[x - 1][y], this.HallComponents); } } if (y > 0) { if (this.SpecificVHalls[x][y - 1] != null) { UnsafeAddHall(new LocRay4(new Loc(x, y), Dir4.Up), floorPlan, this.SpecificVHalls[x][y - 1], this.HallComponents); } } } } }
protected void DrawBlob(T map, BlobMap blobMap, int index, Loc offset, bool encroach) { BlobMap.Blob mapBlob = blobMap.Blobs[index]; for (int xx = Math.Max(0, offset.X); xx < Math.Min(map.Width, offset.X + mapBlob.Bounds.Width); xx++) { for (int yy = Math.Max(0, offset.Y); yy < Math.Min(map.Height, offset.Y + mapBlob.Bounds.Height); yy++) { Loc destLoc = new Loc(xx, yy); Loc srcLoc = destLoc + mapBlob.Bounds.Start - offset; if (blobMap.Map[srcLoc.X][srcLoc.Y] == index) { // can place anything if encroaching // otherwise, can place anything except roomterrain if (encroach || !map.GetTile(destLoc).TileEquivalent(map.RoomTerrain)) { map.TrySetTile(new Loc(xx, yy), this.Terrain.Copy()); } } } } GenContextDebug.DebugProgress("Draw Blob"); }
public override void ApplyToPath(IRandom rand, GridPlan floorPlan) { if (floorPlan.GridWidth < 3 || floorPlan.GridHeight < 3) { throw new InvalidOperationException("Not enough room to create path."); } int maxRooms = (2 * floorPlan.GridWidth) + (2 * floorPlan.GridHeight) - 4; int roomOpen = maxRooms * this.CircleRoomRatio.Pick(rand) / 100; int paths = this.Paths.Pick(rand); if (roomOpen < 1 && paths < 1) { roomOpen = 1; } GenContextDebug.StepIn("Outer Circle"); // draw the top and bottom for (int xx = 0; xx < floorPlan.GridWidth; xx++) { this.RollOpenRoom(rand, floorPlan, new Loc(xx, 0), ref roomOpen, ref maxRooms); GenContextDebug.DebugProgress("Room"); this.RollOpenRoom(rand, floorPlan, new Loc(xx, floorPlan.GridHeight - 1), ref roomOpen, ref maxRooms); GenContextDebug.DebugProgress("Room"); if (xx > 0) { floorPlan.SetHall(new LocRay4(new Loc(xx, 0), Dir4.Left), this.GenericHalls.Pick(rand), this.HallComponents.Clone()); GenContextDebug.DebugProgress("Hall"); floorPlan.SetHall(new LocRay4(new Loc(xx, floorPlan.GridHeight - 1), Dir4.Left), this.GenericHalls.Pick(rand), this.HallComponents.Clone()); GenContextDebug.DebugProgress("Hall"); } } // draw the left and right (excluding the top and bottom) for (int yy = 0; yy < floorPlan.GridHeight; yy++) { // exclude the top and bottom if (yy > 0 && yy < floorPlan.GridHeight - 1) { this.RollOpenRoom(rand, floorPlan, new Loc(0, yy), ref roomOpen, ref maxRooms); GenContextDebug.DebugProgress("Room"); this.RollOpenRoom(rand, floorPlan, new Loc(floorPlan.GridWidth - 1, yy), ref roomOpen, ref maxRooms); GenContextDebug.DebugProgress("Room"); } if (yy > 0) { floorPlan.SetHall(new LocRay4(new Loc(0, yy), Dir4.Up), this.GenericHalls.Pick(rand), this.HallComponents.Clone()); GenContextDebug.DebugProgress("Hall"); floorPlan.SetHall(new LocRay4(new Loc(floorPlan.GridWidth - 1, yy), Dir4.Up), this.GenericHalls.Pick(rand), this.HallComponents.Clone()); GenContextDebug.DebugProgress("Hall"); } } GenContextDebug.StepOut(); GenContextDebug.StepIn("Inner Paths"); Rect innerRect = new Rect(1, 1, floorPlan.GridWidth - 2, floorPlan.GridHeight - 2); // create inner paths for (int pathsMade = 0; pathsMade < paths; pathsMade++) { GenContextDebug.StepIn($"Path {pathsMade}"); Dir4 startDir = DirExt.VALID_DIR4.ElementAt(rand.Next(DirExt.DIR4_COUNT)); int x = rand.Next(innerRect.Start.X, innerRect.End.X); int y = rand.Next(innerRect.Start.Y, innerRect.End.Y); switch (startDir) { case Dir4.Down: y = 0; break; case Dir4.Left: x = floorPlan.GridWidth - 1; break; case Dir4.Up: y = floorPlan.GridHeight - 1; break; case Dir4.Right: x = 0; break; case Dir4.None: break; default: throw new ArgumentOutOfRangeException(nameof(startDir), "Invalid enum value."); } Loc wanderer = new Loc(x, y); Dir4 prevDir = Dir4.None; // direction of movement int pathLength = (startDir.ToAxis() == Axis4.Vert) ? innerRect.Height : innerRect.Width; for (int currentLength = 0; currentLength < pathLength; currentLength++) { Dir4 chosenDir = startDir; // avoid this block the first time if (currentLength > 0) { List <Dir4> dirs = new List <Dir4>(); foreach (Dir4 dir in DirExt.VALID_DIR4) { // do not backtrack if (dir == prevDir) { continue; } // do not hit edge if (!Collision.InBounds(innerRect, wanderer + dir.GetLoc())) { continue; } dirs.Add(dir); } chosenDir = dirs[rand.Next(dirs.Count)]; } Loc dest = wanderer + chosenDir.GetLoc(); GridRoomPlan existingRoom = floorPlan.GetRoomPlan(dest); if (existingRoom == null) { if (currentLength == pathLength - 1) // only the end room can be a non-hall { floorPlan.AddRoom(dest, this.GenericRooms.Pick(rand), this.RoomComponents.Clone()); } else { floorPlan.AddRoom(dest, this.GetDefaultGen(), this.HallComponents.Clone(), true); } GenContextDebug.DebugProgress("Room"); } else if (existingRoom.PreferHall) { if (currentLength == pathLength - 1) { // override the hall room existingRoom.RoomGen = this.GenericRooms.Pick(rand).Copy(); existingRoom.PreferHall = false; } } floorPlan.SetHall(new LocRay4(wanderer, chosenDir), this.GenericHalls.Pick(rand), this.HallComponents.Clone()); GenContextDebug.DebugProgress("Hall"); wanderer = dest; prevDir = chosenDir.Reverse(); } GenContextDebug.StepOut(); } GenContextDebug.StepOut(); }
public override void ApplyToPath(IRandom rand, FloorPlan floorPlan) { // choose certain rooms in the list to be special rooms // special rooms are required; so make sure they don't overlap IRoomGen newGen = this.Rooms.Pick(rand).Copy(); Loc size = newGen.ProposeSize(rand); newGen.PrepareSize(rand, size); int factor = floorPlan.DrawRect.Area / newGen.Draw.Area; // TODO: accept smaller rooms to replace // bulldozing the surrounding rooms to get the space var room_indices = new SpawnList <RoomHallIndex>(); for (int ii = 0; ii < floorPlan.RoomCount; ii++) { FloorRoomPlan plan = floorPlan.GetRoomPlan(ii); if (!plan.Immutable && plan.RoomGen.Draw.Width >= newGen.Draw.Width && plan.RoomGen.Draw.Height >= newGen.Draw.Height) { room_indices.Add(new RoomHallIndex(ii, false), ComputeRoomChance(factor, plan.RoomGen.Draw, newGen.Draw)); } } for (int ii = 0; ii < floorPlan.HallCount; ii++) { var roomHall = new RoomHallIndex(ii, true); IFloorRoomPlan plan = floorPlan.GetRoomHall(roomHall); if (plan.RoomGen.Draw.Width >= newGen.Draw.Width && plan.RoomGen.Draw.Height >= newGen.Draw.Height) { room_indices.Add(roomHall, ComputeRoomChance(factor, plan.RoomGen.Draw, newGen.Draw)); } } while (room_indices.Count > 0) { int ind = room_indices.PickIndex(rand); RoomHallIndex oldRoomHall = room_indices.GetSpawn(ind); Dictionary <Dir4, List <RoomHallIndex> > adjacentIndicesByDir = GetDirectionAdjacents(floorPlan, oldRoomHall); var adjacentsByDir = new Dictionary <Dir4, List <IRoomGen> >(); foreach (Dir4 dir in DirExt.VALID_DIR4) { adjacentsByDir[dir] = new List <IRoomGen>(); foreach (RoomHallIndex adj in adjacentIndicesByDir[dir]) { adjacentsByDir[dir].Add(floorPlan.GetRoomHall(adj).RoomGen); } } Loc placement = this.FindPlacement(rand, adjacentsByDir, newGen, floorPlan.GetRoomHall(oldRoomHall).RoomGen); if (placement != new Loc(-1)) { newGen.SetLoc(placement); this.PlaceRoom(rand, floorPlan, newGen, oldRoomHall); GenContextDebug.DebugProgress("Set Special Room"); return; } room_indices.RemoveAt(ind); } }
/// <summary> /// Generates the position and size of each room and hall, and places it in the specified IFloorPlanGenContext. /// </summary> /// <param name="map"></param> public void PlaceRoomsOnFloor(IFloorPlanGenContext map) { // decide on room sizes for (int ii = 0; ii < this.ArrayRooms.Count; ii++) { this.ChooseRoomBounds(map.Rand, ii); } // decide on halls; write to RoomSideReqs for (int xx = 0; xx < this.VHalls.Length; xx++) { for (int yy = 0; yy < this.VHalls[xx].Length; yy++) { this.ChooseHallBounds(map.Rand, xx, yy, true); } } for (int xx = 0; xx < this.HHalls.Length; xx++) { for (int yy = 0; yy < this.HHalls[xx].Length; yy++) { this.ChooseHallBounds(map.Rand, xx, yy, false); } } GenContextDebug.StepIn("Main Rooms"); List <RoomHallIndex> roomToHall = new List <RoomHallIndex>(); foreach (var plan in this.ArrayRooms) { if (plan.PreferHall) { roomToHall.Add(new RoomHallIndex(map.RoomPlan.HallCount, true)); map.RoomPlan.AddHall((IPermissiveRoomGen)plan.RoomGen, plan.Components); GenContextDebug.DebugProgress("Add Hall Room"); } else { roomToHall.Add(new RoomHallIndex(map.RoomPlan.RoomCount, false)); map.RoomPlan.AddRoom(plan.RoomGen, plan.Components); GenContextDebug.DebugProgress("Added Room"); } } GenContextDebug.StepOut(); GenContextDebug.StepIn("Connecting Halls"); for (int xx = 0; xx < this.VHalls.Length; xx++) { for (int yy = 0; yy < this.VHalls[xx].Length; yy++) { GridHallGroup hallGroup = this.VHalls[xx][yy]; for (int ii = 0; ii < hallGroup.HallParts.Count; ii++) { List <RoomHallIndex> adj = new List <RoomHallIndex>(); if (ii == 0) { int upRoom = this.Rooms[xx][yy]; if (upRoom > -1) { adj.Add(roomToHall[upRoom]); } } else { adj.Add(new RoomHallIndex(map.RoomPlan.HallCount - 1, true)); } if (ii == hallGroup.HallParts.Count - 1) { int downRoom = this.Rooms[xx][yy + 1]; if (downRoom > -1) { adj.Add(roomToHall[downRoom]); } } map.RoomPlan.AddHall(hallGroup.HallParts[ii].RoomGen, hallGroup.HallParts[ii].Components, adj.ToArray()); GenContextDebug.DebugProgress("Add Hall"); } } } for (int xx = 0; xx < this.HHalls.Length; xx++) { for (int yy = 0; yy < this.HHalls[xx].Length; yy++) { GridHallGroup hallGroup = this.HHalls[xx][yy]; for (int ii = 0; ii < hallGroup.HallParts.Count; ii++) { List <RoomHallIndex> adj = new List <RoomHallIndex>(); if (ii == 0) { int leftRoom = this.Rooms[xx][yy]; if (leftRoom > -1) { adj.Add(roomToHall[leftRoom]); } } else { adj.Add(new RoomHallIndex(map.RoomPlan.HallCount - 1, true)); } if (ii == hallGroup.HallParts.Count - 1) { int rightRoom = this.Rooms[xx + 1][yy]; if (rightRoom > -1) { adj.Add(roomToHall[rightRoom]); } } map.RoomPlan.AddHall(hallGroup.HallParts[ii].RoomGen, hallGroup.HallParts[ii].Components, adj.ToArray()); GenContextDebug.DebugProgress("Add Hall"); } } } GenContextDebug.StepOut(); }
public override void ApplyToPath(IRandom rand, FloorPlan floorPlan) { for (int ii = 0; ii < 10; ii++) { // always clear before trying floorPlan.Clear(); int tilesToOpen = floorPlan.DrawRect.Area * this.FillPercent.Pick(rand) / 100; if (tilesToOpen < 1) { tilesToOpen = 1; } int addBranch = this.BranchRatio.Pick(rand); int tilesLeft = tilesToOpen; // choose a room IRoomGen room = this.PrepareRoom(rand, floorPlan, false); // place in a random location room.SetLoc(new Loc( rand.Next(floorPlan.DrawRect.Left, floorPlan.DrawRect.Right - room.Draw.Width + 1), rand.Next(floorPlan.DrawRect.Top, floorPlan.DrawRect.Bottom - room.Draw.Height + 1))); floorPlan.AddRoom(room, this.RoomComponents.Clone()); GenContextDebug.DebugProgress("Start Room"); tilesLeft -= room.Draw.Area; // repeat this process until the requisite room amount is met int pendingBranch = 0; while (tilesLeft > 0) { (int area, int rooms)terminalResult = this.ExpandPath(rand, floorPlan, false); (int area, int rooms)branchResult = (0, 0); if (terminalResult.area > 0) { tilesLeft -= terminalResult.area; // add branch PER ROOM when we add over the min threshold for (int jj = 0; jj < terminalResult.rooms; jj++) { if (floorPlan.RoomCount + floorPlan.HallCount - terminalResult.rooms + jj + 1 > 2) { pendingBranch += addBranch; } } } else if (this.NoForcedBranches) { break; } else { pendingBranch = 100; } while (pendingBranch >= 100 && tilesLeft > 0) { branchResult = this.ExpandPath(rand, floorPlan, true); if (branchResult.area == 0) { break; } pendingBranch -= 100; // if we add any more than one room, that also counts as a branchable node pendingBranch += (branchResult.rooms - 1) * addBranch; tilesLeft -= branchResult.area; } if (terminalResult.area == 0 && branchResult.area == 0) { break; } } if (tilesLeft <= 0) { break; } } }