private static bool CheckForAndMakePipeHallway(Room previousRoom, Room newRoom) { Dictionary<string, Room> horizontallySortedRooms = SortRoomsByAxis("x", previousRoom, newRoom); Dictionary<string, Room> verticallySortedRooms = SortRoomsByAxis("y", previousRoom, newRoom); // Check for and create a vertically oriented tunnel. if (horizontallySortedRooms["farthest"].topLeft.x <= horizontallySortedRooms["closest"].bottomRight.x - 2) { int x = horizontallySortedRooms["farthest"].topLeft.x + 1; int startY = verticallySortedRooms["closest"].bottomRight.y; int stopY = verticallySortedRooms["farthest"].bottomRight.y; CreateVerticalTunnel(startY, stopY, x); return true; } // Check for and create a horizontally oriented tunnel. if (verticallySortedRooms["farthest"].topLeft.y <= verticallySortedRooms["closest"].bottomRight.y - 2) { int y = verticallySortedRooms["farthest"].topLeft.y + 1; int startX = horizontallySortedRooms["closest"].bottomRight.x; int stopX = horizontallySortedRooms["farthest"].topLeft.x; CreateHorizontalTunnel(startX, stopX, y); return true; } return false; }
public static void MakeHallways(List<List<int>> dungeonLayout, Room previousRoom, Room newRoom) { DungeonLayout = dungeonLayout; if (CheckForAndMakePipeHallway(previousRoom, newRoom)) { return; } MakeRightAngleHallways(previousRoom, newRoom); }
/// <summary> /// Class constructor.</summary> /// <param name="chunkArray">A two-dimensional list of the ints that serve as lookup keys /// for the chunks that store the map.</param> /// <param name="act">The act of the game this map was generated in.</param> /// <param name="firstRoom">The first room generated in this map. Used for the players /// initial X/Y placement on this floor.</param> /// <param name="lastRoom">The last room generated in this map. Used to place the stairs /// down to a new floor.</param> /// <param name="chunkDictionary">A dictionary that stores the chunks that make up the map. /// Keys are the ints found in the map</param> public Map(int act, Room firstRoom, Room lastRoom, List<List<int>> chunkArray, Dictionary<int, Chunk> chunkDictionary) { this.chunkArray = chunkArray; this.act = act; this.firstRoom = firstRoom; this.lastRoom = lastRoom; this.chunkDictionary = chunkDictionary; }
/// <summary> /// Updates all tiles in a room to match it's style.</summary> /// <param name="room">The room to be retiled.</param> private static void RoomTiler(Room room) { // For each tile in the room randomly select a tile from the list for the room style // and apply it. Dictionary<Range, int> tileDict = MapParser.GetTilerDict(Act, room.style); Coord topLeft = room.topLeft; Coord bottomRight = room.bottomRight; for (int x = topLeft.x + 1; x <= bottomRight.x - 1; x++) for (int y = topLeft.y + 1; y <= bottomRight.y - 1; y++) { int tileSelection = RNG.Next(1, 100); foreach (KeyValuePair<Range, int> kvp in tileDict) if (kvp.Key.IsInRange(tileSelection)) DungeonLayout[x][y] = kvp.Value; } // Place the north and south walls of the room. for (int x = topLeft.x; x <= bottomRight.x; x++) { DungeonLayout[x][topLeft.y] = 0; DungeonLayout[x][bottomRight.y] = 0; } // Place the eastAmplitude and west walls of the room. for (int y = topLeft.y; y <= Math.Abs(bottomRight.y); y++) { DungeonLayout[topLeft.x][y] = 0; DungeonLayout[bottomRight.x][y] = 0; } }
/// <summary> /// Selects a style for a room. /// </summary> /// <param name="room">The room to be styled.</param> private static void RoomStyler(Room room) { //Chooses a room style by comparing a random float to a styles dict. int styleSelection = RNG.Next(0, 100); Dictionary<Range, string> roomStyles = MapParser.GetPotentialRoomStyles(Act); foreach (KeyValuePair<Range, string> kvp in roomStyles) if (kvp.Key.IsInRange(styleSelection)) { room.style = kvp.Value; return; } }
/// <summary> /// Places appropriate furniture into a room based on its style.</summary> /// <param name="room">The room to be furnished.</param> private static void RoomFurnisher(Room room) { /* TODO: Implement RoomFurnisher. Based on the generatedRooms style and that styles rule set creates and decorates a room with objects. Calls parser to generate the room styles decoration dict and based on the rule set for the room style add objects and update tiles */ }
/// <summary> /// Creates and furnishes a randomly generated room.</summary> /// <returns>Returns a finished room.</returns> private static Room RoomBuilder(List<Room> generatedRooms, bool allowIntersections = false) { // Choose a random roomWidth and height based on values from the parser. Range potentialRoomWidth = MapParser.GetPotentialRoomDimension(Act, "width"); Range potentialRoomHeight = MapParser.GetPotentialRoomDimension(Act, "height"); int roomWidth = RNG.Next((int)potentialRoomWidth.min, (int)potentialRoomWidth.max + 1); int roomHeight = RNG.Next((int)potentialRoomHeight.min, (int)potentialRoomHeight.max + 1); // Choose a random position inside the maps boundaries and create the room there. var mapDimensions = new Range(DungeonLayout.Count - 1, DungeonLayout[0].Count - 1); int roomPosX = RNG.Next(0, (int)mapDimensions.min - roomWidth + 1); int roomPosY = RNG.Next(0, (int)mapDimensions.max - roomHeight + 1); var newRoom = new Room(roomPosX, roomPosY, roomWidth, roomHeight); // Run through the other generatedRooms and see if they Intersect with this one if (!allowIntersections) { foreach (Room otherRoom in generatedRooms) // If this room intersects, discard it. if (newRoom.Intersect(otherRoom)) return null; } RoomStyler(newRoom); RoomTiler(newRoom); RoomFurnisher(newRoom); return newRoom; }
/// <summary> /// Determines if this room intersects with another.</summary> /// <param name="other">The room you are testing for intersection with.</param> /// <returns>True or false.</returns> public bool Intersect(Room other) { return ((this.topLeft.x <= other.bottomRight.x) && (this.bottomRight.x >= other.topLeft.x) && (this.topLeft.y <= other.bottomRight.y) && (this.bottomRight.y >= other.topLeft.y)); }
private static Dictionary<string, Room> SortRoomsByAxis(string axis, Room room1, Room room2) { int r1XY; int r2XY; Room closest; Room farthest; if (axis == "x") { r1XY = room1.center.x; r2XY = room2.center.x; } else { r1XY = room1.center.y; r2XY = room2.center.y; } if (r1XY < r2XY) { closest = room1; farthest = room2; } else { closest = room2; farthest = room1; } return new Dictionary<string, Room>() { {"closest", closest}, {"farthest", farthest} }; }
private static void MakeRightAngleHallways(Room previousRoom, Room newRoom) { Dictionary<string, Room> horizontallySortedRooms = SortRoomsByAxis("x", previousRoom, newRoom); Dictionary<string, Room> verticallySortedRooms = SortRoomsByAxis("y", previousRoom, newRoom); // Flip a coin to decide hallway tunneling pattern. if (rng.Next(0, 2) == 0) { //First move horizontally, then vertically int horizontalStartX = horizontallySortedRooms["closest"].bottomRight.x; int horizontalStopX = horizontallySortedRooms["farthest"].center.x + 1; int horizontalY = horizontallySortedRooms["closest"].center.y; CreateHorizontalTunnel(horizontalStartX, horizontalStopX, horizontalY); int verticalStartY; int verticalStopY; string sideToCap; if (horizontallySortedRooms["closest"].center.y <= verticallySortedRooms["closest"].center.y) { verticalStartY = horizontalY + 1; verticalStopY = verticallySortedRooms["farthest"].topLeft.y; sideToCap = "top"; } else { verticalStartY = verticallySortedRooms["closest"].bottomRight.y; verticalStopY = horizontalY - 1; sideToCap = "bottom"; } CreateVerticalTunnel(verticalStartY, verticalStopY, horizontalStopX, true, sideToCap); } else { // First move vertically, then horizontally int verticalStartY = verticallySortedRooms["closest"].bottomRight.y; int verticalStopY = verticallySortedRooms["farthest"].center.y + 1; int verticalX = verticallySortedRooms["closest"].center.x; CreateVerticalTunnel(verticalStartY, verticalStopY, verticalX); int horizontalStartX; int horizontalStopX; string sideToCap; if (verticallySortedRooms["closest"].center.x <= horizontallySortedRooms["closest"].center.x) { horizontalStartX = verticalX + 1; horizontalStopX = horizontallySortedRooms["farthest"].topLeft.x; sideToCap = "left"; } else { horizontalStartX = horizontallySortedRooms["closest"].bottomRight.x; horizontalStopX = verticalX - 1; sideToCap = "right"; } CreateHorizontalTunnel(horizontalStartX, horizontalStopX, verticalStopY, true, sideToCap); } }