public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns) { // random per room, not per-tile var spawningRooms = new SpawnList <RoomHallIndex>(); var terminalRooms = new SpawnList <RoomHallIndex>(); // TODO: higher likelihoods for terminals at the ends of longer paths for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { spawningRooms.Add(new RoomHallIndex(ii, false)); List <int> adjacent = map.RoomPlan.GetAdjacentRooms(ii); if (adjacent.Count == 1) { terminalRooms.Add(new RoomHallIndex(ii, false)); } } if (this.IncludeHalls) { for (int ii = 0; ii < map.RoomPlan.HallCount; ii++) { spawningRooms.Add(new RoomHallIndex(ii, true)); List <RoomHallIndex> adjacent = map.RoomPlan.GetRoomHall(new RoomHallIndex(ii, true)).Adjacents; if (adjacent.Count == 1) { terminalRooms.Add(new RoomHallIndex(ii, true)); } } } // first attempt to spawn in the terminals; remove from terminal list if successful this.SpawnRandInCandRooms(map, terminalRooms, spawns, 0); this.SpawnRandInCandRooms(map, spawningRooms, spawns, 100); }
public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns) { // random per room, not per-tile var spawningRooms = new SpawnList <RoomHallIndex>(); for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { if (!BaseRoomFilter.PassesAllFilters(map.RoomPlan.GetRoomPlan(ii), this.Filters)) { continue; } spawningRooms.Add(new RoomHallIndex(ii, false), 10); } if (this.IncludeHalls) { for (int ii = 0; ii < map.RoomPlan.HallCount; ii++) { if (!BaseRoomFilter.PassesAllFilters(map.RoomPlan.GetHallPlan(ii), this.Filters)) { continue; } spawningRooms.Add(new RoomHallIndex(ii, true), 10); } } this.SpawnRandInCandRooms(map, spawningRooms, spawns, 100); }
protected static SpawnList <ListPathTraversalNode> GetPossibleExpansions(FloorPlan floorPlan, List <RoomHallIndex> candList) { // get all probabilities. // the probability of an extension is the distance that the target room is from the start room, in rooms var expansions = new SpawnList <ListPathTraversalNode>(); for (int nn = 0; nn < candList.Count; nn++) { // find the room to connect to // go through all sides of all rooms (randomly) RoomHallIndex chosenFrom = candList[nn]; IFloorRoomPlan planFrom = floorPlan.GetRoomHall(chosenFrom); // exhausting all possible directions (randomly) foreach (Dir4 dir in DirExt.VALID_DIR4) { bool forbidExtend = false; foreach (RoomHallIndex adjacent in planFrom.Adjacents) { Rect adjRect = floorPlan.GetRoomHall(adjacent).RoomGen.Draw; if (planFrom.RoomGen.Draw.GetScalar(dir) == adjRect.GetScalar(dir.Reverse())) { forbidExtend = true; break; } } if (!forbidExtend) { // find a rectangle to connect it with ListPathTraversalNode?expandToResult = GetRoomToConnect(floorPlan, chosenFrom, dir); if (expandToResult is ListPathTraversalNode expandTo) { int prb = floorPlan.GetDistance(expandTo.From, expandTo.To); if (prb < 0) { expansions.Add(expandTo, 1); } else if (prb > 0) { expansions.Add(expandTo, prb); } } } } } return(expansions); }
public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns) { // random per room, not per-tile var spawningRooms = new SpawnList <RoomHallIndex>(); for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { spawningRooms.Add(new RoomHallIndex(ii, false)); } if (this.IncludeHalls) { for (int ii = 0; ii < map.RoomPlan.HallCount; ii++) { spawningRooms.Add(new RoomHallIndex(ii, true)); } } this.SpawnRandInCandRooms(map, spawningRooms, spawns, 100); }
public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns) { // gather up all rooms and put in a spawn list // rooms that are farther from the start are more likely to have items var spawningRooms = new SpawnList <RoomHallIndex>(); Dictionary <RoomHallIndex, int> roomWeights = new Dictionary <RoomHallIndex, int>(); // get the start room int startRoom = 0; for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { FloorRoomPlan room = map.RoomPlan.GetRoomPlan(ii); if (Collision.InBounds(room.RoomGen.Draw, map.GetLoc(0))) { startRoom = ii; break; } } int maxVal = 1; void NodeAct(RoomHallIndex nodeIndex, int distance) { roomWeights[nodeIndex] = distance + 1; maxVal = Math.Max(maxVal, roomWeights[nodeIndex]); } Graph.TraverseBreadthFirst(new RoomHallIndex(startRoom, false), NodeAct, map.RoomPlan.GetAdjacents); int multFactor = int.MaxValue / maxVal / roomWeights.Count; foreach (RoomHallIndex idx in roomWeights.Keys) { IFloorRoomPlan room = map.RoomPlan.GetRoomHall(idx); if (idx.IsHall && !this.IncludeHalls) { continue; } if (!BaseRoomFilter.PassesAllFilters(room, this.Filters)) { continue; } if (roomWeights[idx] == 0) { continue; } spawningRooms.Add(idx, roomWeights[idx] * multFactor); } this.SpawnRandInCandRooms(map, spawningRooms, spawns, this.SuccessPercent); }
public CategorySpawnChooser(CategorySpawnChooser <T> other) { Spawns = new SpawnDict <string, SpawnList <T> >(); foreach (string key in other.Spawns.GetKeys()) { SpawnList <T> list = new SpawnList <T>(); SpawnList <T> otherList = other.Spawns.GetSpawn(key); for (int ii = 0; ii < otherList.Count; ii++) { list.Add(otherList.GetSpawn(ii), otherList.GetSpawnRate(ii)); } Spawns.Add(key, list, other.Spawns.GetSpawnRate(key)); } }
public SpawnList <T> GetSpawnList(int level) { SpawnList <T> newList = new SpawnList <T>(); foreach (SpawnRange spawn in this.spawns) { if (spawn.Range.Min <= level && level < spawn.Range.Max) { newList.Add(spawn.Spawn, spawn.Rate); } } return(newList); }
public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns) { // gather up all rooms and put in a spawn list // rooms that are farther from the start are more likely to have items var spawningRooms = new SpawnList <RoomHallIndex>(); int[] roomWeights = new int[map.RoomPlan.RoomCount]; // get the start room int startRoom = 0; for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { IRoomGen room = map.RoomPlan.GetRoom(ii); if (Collision.InBounds(room.Draw, map.GetLoc(0))) { startRoom = ii; break; } } int maxVal = 1; void NodeAct(int nodeIndex, int distance) { roomWeights[nodeIndex] = distance + 1; maxVal = Math.Max(maxVal, roomWeights[nodeIndex]); } List <int> GetAdjacents(int nodeIndex) => map.RoomPlan.GetAdjacentRooms(nodeIndex); Graph.TraverseBreadthFirst(roomWeights.Length, startRoom, NodeAct, GetAdjacents); int multFactor = int.MaxValue / maxVal / roomWeights.Length; for (int ii = 0; ii < roomWeights.Length; ii++) { spawningRooms.Add(new RoomHallIndex(ii, false), roomWeights[ii] * multFactor); } this.SpawnRandInCandRooms(map, spawningRooms, spawns, this.SuccessPercent); }
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); } }
public SpawnList <Loc> GetPossiblePlacements(Dictionary <Dir4, List <IRoomGen> > adjacentsByDir, IRoomGen newGen, IRoomGen oldGen) { // test all positions around perimeter Rect oldRect = oldGen.Draw; SpawnList <Loc> possiblePlacements = new SpawnList <Loc>(); // top and bottom for (int xx = oldRect.Left; xx < oldRect.Right - newGen.Draw.Width + 1; xx++) { Loc topLoc = new Loc(xx, oldRect.Top); int topMatch = this.GetAllBorderMatch(adjacentsByDir, newGen, oldGen, topLoc); if (topMatch > 0) { possiblePlacements.Add(topLoc, topMatch); } Loc bottomLoc = new Loc(xx, oldRect.Bottom - newGen.Draw.Height); if (bottomLoc != topLoc) { int bottomMatch = this.GetAllBorderMatch(adjacentsByDir, newGen, oldGen, bottomLoc); if (bottomMatch > 0) { possiblePlacements.Add(bottomLoc, bottomMatch); } } } // left and right for (int yy = oldRect.Top + 1; yy < oldRect.Bottom - newGen.Draw.Height; yy++) { Loc leftLoc = new Loc(oldRect.Left, yy); int leftMatch = this.GetAllBorderMatch(adjacentsByDir, newGen, oldGen, leftLoc); if (leftMatch > 0) { possiblePlacements.Add(leftLoc, leftMatch); } Loc rightLoc = new Loc(oldRect.Right - newGen.Draw.Width, yy); if (rightLoc != leftLoc) { int rightMatch = this.GetAllBorderMatch(adjacentsByDir, newGen, oldGen, rightLoc); if (rightMatch > 0) { possiblePlacements.Add(rightLoc, rightMatch); } } } if (possiblePlacements.SpawnTotal == 0) { if (oldRect.Width >= newGen.Draw.Width + 2 && oldRect.Height >= newGen.Draw.Height + 2) { for (int xx = oldRect.Left + 1; xx < oldRect.Right - newGen.Draw.Width; xx++) { for (int yy = oldRect.Top + 1; yy < oldRect.Bottom - newGen.Draw.Height; yy++) { possiblePlacements.Add(new Loc(xx, yy), 1); } } } } return(possiblePlacements); }
public static void AddLegalPlacements(SpawnList <Loc> possiblePlacements, FloorPlan floorPlan, RoomHallIndex indexFrom, IRoomGen roomFrom, IRoomGen room, Dir4 expandTo) { bool vertical = expandTo.ToAxis() == Axis4.Vert; // this scaling factor equalizes the chances of long sides vs short sides int reverseSideMult = vertical ? roomFrom.Draw.Width * room.Draw.Width : roomFrom.Draw.Height * room.Draw.Height; IntRange side = roomFrom.Draw.GetSide(expandTo.ToAxis()); // subtract the room's original size, not the inflated trialrect size side.Min -= (vertical ? room.Draw.Size.X : room.Draw.Size.Y) - 1; Rect tryRect = room.Draw; // expand in every direction // this will create a one-tile buffer to check for collisions tryRect.Inflate(1, 1); int currentScalar = side.Min; while (currentScalar < side.Max) { // compute the location Loc trialLoc = roomFrom.GetEdgeRectLoc(expandTo, room.Draw.Size, currentScalar); tryRect.Start = trialLoc + new Loc(-1, -1); // check for collisions (not counting the rectangle from) List <RoomHallIndex> collisions = floorPlan.CheckCollision(tryRect); // find the first tile in which no collisions will be found int maxCollideScalar = currentScalar; bool collided = false; foreach (RoomHallIndex collision in collisions) { if (collision != indexFrom) { IRoomGen collideRoom = floorPlan.GetRoomHall(collision).RoomGen; // this is the point at which the new room will barely touch the collided room // the +1 at the end will move it into the safe zone maxCollideScalar = Math.Max(maxCollideScalar, vertical ? collideRoom.Draw.Right : collideRoom.Draw.Bottom); collided = true; } } // if no collisions were hit, do final checks and add the room if (!collided) { Loc locTo = roomFrom.GetEdgeRectLoc(expandTo, room.Draw.Size, currentScalar); // must be within the borders of the floor! if (floorPlan.DrawRect.Contains(new Rect(locTo, room.Draw.Size))) { // check the border match and if add to possible placements int chanceTo = FloorPlan.GetBorderMatch(roomFrom, room, locTo, expandTo); if (chanceTo > 0) { possiblePlacements.Add(locTo, chanceTo * reverseSideMult); } } } currentScalar = maxCollideScalar + 1; } }