I received this insightful Tweet from the always insightful @tipadeknife in response to my previous post:
I wasn’t aware (although I am not surprised) that rogue-like design is practically a discipline in and of itself. There’s a lot of knowledge out there about how to design dungeons for this genre, and while pretty must everything I found today focused more on connecting rooms that weren’t as geometrically aligned as mine are, I found one suggestion that shows how looking at something from a different direction — in this case, a completely different direction — can be more useful than pursuing a solution in a dead-end.
Naturally my impetus was to take my grid of sectors and find a way to connect them; you can read about it in the previous post linked via the Tweet above if you haven’t. Someone on one of the forums I landed on suggested that rather than trying to figure out how to connect rooms, consider connecting all of the rooms and then start taking away connections. While this wasn’t without its own challenges, I have a working model that adheres to my rules and leaves me with no loose sectors. Let’s investigate!
Everyone Gets a Connection
I am still using my original and tested Big Bang code to generate a 10×10 grid of sectors.
Next, each sector gets a going-over. The bulk of the connector code simply checks for the IDs of the sectors that are around them based on their [x,y] values. As stated in the previous post, this is important because edges will only have a minimum of 3 paths (corners) and a maximum of up to 5 (edge) while interior sectors will have a full 8. I check every surrounding sector by using Ye Olden +/- X/Y method and use the calculated values to look up the ID of the sectors at those locations. Every ID I find is stored with the current “center” sector in an array. At this point I can look at a sector and verify that, based on its own [x,y] position, whether it has received the proper number of exits and (if I want) the [x,y] of the sectors belonging to those exit ID values.
After that, I have to start removing connections. This took a few passes because there are three classifications of sector: major hubs, minor hubs, and standard sectors. A major hub is guaranteed to contain habitable planets, which guarantees a station, and since those sectors are preferred by the game’s population, they get a minimum of 6 connections. Minor sectors are also desirable, but less than major hubs, so they get a minimum of 4 connections. Standard systems, by virtue of having to provide opportunities to ensure all systems are connected, get a minimum of 2 connections. Before I make any further moves, I make sure that this sector can “spare” losing any more connections at this time. If so, the process continues .
The removal logic is mostly the same. I filter by the sector type (major, minor, or standard) to get a working subset. Looping through this collection I get the list of exits that this sector knows about. Based on the sector type, I make a sub-loop: 2 for majors, 4 for minors, and 6 for samples. These are the times I pass over the sector to remove a single connection. Using a random number generator, I pull out a single value from sector’s exit collection array and use that ID to get the system on the other side of the exit.
At this point, though, I have to do some sanity checking. Based on the sector type on the other side of the gate, if removing this next connection would leave it deficient in connections, I don’t remove anything. Put another way, if removing one connection from a major hub sector would leave the standard sector on the other side of that connection with less than 2 connections, I skip it.
Finally, I spit out some stats just to make sure that everything jives and unlike the previous post’s stats, these seem to line up perfectly every time.
: While writing out this post to explain everything, I realize that at the top of each sector type removal block, there’s logic that is intended to prevent the removal of sectors if doing do would drop the exit count below what the sector type would sustain. This was put in place for cases where edge or corner sectors were ending up with 1 or 0 exits. However, I realized during the writing of this post that the current logic isn’t sound. For example, the major hub removal code only allows processing if the current exit count is greater than 6, the minimum number of connections a major hub should have. However, if there are 7 or 8 connections (as there might be for an interior sector), then a major hub should remove two. That’s OK if there are 8, but if there are only 7 exits (for whatever reason), then removing 2 would drop the number of exits below the required number of exits for a major hub sector. It’s late when writing this, and I don’t want to have to think about it right now, so as of this writing, that flaw is still in the code.