afterglow/sim/rooms_data.py¶

Part of Afterglow.

  1"""Authored room data for Afterglow: the full game, three worlds.
  2
  3Eighteen LARGE single-screen rooms (56 wide x 30 tall at our 8px tile; the camera
  4auto-frames the whole grid) that TEACH BY DESIGN, no text tutorials. Each room has a
  5real winding path with the exit set well away from the spawn (usually a vertical climb
  6or a gated crossing), so you cannot simply walk-and-hop straight at it. The difficulty
  7curve hands the player one new idea at a time and then asks them to combine ideas:
  8
  9  WORLD 1  'glade'   (6 rooms): pure movement, NO instant-death hazards (a miss just
 10      lands on a lower floor). run + variable-height jump -> a stepped climb -> a longer
 11      run-jump ascent -> the wall-jump (a short shaft, then a tall one) -> a graduation
 12      that adds a spring. No dash, crystals, orbs or gates.
 13  WORLD 2  'caverns' (6 rooms): the air-DASH + telegraphed hazards. the dash alone over
 14      a chasm, then a two-gap crossing, then resonance CRYSTALS (dash-through refills the
 15      dash), a 2-crystal chain, a rising up-dash constellation, and the long dash-chain.
 16  WORLD 3  'spire'   (6 rooms): GLOW ORBS + LIGHT-GATES (a gate is solid only while the
 17      Wisp glows) braided with dash-chains and hazards. introduced gently (fetch the
 18      light, cross the bridge), then under a 4s glow clock, then with the dash, then a
 19      vertical gate shaft, a timed dash-chain, and a climactic finale.
 20
 21Each room has exactly one spawn 'P', one exit 'E', and one hidden shard '*' tucked off
 22the main path as the expert-optional challenge. Every row is exactly 56 characters; see
 23tests/test_rooms.py for the structural gate and tests/test_solvable.py for the
 24reachability + naive-gating + scripted-solution proofs.
 25
 26Grid legend (see sim.tiles): equal-length rows, y-DOWN, one char / 8px tile:
 27  '.' empty | '#' solid | '^' hazard | 'C' crystal | 'O' glow orb |
 28  'G' light-gate | 'S' spring | '*' hidden shard | '-' moving platform |
 29  'P' spawn | 'E' exit.
 30"""
 31
 32from __future__ import annotations
 33
 34from .room import RoomDef
 35
 36# ---------------------------------------------------------------------------
 37# WORLD 1 -- THE GLADE: pure movement fundamentals (no hazards).
 38# ---------------------------------------------------------------------------
 39
 40# 1.1 First Light: gentle opener. An ascending staircase of platforms climbs up-and-
 41# right from the low-left spawn to a high-right exit, growing gaps teaching the run and
 42# the variable-height jump. The exit is too high to walk to: you must climb. Shard on a
 43# low side ledge below the start (an optional drop-and-return off the ascent).
 44_GLADE_01 = RoomDef(
 45    name="First Light",
 46    palette="glade",
 47    grid=[
 48        "########################################################",
 49        "########################################################",
 50        "#..................................................#####",
 51        "#..............................................E...#####",
 52        "#...........................................########...#",
 53        "#......................................................#",
 54        "#......................................................#",
 55        "#.................................############.........#",
 56        "#......................................................#",
 57        "#......................................................#",
 58        "#......................................................#",
 59        "#......................############....................#",
 60        "#......................................................#",
 61        "#......................................................#",
 62        "#......................................................#",
 63        "#...........#####......................................#",
 64        "#......................................................#",
 65        "#......................................................#",
 66        "#...................*..................................#",
 67        "#.................#####................................#",
 68        "#......................................................#",
 69        "#......................................................#",
 70        "#......................................................#",
 71        "##########.............................................#",
 72        "#......................................................#",
 73        "#......................................................#",
 74        "#.P....................................................#",
 75        "########################################################",
 76        "########################################################",
 77        "########################################################",
 78    ],
 79)
 80
 81# 1.2 Over the Brook: a stepped ascent over a wide trough. Stair platforms rise to a
 82# high-right exit ledge; missing a step drops you onto the safe lower floor (a brook,
 83# no hazard in the glade), never a punishing pit. Shard on a high ledge above the exit.
 84_GLADE_02 = RoomDef(
 85    name="Over the Brook",
 86    palette="glade",
 87    grid=[
 88        "########################################################",
 89        "#......................................................#",
 90        "#......................................................#",
 91        "#......................................................#",
 92        "#.......................................E..............#",
 93        "#......................................####............#",
 94        "#......................................................#",
 95        "#......................................................#",
 96        "#......................................................#",
 97        "#.............................................*........#",
 98        "#...........................................########...#",
 99        "#......................................................#",
100        "#.................................######...............#",
101        "#......................................................#",
102        "#.........................######.......................#",
103        "#......................................................#",
104        "#.................######...............................#",
105        "#......................................................#",
106        "#.........######.......................................#",
107        "#......................................................#",
108        "#......................................................#",
109        "#......................................................#",
110        "#......................................................#",
111        "#.P....................................................#",
112        "#########..............................................#",
113        "#......................................................#",
114        "#......................................................#",
115        "########################################################",
116        "########################################################",
117        "########################################################",
118    ],
119)
120
121# 1.3 Stepping Stones: a long run of platforms with widening gaps rising to a high
122# exit; commit to run-jumps and read the spacing. Spawn low-left, exit high-right.
123# Shard on a low side ledge below the start (drop off the main line and climb back).
124_GLADE_03 = RoomDef(
125    name="Stepping Stones",
126    palette="glade",
127    grid=[
128        "########################################################",
129        "########################################################",
130        "#................................................#######",
131        "#..............................................E.#######",
132        "#...........................................########...#",
133        "#......................................................#",
134        "#......................................................#",
135        "#...........................................#######....#",
136        "#.......................................###########....#",
137        "#......................................................#",
138        "#......................................................#",
139        "#.............................###############..........#",
140        "#......................................................#",
141        "#......................................................#",
142        "#......................................................#",
143        "#.................................#############........#",
144        "#......................................................#",
145        "#......................................................#",
146        "#.......................###############................#",
147        "#......................................................#",
148        "#......................................................#",
149        "#.............###############..........................#",
150        "#......................................................#",
151        "#.*....................................................#",
152        "#####.#############....................................#",
153        "#......................................................#",
154        "#...P..................................................#",
155        "########################################################",
156        "########################################################",
157        "########################################################",
158    ],
159)
160
161# 1.4 The Lean: introduce the wall-jump in a short, gentle 2-wide shaft. Spawn at the
162# base; alternate wall-jumps up the two faces to a ledge bearing the exit at the top.
163# Falling drops back to the shaft floor (no hazard). Shorter than the Chimney so the
164# idea lands before the full test. Shard on a ledge off the right wall.
165_GLADE_04 = RoomDef(
166    name="The Lean",
167    palette="glade",
168    grid=[
169        "########################################################",
170        "#......................................................#",
171        "#......................................................#",
172        "#................E.....................................#",
173        "#..............#####...................................#",
174        "####################..##################################",
175        "####################..##################################",
176        "####################..##################################",
177        "#################.....##################################",
178        "#################.*...##################################",
179        "####################..##################################",
180        "####################..##################################",
181        "####################..##################################",
182        "####################..##################################",
183        "####################..##################################",
184        "####################..##################################",
185        "####################..##################################",
186        "####################..##################################",
187        "####################..##################################",
188        "####################P.##################################",
189        "###################.##.#################################",
190        "###################.##.#################################",
191        "###################.##.#################################",
192        "###################.##.#################################",
193        "###################.##.#################################",
194        "###################.##.#################################",
195        "###################.##.#################################",
196        "########################################################",
197        "########################################################",
198        "########################################################",
199    ],
200)
201
202# 1.5 Chimney: the pure wall-jump test, a tall narrow 2-wide shaft climbed by
203# alternating wall-jumps; the top opens onto a ledge bearing the exit. Shard on a
204# ledge off the right pillar partway up (an optional dismount).
205_GLADE_05 = RoomDef(
206    name="Chimney",
207    palette="glade",
208    grid=[
209        "########################################################",
210        "#......................................................#",
211        "#...................E..................................#",
212        "#.................#####................................#",
213        "#.......................#..#...........................#",
214        "#.......................#..#...........................#",
215        "#.......................#..#...........................#",
216        "#.......................#..#...........................#",
217        "#.......................#.##...........................#",
218        "#.......................#..#...........................#",
219        "#.......................#..#...........................#",
220        "#.......................#..#...........................#",
221        "#.......................##.#*..........................#",
222        "#.......................#..##..........................#",
223        "#.......................#..#...........................#",
224        "#.......................#..#...........................#",
225        "#.......................#.##...........................#",
226        "#.......................#..#...........................#",
227        "#.......................#..#...........................#",
228        "#.......................#..#...........................#",
229        "#.......................##.#...........................#",
230        "#.......................#..#...........................#",
231        "#.......................#P.#...........................#",
232        "########################################################",
233        "#......................................................#",
234        "#......................................................#",
235        "#......................................................#",
236        "#......................................................#",
237        "########################################################",
238        "########################################################",
239    ],
240)
241
242# 1.6 Glade's End: the graduation. Run-jump up a flight of platforms, then a spring
243# launches you to the high exit ledge (too high to reach by jump alone), combining the
244# run, the variable jump and the spring. Shard on a side ledge near the spring's arc.
245_GLADE_06 = RoomDef(
246    name="Glade's End",
247    palette="glade",
248    grid=[
249        "########################################################",
250        "########################################################",
251        "#......................................#################",
252        "#....................................E.#################",
253        "#.........................##.....##############........#",
254        "#......................................................#",
255        "#......................................................#",
256        "#......................................................#",
257        "#......................................................#",
258        "#......................................................#",
259        "#......................................................#",
260        "#....................*.................................#",
261        "#..................#####......S........................#",
262        "#.......................#############..................#",
263        "#......................................................#",
264        "#......................................................#",
265        "#.....................#############....................#",
266        "#......................................................#",
267        "#.............#############............................#",
268        "#......................................................#",
269        "#......................................................#",
270        "#.......#############..................................#",
271        "#......................................................#",
272        "#......................................................#",
273        "#.###########..........................................#",
274        "#......................................................#",
275        "#..P...................................................#",
276        "########################################################",
277        "########################################################",
278        "########################################################",
279    ],
280)
281
282# ---------------------------------------------------------------------------
283# WORLD 2 -- THE CAVERNS: the air-dash, resonance crystals, dash-chains.
284# ---------------------------------------------------------------------------
285
286# 2.1 First Spark: a chasm too wide to jump; an air-dash carries you across. Spawn and
287# the far exit ledge sit at the same height (a clean horizontal dash) so the dash reads
288# in isolation. Hazard floor under the chasm (telegraphed). Shard on a lower-right ledge
289# (a downward dash off the line).
290_CAVERNS_01 = RoomDef(
291    name="First Spark",
292    palette="caverns",
293    grid=[
294        "########################################################",
295        "#......................................................#",
296        "#......................................................#",
297        "#......................................................#",
298        "#......................................................#",
299        "#......................................................#",
300        "#......................................................#",
301        "#......................................................#",
302        "#.P....................................................#",
303        "###############...............*........................#",
304        "###############.............##############.............#",
305        "#......................................................#",
306        "#......................................................#",
307        "#...........................................E..........#",
308        "#.........................................#####........#",
309        "#......................................................#",
310        "#......................................................#",
311        "#......................................................#",
312        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
313        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
314        "#......................................................#",
315        "#......................................................#",
316        "#......................................................#",
317        "#......................................................#",
318        "#......................................................#",
319        "#......................................................#",
320        "#......................................................#",
321        "#......................................................#",
322        "########################################################",
323        "########################################################",
324    ],
325)
326
327# 2.2 Crossing: two chasms in a row; the dash recharges on landing, so each gap is its
328# own dash, with a mid platform between and a stepping ledge climbing out of the second
329# one. Both gaps cross a hazard floor. Shard high over the mid platform (an up-aimed
330# dash).
331_CAVERNS_02 = RoomDef(
332    name="Crossing",
333    palette="caverns",
334    grid=[
335        "########################################################",
336        "#......................................................#",
337        "#......................................................#",
338        "#......................................................#",
339        "#.........................*......................E.....#",
340        "#.......................#####..................#####...#",
341        "#......................................................#",
342        "#......................................................#",
343        "#......................................................#",
344        "#....................................#####.............#",
345        "#......................................................#",
346        "#......................................................#",
347        "#......................................................#",
348        "#.....................########.........................#",
349        "#......................................................#",
350        "#......................................................#",
351        "#.P....................................................#",
352        "##########.............................................#",
353        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
354        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
355        "#......................................................#",
356        "#......................................................#",
357        "#......................................................#",
358        "#......................................................#",
359        "#......................................................#",
360        "#......................................................#",
361        "#......................................................#",
362        "#......................................................#",
363        "########################################################",
364        "########################################################",
365    ],
366)
367
368# 2.3 Resonance: one resonance crystal hangs mid-chasm. Dash into it to shatter and
369# refill the dash, then dash again to the far exit. The core dash-refill lesson over a
370# hazard chasm. Shard on a low ledge mid-chasm (an angled-down dash off the line).
371_CAVERNS_03 = RoomDef(
372    name="Resonance",
373    palette="caverns",
374    grid=[
375        "########################################################",
376        "#......................................................#",
377        "#......................................................#",
378        "#......................................................#",
379        "#......................................................#",
380        "#......................................................#",
381        "#......................................................#",
382        "#......................................................#",
383        "#.........................C............................#",
384        "#......................................................#",
385        "#.P....................................................#",
386        "#########..............................................#",
387        "#......................................................#",
388        "#...........................................E..........#",
389        "#.........................................#######......#",
390        "#......................................................#",
391        "#...................*..................................#",
392        "#.................####.................................#",
393        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
394        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
395        "#......................................................#",
396        "#......................................................#",
397        "#......................................................#",
398        "#......................................................#",
399        "#......................................................#",
400        "#......................................................#",
401        "#......................................................#",
402        "#......................................................#",
403        "########################################################",
404        "########################################################",
405    ],
406)
407
408# 2.4 Twin Lights: two crystals stagger across the chasm: dash, refill, dash, refill,
409# dash. A short constellation building the chaining rhythm over a hazard floor. Shard
410# high above the second crystal (aim the middle dash a touch upward).
411_CAVERNS_04 = RoomDef(
412    name="Twin Lights",
413    palette="caverns",
414    grid=[
415        "########################################################",
416        "########################################################",
417        "########################################################",
418        "#......................................................#",
419        "#......................................................#",
420        "#.......................*..............................#",
421        "#.....................#####............................#",
422        "#......................................................#",
423        "#......................................................#",
424        "#......................................................#",
425        "#......................................................#",
426        "#.......................................################",
427        "#.P...........C.........C.........E.....################",
428        "#########.......................#######................#",
429        "#......................................................#",
430        "#......................................................#",
431        "#......................................................#",
432        "#......................................................#",
433        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
434        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
435        "#......................................................#",
436        "#......................................................#",
437        "#......................................................#",
438        "#......................................................#",
439        "#......................................................#",
440        "#......................................................#",
441        "#......................................................#",
442        "########################################################",
443        "########################################################",
444        "########################################################",
445    ],
446)
447
448# 2.5 Constellation: a rising diagonal of crystals demands an upward dash-chain. Jump
449# off the spawn ledge, then up-right dash through each crystal so it refills the dash for
450# the next angled dash, climbing to the apex exit. Shard on a high-left ledge off the
451# chain.
452_CAVERNS_05 = RoomDef(
453    name="Constellation",
454    palette="caverns",
455    grid=[
456        "########################################################",
457        "#......................................................#",
458        "#......................................................#",
459        "#.......................................E..............#",
460        "#.....................................#####............#",
461        "#......................................................#",
462        "#................................C.....................#",
463        "#......................................................#",
464        "#..........................C...........................#",
465        "#......................................................#",
466        "#....................C.................................#",
467        "#.....*................................................#",
468        "#...####.......C.......................................#",
469        "#......................................................#",
470        "#......................................................#",
471        "#.P....................................................#",
472        "#########..............................................#",
473        "#......................................................#",
474        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
475        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
476        "#......................................................#",
477        "#......................................................#",
478        "#......................................................#",
479        "#......................................................#",
480        "#......................................................#",
481        "#......................................................#",
482        "#......................................................#",
483        "#......................................................#",
484        "########################################################",
485        "########################################################",
486    ],
487)
488
489# 2.6 The Long Dark: the caverns capstone and the longest dash-chain. Three crystals
490# strung across a very wide hazard chasm, each refilling the dash for the next, carrying
491# the Wisp all the way to the far exit. Shard tucked low past the mid-chain.
492_CAVERNS_06 = RoomDef(
493    name="The Long Dark",
494    palette="caverns",
495    grid=[
496        "########################################################",
497        "#......................................................#",
498        "#......................................................#",
499        "#......................................................#",
500        "#......................................................#",
501        "#......................................................#",
502        "#......................................................#",
503        "#......................................................#",
504        "#...............C...........C...........C..............#",
505        "#......................................................#",
506        "#.P....................................................#",
507        "########...............................................#",
508        "#................................................E.....#",
509        "#..............................................######..#",
510        "#......................................................#",
511        "#.................................*....................#",
512        "#...............................####...................#",
513        "#......................................................#",
514        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
515        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
516        "#......................................................#",
517        "#......................................................#",
518        "#......................................................#",
519        "#......................................................#",
520        "#......................................................#",
521        "#......................................................#",
522        "#......................................................#",
523        "#......................................................#",
524        "########################################################",
525        "########################################################",
526    ],
527)
528
529# ---------------------------------------------------------------------------
530# WORLD 3 -- THE AETHER SPIRE: glow orbs + light-gates, then the finale.
531# ---------------------------------------------------------------------------
532
533# 3.1 Kindling: the first orb + gate. The orb sits to the LEFT of spawn (away from the
534# exit): fetch the light, return, then cross the now-solid gate bridge to the exit on the
535# right. Walking straight at the exit steps onto an open (unglowing) gate and drops into
536# a deep but SAFE pit you cannot climb back out of toward the exit. Gentle, no hazards.
537# Shard above, behind a second gate the same glow opens.
538_SPIRE_01 = RoomDef(
539    name="Kindling",
540    palette="spire",
541    grid=[
542        "########################################################",
543        "#......................................................#",
544        "#......................................................#",
545        "#......................................................#",
546        "#......................................................#",
547        "#......................................................#",
548        "#......................................................#",
549        "#......................................................#",
550        "#.......P.....GGGGGGGGGGGGGGGGGGGGGGGG....E............#",
551        "###...########........................##########.......#",
552        "#......................................................#",
553        "#......................................................#",
554        "#......................................................#",
555        "#...O...........*......................................#",
556        "#..###.........###.....................................#",
557        "#......................................................#",
558        "#......................................................#",
559        "#......................................................#",
560        "#......................................................#",
561        "#......................................................#",
562        "#......................................................#",
563        "#......................................................#",
564        "#......................................................#",
565        "#......................................................#",
566        "#......................................................#",
567        "#......................................................#",
568        "########################################################",
569        "#......................................................#",
570        "########################################################",
571        "########################################################",
572    ],
573)
574
575# 3.2 Hold the Light: the glow is a 4s clock. Grab the orb, cross a long gate bridge
576# before it fades; now hazards lurk under the bridge. Spawn left, exit right. Shard past
577# a second, higher gate bridge.
578_SPIRE_02 = RoomDef(
579    name="Hold the Light",
580    palette="spire",
581    grid=[
582        "########################################################",
583        "#......................................................#",
584        "#......................................................#",
585        "#....O.................................................#",
586        "#......................................................#",
587        "#.......................................*..............#",
588        "#....C...........................GGGGGG.##.............#",
589        "#......................................................#",
590        "#......................................................#",
591        "#....C.................................................#",
592        "#......................................................#",
593        "#......................................................#",
594        "#.P..S.................................................#",
595        "########....GGGGGGGGGGGGGG..................E..........#",
596        "########..................................####.........#",
597        "#.......^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^............#",
598        "#......................................................#",
599        "#......................................................#",
600        "#......................................................#",
601        "#......................................................#",
602        "#......................................................#",
603        "#......................................................#",
604        "#......................................................#",
605        "#......................................................#",
606        "#......................................................#",
607        "#......................................................#",
608        "#......................................................#",
609        "#......................................................#",
610        "########################################################",
611        "########################################################",
612    ],
613)
614
615# 3.3 Quickening: combine the dash with the gate. Grab the orb, dash across a hazard gap
616# onto a gate bridge that only exists while you glow; the dash gets you there in time.
617# Shard high-left (an up-dash off a crystal). The orb is left of the dash line so a dash
618# without glowing falls.
619_SPIRE_03 = RoomDef(
620    name="Quickening",
621    palette="spire",
622    grid=[
623        "########################################################",
624        "#......................................................#",
625        "#......................................................#",
626        "#.........*............................................#",
627        "#.......####...........................................#",
628        "#......................................................#",
629        "#..........C...........................................#",
630        "#......................................................#",
631        "#......................................................#",
632        "#......................................................#",
633        "#...O...P..............................................#",
634        "###############.........GGGGGGGGGG......E..............#",
635        "###############...................########.............#",
636        "#......................................................#",
637        "#......................................................#",
638        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
639        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
640        "#......................................................#",
641        "#......................................................#",
642        "#......................................................#",
643        "#......................................................#",
644        "#......................................................#",
645        "#......................................................#",
646        "#......................................................#",
647        "#......................................................#",
648        "#......................................................#",
649        "#......................................................#",
650        "#......................................................#",
651        "########################################################",
652        "########################################################",
653    ],
654)
655
656# 3.4 Lantern Climb: a vertical gate shaft. Grab the orb at the base, then wall-jump up
657# the two gate pillars (solid only while glowing) to the exit at the top, racing the 4s
658# glow clock. Shard on a ledge off the shaft's right wall.
659_SPIRE_04 = RoomDef(
660    name="Lantern Climb",
661    palette="spire",
662    grid=[
663        "########################################################",
664        "#......................................................#",
665        "#......................................................#",
666        "#......................................................#",
667        "#......................................................#",
668        "#......................................................#",
669        "#......................................................#",
670        "#........E.............................................#",
671        "####################...................................#",
672        "#.....................G..G.............................#",
673        "#.....................G..G*............................#",
674        "#.....................G..G###..........................#",
675        "#.....................G..G.............................#",
676        "#.....................G..G.............................#",
677        "#.....................G..G.............................#",
678        "#.....................G..G.............................#",
679        "#.....................G..G.............................#",
680        "#.....................G..G.............................#",
681        "#.....................G..G...............O.............#",
682        "#.....................G..G.............................#",
683        "#.....................G..G.............................#",
684        "#.....................G................................#",
685        "#.....................G.P..............................#",
686        "########################################################",
687        "#......................................................#",
688        "#......................................................#",
689        "#......................................................#",
690        "#......................................................#",
691        "########################################################",
692        "########################################################",
693    ],
694)
695
696# 3.5 Beacon Run: the timed dash-chain across gates. Grab the orb, dash, a crystal
697# mid-chasm refills the dash, then a gate bridge, all under the 4s glow clock. The
698# hardest pre-finale room. Shard hidden low over the hazard (an angled-down dash off the
699# easy line).
700_SPIRE_05 = RoomDef(
701    name="Beacon Run",
702    palette="spire",
703    grid=[
704        "########################################################",
705        "#......................................................#",
706        "#......................................................#",
707        "#......................................................#",
708        "#......................................................#",
709        "#......................................................#",
710        "#......................................................#",
711        "#......................................................#",
712        "#......................................................#",
713        "#......................................................#",
714        "#...O...P..............................................#",
715        "###########.........C.......GGGGGGGGGG......E..........#",
716        "###########...........................########.........#",
717        "#......................................................#",
718        "#...............*......................................#",
719        "#.............####.....................................#",
720        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
721        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
722        "#......................................................#",
723        "#......................................................#",
724        "#......................................................#",
725        "#......................................................#",
726        "#......................................................#",
727        "#......................................................#",
728        "#......................................................#",
729        "#......................................................#",
730        "#......................................................#",
731        "#......................................................#",
732        "########################################################",
733        "########################################################",
734    ],
735)
736
737# 3.6 The Aether Spire: THE FINALE, braiding every mechanic. Grab the orb, dash through
738# a resonance crystal to refill, dash onto the timed gate bridge (solid only while
739# glowing), cross it, then ride a spring up to the summit exit. Climactic and fair.
740# Shard on a high ledge past the spring.
741_SPIRE_06 = RoomDef(
742    name="The Aether Spire",
743    palette="spire",
744    grid=[
745        "########################################################",
746        "#......................................................#",
747        "#...........................................E..........#",
748        "#.........................................######.......#",
749        "#......................................................#",
750        "#.................................................*....#",
751        "#...............................................####...#",
752        "#......................................................#",
753        "#......................................................#",
754        "#......................................................#",
755        "#......................................................#",
756        "#...O...P..............................................#",
757        "###########.........C.......GGGGGGGGGG......S..........#",
758        "###########...........................########.........#",
759        "#......................................................#",
760        "#......................................................#",
761        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
762        "#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#",
763        "#......................................................#",
764        "#......................................................#",
765        "#......................................................#",
766        "#......................................................#",
767        "#......................................................#",
768        "#......................................................#",
769        "#......................................................#",
770        "#......................................................#",
771        "#......................................................#",
772        "#......................................................#",
773        "########################################################",
774        "########################################################",
775    ],
776)
777
778
779WORLDS = [
780    {
781        "id": "glade",
782        "name": "The Glade",
783        "rooms": [_GLADE_01, _GLADE_02, _GLADE_03, _GLADE_04, _GLADE_05, _GLADE_06],
784    },
785    {
786        "id": "caverns",
787        "name": "The Caverns",
788        "rooms": [_CAVERNS_01, _CAVERNS_02, _CAVERNS_03, _CAVERNS_04, _CAVERNS_05, _CAVERNS_06],
789    },
790    {
791        "id": "spire",
792        "name": "The Aether Spire",
793        "rooms": [_SPIRE_01, _SPIRE_02, _SPIRE_03, _SPIRE_04, _SPIRE_05, _SPIRE_06],
794    },
795]