A dungeon now names the boss arena it ends in, and the arena decides the boss. Three entrances in the hub: Warden's Descent, The Choir Vault, Proving Grounds. That replaces the seed coin-flip from the last commit, which was the wrong call. Which boss you are about to fight is the single thing a player decides before walking into a dungeon, and rolling it for them makes that decision unavailable. Only the Proving Grounds still leaves its arena open, because a harness you re-enter every couple of minutes wants whichever fight comes up first -- and it is the one place where "either will do" is true. test_every_boss_has_a_dungeon_that_reaches_it is the check that matters here: adding a boss and forgetting to give it a way in is now a failing test rather than a boss nobody meets. The smoke test asserts all three portals open over a real socket -- bots pick theirs by account id, so a run exercises each. Bullets no longer animate. The sheet's eight frames are a COLOUR cycle rather than a shape change, so running it had every bullet on screen strobing through a palette in unison, which with a few hundred in the air is exactly as hard to look at as it sounds. Each bullet holds one frame and turns slowly instead, offset by its own id so a ring of twenty does not rotate as one rigid wheel. The rate is slow enough that nothing completes a full turn inside its own lifetime, so it reads as drift rather than spin, and a test pins that against the longest-lived bullet in the game. The renderer slices four textures at startup now instead of thirty-two. check.sh clean, 414 tests, SMOKE PASS (22 assertions), all four diagnostics green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
42568a40ad
commit
4a98cf4b0e
15 files changed
+251
-100
No files matched your search
+25
-1
@@ -9,10 +9,12 @@ extends RefCounted
|
||||
## one entry plus one marker.
|
||||
|
||||
const STANDARD := &"warden_descent"
|
||||
const VAULT := &"choir_vault"
|
||||
const PROVING := &"proving_grounds"
|
||||
|
||||
const ORDER: Array[StringName] = [
|
||||
STANDARD,
|
||||
VAULT,
|
||||
PROVING,
|
||||
]
|
||||
|
||||
@@ -24,6 +26,7 @@ static func default_id() -> StringName:
|
||||
static func get_def(id: StringName) -> DungeonDef:
|
||||
match id:
|
||||
STANDARD: return standard()
|
||||
VAULT: return vault()
|
||||
PROVING: return proving_grounds()
|
||||
return null
|
||||
|
||||
@@ -53,11 +56,28 @@ static func standard() -> DungeonDef:
|
||||
var d := DungeonDef.new()
|
||||
d.id = STANDARD
|
||||
d.display_name = "Warden's Descent"
|
||||
d.subtitle = "the real run"
|
||||
d.subtitle = "the Warden of the Fold"
|
||||
d.arena = &"warden_hall"
|
||||
d.tint = Color(0.5, 0.9, 1.0)
|
||||
return d
|
||||
|
||||
|
||||
## The second boss's own run. Same generator and the same enemies as the
|
||||
## Descent; what differs is the arena it ends in, and therefore who is waiting.
|
||||
##
|
||||
## A dedicated entrance rather than a coin flip on the run's seed: which boss
|
||||
## you are about to fight is the single thing a player decides before walking
|
||||
## into a dungeon, and rolling it for them makes that decision unavailable.
|
||||
static func vault() -> DungeonDef:
|
||||
var d := DungeonDef.new()
|
||||
d.id = VAULT
|
||||
d.display_name = "The Choir Vault"
|
||||
d.subtitle = "the Cantor of the Vault"
|
||||
d.arena = &"choir_vault"
|
||||
d.tint = Color(0.75, 0.6, 1.0)
|
||||
return d
|
||||
|
||||
|
||||
## A test harness you can walk into.
|
||||
##
|
||||
## Same generator, same rooms, same enemies and the same Warden -- everything
|
||||
@@ -71,6 +91,10 @@ static func proving_grounds() -> DungeonDef:
|
||||
d.id = PROVING
|
||||
d.display_name = "Proving Grounds"
|
||||
d.subtitle = "for testing -- fragile, generous"
|
||||
# Deliberately left to the seed. The harness exists to reach a fight fast,
|
||||
# and either fight will do -- runs here last a couple of minutes, so the one
|
||||
# you want is one re-entry away.
|
||||
d.arena = &""
|
||||
d.enemy_hp_mult = 0.2
|
||||
d.boss_hp_mult = 0.08
|
||||
# 0.08 -> 0.8 for trash. High enough that a handful of kills fills a bag,
|
||||
|
||||
@@ -112,17 +112,17 @@ static func stamp(grid: MapGrid, s: PackedStringArray, origin: Vector2i) -> Dict
|
||||
## P a dungeon portal S player spawn T practice target
|
||||
## U the upgrade NPC
|
||||
##
|
||||
## Each `P`, in reading order, opens the matching entry in Dungeons.ORDER. Two
|
||||
## of them now: the real run and the Proving Grounds, side by side so they can
|
||||
## be compared without restarting anything. Adding a third dungeon means adding
|
||||
## a third marker here.
|
||||
## Each `P`, in reading order, opens the matching entry in Dungeons.ORDER: the
|
||||
## Warden's Descent, the Choir Vault, and the Proving Grounds. Adding a dungeon
|
||||
## means adding an entry there and a marker here, and they have to stay in the
|
||||
## same order.
|
||||
static func lobby() -> PackedStringArray:
|
||||
return PackedStringArray([
|
||||
"#########################################",
|
||||
"#.......................................#",
|
||||
"#.......................................#",
|
||||
"#.......................................#",
|
||||
"#..............P.........P..............#",
|
||||
"#.........P.........P.........P.........#",
|
||||
"#.......................................#",
|
||||
"#.....o...........................o.....#",
|
||||
"#.......................................#",
|
||||
|
||||
Reference in new issue
Block a user