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