Generating rooms that sit between two dungeon floors
The dungeon generator now sinks a room 3 m under one floor and puts a spiral stair in it, so the party walks down to the next floor without a lift.
A dungeon can now have a room that stands between two floors. A corridor on floor 1 turns a curved corner and goes down into the room, and a spiral stair in the room goes on down to floor 2. The party walks the whole way with no lift and no fade, and the generator lays one of these for about half of the pairs of floors.

The film’s 8 frames, in order, with captions.
Why add a room between floors?
I wanted floors that aren’t flat slabs that only meet at lifts. I’d described it as a rounded corridor that goes down to a room in between the two levels, and then continues down to the bottom. It’s the last step of the verticality work, so it uses the stairs, curves, spirals and sunk rooms I’d already built.
How does a room between work?
It needed no new mark on the dungeon sheet. A sunk room already exists on the sheet, and a spiral with a leads field already goes down to the next floor. The one thing in the way was that the ground code forced a spiral with leads to the floor’s base height, so it couldn’t stand in a sunk room. Now DungeonGround._settle leaves it at its own square’s floor, and the Python port of that code does the same. DungeonSpiral.pair() already measured the climb from the two squares’ floors, so the winding comes out right.
The room belongs to the upper floor. Its walls, lights, meat and monsters are that floor’s, and it’s built like any sunk room. A class called DungeonBetween calls a square between two floors when it stands 2.5 m or more off its floor’s base. The map draws the room on floor 1’s level and adds BETWEEN FLOORS 1 AND 2 to the level line while the party is in it. The stacking code already keeps rock under any sunk square, so floor 2 stands deeper under the room. In the test dungeon floor 2 is 10 m under floor 1 and the spiral climbs 7 m.
How does the generator pick the room?
tools/dungeon_jagged.py runs for each pair of floors after the climbing ducts, at a rate of 0.5 a pair drawn from the dungeon’s seed. It looks for a room of the upper floor with no entrance, exit, lift, ladder, duct, spiral, secret door or teleport in it, where every way in is a run of at least two corridor squares. Two squares matter because the ground refuses a stair steeper than 2 m a square. A way in that turns a curved corner first is tried first.
For the chosen room it lays a stair or ramp on each way in, a tunnel at the room’s depth to a spiral stair, and a tunnel dug on floor 2 to the spiral’s foot. The depth is tried at 3 m, then 3.5, 2.5 and 4 m, and the first one where the spiral’s winding fits is used. 3 m is half of a floor and its rock, which are 6 m together. Each attempt works on a deep copy of the floors, and it’s kept only if every spiral between floors still winds, the quick exit’s column stays in rock and both floors pass every hard check. Otherwise the copy is thrown away and the next depth or spot is tried.
If no room of the floor will sink, the generator digs a bare 3 by 3 room off a room’s wall, down a stair that turns a corner or goes two squares straight, with the spiral off its far wall. The dug room has walls, ceiling, lights and meat, but no room kind, so it has no furniture and no stocking. That’s still open.
How did I check it?
tests/jagged passes 35 checks with none failing. It plans the dungeon, stacks it, builds it solid in a theme, puts a monster in the room, walks from floor 1 to floor 2 and back, and checks the map. Sweeps of 40 two-floor seeds and 20 three-floor seeds laid 21 rooms between in each and failed none. --rising off still gives the old output byte for byte.
I kept the rate and the depth at half of the floor pairs and 3 m. The dungeon report’s floor pictures don’t mark a room between yet, so only the in-game map says so.