I keep coming back to this part and thinking about it more. One thing that happened as a result was that yesterday I realized that this algorithm is, from a certain perspective, unnecessarily complicated: you don’t actually need to do the tricky delta/gcd() stuff to ensure that all the rooms connect in a loop and yet occur with some variety. As always in programming, you can just introduce a bit of indirection instead: say that every room connects to the next-highest-index room modulo the total number of rooms, but also give each room an arbitrary “display number” that you show to the player, letting their actual indices in the adjacency lists be an implementation detail. Then the numbers can be totally random, spaced in accordance with a delta like that specified above, plainly sequential, or anything else. In fact, they don’t even need to be numbers: they’re totally aesthetic from the player’s perspective, aside from how they differentiate the rooms from one another. Once I realized this, I wrote the according cave-generation code, as well as a Wumpus-style text-based navigation system and the ability to render a graph of a generated cave with Graphviz. It’s similar to the bsdgames algorithm but more flexible, and it’s been given me intriguing and still rather inchoate sensations. I’ll say more about it in another post down the road as I figure out what I think about it more…stay tuned. ![]()
Right now, I actually want to focus on something else: even if the delta/gcd() stuff is arguably unnecessary in this case, the principle behind what makes it work in this context is both beautiful and widely useful, I think. I have the urge to go over it in more detail since I rather brushed over it before, so I thought I might as well in case anyone else is intrigued by it. To me it’s a lovely intersection of art and mathematics, and one with broad applicability (i.e. to both music and game design). I’ll start with the musical angle, because it’s more tactile, and work back up to game design. Don’t worry if you’re not familiar with any music theory—I’ll do my best not to assume anything. (I don’t mind questions at all either, if anyone has any.)
Perhaps the most basic concept in rhythm is that of pulse:
Although this pattern by itself contains little information in rhythmic terms, it does have one obvious property: the pulse comes at a certain rate, in this case 120 “beats-per-minute” or BPM. In the European classical tradition, music that feels around as fast as this is often in the “allegro moderato” i.e. “moderately quick and lively” vein…little elves skipping merrily in the languid light of late summer…
…quiet, burning anguish and fury, alone at the far reaches of the night, widening in scope…
…thousands of wild geese attacking…
Maybe I’m getting a little sidetracked.
I suppose at the very least, one thing you can say from this is that even something as nonspecific as a rough musical speed can suggest a fair bit to a composer. But, if you want to take the suggestion, you naturally have to go beyond the pure pulse to get musical effects like these.
One of the most basic things you can do to go further is play some of the pulses louder than others. Especially basic is to do so in a simple repeating pattern, at a gamboling 100 BPM in this case.
Probably you can nod your head or tap your foot in time with that and have a sense of where it “loops.” One of the beats is the loudest one, and you probably will have a natural tendency to hear that as the “start of the loop.” After that there are three other beats, for a total of four per “loop.” You can see this in its spectrogram as well:
In English-language musical jargon, what I’m calling a “loop” here is more often called a “measure,” or “bar.” You can say that the rhythmic pattern above has “four beats per measure.” This is commonly expressed with the notation “4/4,” a type of notation called a “time signature,” which you may well already know of. The top number is what’s important for the sake of our discussion here—that “4” gives the number of beats. (The bottom “4” means that a beat has “quarter-note length,” which I think will take us too far off track to discuss in more detail here, but I can go into it on its in an addendum if anyone is curious.)
Here’s 6/8, another common time signature, at a brisk 160 BPM:
In this case, we have 6 beats per measure. We can get an interesting effect if we switch back-and-forth between 6/8 and 4/4:
You can see that, although the measures stay the same length, the number of beats changes, which causes the beats to fall at different places in the measure. What if we play these two patterns on top of each other?
Let’s take this a little slower so we can hear what’s happening more easily.
You can hopefully both hear and see that beat 4 of the 6/8 and beat 3 of the 4/4 overlap. This is because beat 4 of the 6/8 occurs in the middle of the 6/8, and beat 3 of the 4/4 occurs in the middle of the 4/4; since the measure is the same length either way, they overlap at the halfway point. Another way of putting this is to say that 6 and 4 are both divisible by 2: if you divide something into 6 parts, and you also divide it into 4 parts, you’ll end up dividing it in half both times (3 + 3 vs. 2 + 2).
In this case, having the 4/4 and 6/8 overlap halfway across kind of makes the measure sound half as long. If we wanted to preserve the feel of the original measure length, one thing we could do is switch out the 6/8 for 3/4:
You can hear and see that now the two patterns only overlap on the first beat of the measure (the “downbeat” as it’s called). This is because the only factor 3 and 4 share is 1; no other positive integer divides them both. In number theory, 3 and 4 are said to be “coprime” for this reason.
When you layer rhythmic patterns in two different meters on top of one another like this, it’s called a “polyrhythm.” Because of the measure-shortening effect caused by using meters with non-coprime numbers of beats per measure, which tends to imply a different pattern than written—for instance the 6/8 vs. 4/4 example sounds rather like 3/4 vs. 2/4 instead—people tend to talk about polyrhythms where all the beats-per-measure of the meters used are coprime.
The Chopi culture of Mozambique is known worldwide for a distinctive traditional music style which makes intensive use of polyrhythm.
To abruptly travel from Mozambique to the Wumpuszőne, consider if we have a cave with only four rooms.
┌─┐ ┌─┐
│0│ │1│
└─┘ └─┘
┌─┐ ┌─┐
│2│ │3│
└─┘ └─┘
(I’m numbering them starting from 0, instead of from 1 like Wumpus does, because it makes the math a bit nicer.)
We want to connect them up so that every room is reachable from every other. In particular, we want to do this in a way where we start with the first room, 0, increment the room number by some amount modulo the total number of rooms (4 in this case), make a two-way connection between room 0 and the room with the next number, and then start with the next number and repeat, until we’ve covered all 4 rooms. We’ll call the amount we increment the room number by “Δ” (“delta”). The simplest Δ we could use is 1: that gives 0-1 (0 and 0+1 % 4), 1-2 (1 and 1+1 % 4), 2-3 (2 and 2+1 % 4), and 3-0 (3 and 3+1 % 4).
Δ = 1
┌─┐ ┌─┐
│0│─│1│
└─┘ └─┘
╳
┌─┐ ┌─┐
│2│─│3│
└─┘ └─┘
1 and any other positive integer are always coprime, because their greatest common divisor can only be 1. As you can see, this works: all the rooms are reachable from one another. What if we use a Δ of 2?
Δ = 2
┌─┐ ┌─┐
│0│ │1│
└─┘ └─┘
│ │
┌─┐ ┌─┐
│2│ │3│
└─┘ └─┘
We get “overlapping beats!” Since we have 0-2, 1-3, 2-0, and 3-1, and the connections are two-way, 0-2 and 2-0 become one connection, and 1-3 and 3-1 do as well. The trouble is that the Δ (2) and the total number of rooms (4) are not coprime, because 2 and 4 share a factor of 2. The musical analog is to layer 4/4 and 2/4:
You can hear how the 2/4 vanishes into the 4/4; its beats overlap the 4/4 on 1 and 3. Just as with the prior cave-connecting example, we get two points of overlap. With the cave connections, any overlaps will mean we end up with less total connections, so that we run short of the number we need to connect up all the rooms. That’s why the Δ and the room count have to be coprime if we want each room to be reachable everywhere using this approach.
Here’s Δ = 3:
Δ = 3
┌─┐ ┌─┐
│0│─│1│
└─┘ └─┘
╳
┌─┐ ┌─┐
│2│─│3│
└─┘ └─┘
It works out the same as Δ = 1, with all the rooms reachable from one another. We heard 4/4 and 3/4 earlier, of course, so we’ve encountered this already.
There is a general aesthetic principle we can extract from this discussion: whenever you’re layering discretely periodic things together in some sense, you can make the outcome “maximally busy” if you make all the periods mutually coprime. Conversely, if you want some points of overlap, you can hone in on exactly how many you’ll get by considering the common factors of the periods.
Another application I can think of to game design is in the context of a game like Harvest Moon: you can give the player more variety in their work day-to-day by having different types of farm tasks recur at mutually coprime numbers of days with one another. Likewise, in the case of turn-based RPG combat, if you have effects that take place over multiple turns, having the number of turns each effect lasts for be coprime with the others will give a lot of varied situations in combat from turn-to-turn. Perhaps you can think of yet more applications.
Also, as a side note, although this whole conversation has been about integers, there are ways of extending these ideas to the real and complex numbers. That’s its own topic, but if you’d like something to stimulate your imagination along those lines, here’s Steve Reich’s Piano Phase and some pictures of interference between spherical waves:







