The initiative warning becomes authored data, and staging gets a harness
Unreleased. The warning that v0.6.4 deleted is restored, but not as the string heuristic that caused both faults — rosters carry beforeInitiative now, and the renderers print it. 23 rosters have it: the 18 whose harmedBy restricts what works, plus 5 Troll rosters that carried the instruction in prose and so had two conventions between them. The prose copies are gone, so it is said exactly once wherever it is said. validate-pack enforces both halves — ONLY implies the field, and the phrase may not appear in prose — and core/test.mjs now runs the validator over all sixteen packs, so a pack regression fails the suite rather than waiting for someone to remember the tool. Both rules were confirmed by breaking a pack deliberately. enter()'s decisions move to module/stage.mjs behind injected effects, which makes the failure paths runnable under plain node. That immediately found a bug in the first version of the extraction: Promise.resolve(fx.stage()) does not catch a synchronous throw, so a Forge that threw rather than rejected would have taken the whole of enter() down. Nineteen of the new tests are that matrix — failed scene, failed population with and without a roster, failed hoard, failed cards, async rejection, and a Forge that returns nothing. The contract those tests hold: the scene is the commit point. Fail there and nothing was entered, so a retry is safe; succeed and the turn advances before anything else can fail, so a retry cannot restage. Everything after degrades with a warning that says what was actually lost — the encounter failure no longer promises a roster the area does not have, and the hoard failure is no longer swallowed to the console. Also: game.delve.loadPack is the validating resolver, so raiseDungeon can no longer stage from a pack with no forgeStageType. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9d220a3428
commit
0bbf57b693
@@ -2110,7 +2110,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons ONLY",
|
||||
"avoid": "it will take an appeasement over a fight every time"
|
||||
"avoid": "it will take an appeasement over a fight every time",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
},
|
||||
"nightmare": {
|
||||
"line": "1 Wraith, 1 Ghoul and 4 Skeletons",
|
||||
@@ -2156,4 +2157,4 @@
|
||||
},
|
||||
"_globalPoolsNote": "decisions/temptations/features below are FALLBACKS ONLY. Real content is motif-scoped under motifs.<id>.",
|
||||
"placeNameStyle": "claimant"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +381,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest",
|
||||
"avoid": "do not run this without an appeasement route open"
|
||||
"avoid": "do not run this without an appeasement route open",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1171,4 +1172,4 @@
|
||||
}
|
||||
},
|
||||
"placeNameStyle": "claimant"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,8 +346,9 @@
|
||||
"note": "douses open flames on a hit"
|
||||
}
|
||||
],
|
||||
"harmedBy": "anything, but the Troll only stays down if fire touches it — say so before initiative, and note the swarm is putting your fires out",
|
||||
"avoid": "it will not leave the water; stay off the streamway and it stays in"
|
||||
"harmedBy": "anything, but the Troll only stays down if fire touches it, and note the swarm is putting your fires out",
|
||||
"avoid": "it will not leave the water; stay off the streamway and it stays in",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
},
|
||||
"nightmare": {
|
||||
"line": "1 Troll, 1 Ogre and 3 Ghouls of the Kept",
|
||||
@@ -1170,4 +1171,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +382,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest",
|
||||
"avoid": "it will not strike anyone kneeling — say so before initiative"
|
||||
"avoid": "it will not strike anyone kneeling",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1171,4 +1172,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +396,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest",
|
||||
"avoid": "do not run this without an appeasement route open"
|
||||
"avoid": "do not run this without an appeasement route open",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1185,4 +1186,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,7 +383,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; fire for the Troll; anything for the wolves",
|
||||
"avoid": "the Hunt passes over anyone standing perfectly still — say so before initiative"
|
||||
"avoid": "the Hunt passes over anyone standing perfectly still",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1173,4 +1174,4 @@
|
||||
}
|
||||
},
|
||||
"placeNameStyle": "claimant"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,8 +337,9 @@
|
||||
"note": "free Called Shot to freeze on a hit"
|
||||
}
|
||||
],
|
||||
"harmedBy": "anything, but the Troll only stays down if fire touches it, and everything here is wet — say so before initiative",
|
||||
"avoid": "it will not go into deep water; the boat is safe from it and the shore is not"
|
||||
"harmedBy": "anything, but the Troll only stays down if fire touches it, and everything here is wet",
|
||||
"avoid": "it will not go into deep water; the boat is safe from it and the shore is not",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
},
|
||||
"nightmare": {
|
||||
"line": "1 Wraith standing on the water, 1 Troll and 4 Ghouls",
|
||||
@@ -372,7 +373,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest, fire for the Troll and it is wet",
|
||||
"avoid": "do not run this without an appeasement route open"
|
||||
"avoid": "do not run this without an appeasement route open",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1161,4 +1163,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +397,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest",
|
||||
"avoid": "do not run this without an appeasement route open"
|
||||
"avoid": "do not run this without an appeasement route open",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1186,4 +1187,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,8 +338,9 @@
|
||||
"note": "hold the top of the gully"
|
||||
}
|
||||
],
|
||||
"harmedBy": "anything, but the Troll only stays down if fire touches it — say so before initiative, and there is no fuel above the snowline",
|
||||
"avoid": "it will not leave the gully; the buttress is longer and it is climbable"
|
||||
"harmedBy": "anything, but the Troll only stays down if fire touches it, and there is no fuel above the snowline",
|
||||
"avoid": "it will not leave the gully; the buttress is longer and it is climbable",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
},
|
||||
"nightmare": {
|
||||
"line": "1 Wraith above the snowline, 1 Troll and 3 Dire Wolves",
|
||||
@@ -373,7 +374,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest, fire for the Troll",
|
||||
"avoid": "do not run this without an appeasement route open and shelter within a Turn"
|
||||
"avoid": "do not run this without an appeasement route open and shelter within a Turn",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1162,4 +1164,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,8 +347,9 @@
|
||||
"note": "fearless"
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the Skeletons — say so before initiative",
|
||||
"avoid": "it would far rather be flattered than fight, and will pause to be"
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the Skeletons",
|
||||
"avoid": "it would far rather be flattered than fight, and will pause to be",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
},
|
||||
"nightmare": {
|
||||
"line": "1 Wraith, 1 Ogre in the under-stair and 4 Skeletons",
|
||||
@@ -382,7 +383,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest",
|
||||
"avoid": "do not run this without an appeasement route open"
|
||||
"avoid": "do not run this without an appeasement route open",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1171,4 +1173,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,8 +360,9 @@
|
||||
"note": "fearless; still working the ship they died on"
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the Skeletons — say so before initiative",
|
||||
"avoid": "it wants the crew accounted for; name one of the drowned and it stops to enter them"
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the Skeletons",
|
||||
"avoid": "it wants the crew accounted for; name one of the drowned and it stops to enter them",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
},
|
||||
"nightmare": {
|
||||
"line": "1 Wraith, 1 Ogre out of the mud berth and 5 Skeletons",
|
||||
@@ -395,7 +396,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest",
|
||||
"avoid": "do not run this without an appeasement route open"
|
||||
"avoid": "do not run this without an appeasement route open",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1184,4 +1186,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,8 +337,9 @@
|
||||
"note": "free Called Shot to freeze on a hit"
|
||||
}
|
||||
],
|
||||
"harmedBy": "anything, but the Troll only stays down if fire touches it, and everything here is wet — say so before initiative",
|
||||
"avoid": "it holds the bridge and takes a toll; pay it and it lets you over"
|
||||
"harmedBy": "anything, but the Troll only stays down if fire touches it, and everything here is wet",
|
||||
"avoid": "it holds the bridge and takes a toll; pay it and it lets you over",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
},
|
||||
"nightmare": {
|
||||
"line": "1 Wraith at the ford, 1 Troll and 4 Ghouls",
|
||||
@@ -372,7 +373,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest, fire for the Troll and it is wet",
|
||||
"avoid": "do not run this without an appeasement route open"
|
||||
"avoid": "do not run this without an appeasement route open",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1161,4 +1163,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +382,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest",
|
||||
"avoid": "it does not strike anyone who has said nothing — say so before initiative"
|
||||
"avoid": "it does not strike anyone who has said nothing",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1171,4 +1172,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +397,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest",
|
||||
"avoid": "do not run this without an appeasement route open"
|
||||
"avoid": "do not run this without an appeasement route open",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1187,4 +1188,4 @@
|
||||
}
|
||||
},
|
||||
"placeNameStyle": "own"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,8 +337,9 @@
|
||||
"note": "hold the ground below it"
|
||||
}
|
||||
],
|
||||
"harmedBy": "anything, but the Troll only stays down if fire touches it — say so before initiative; there is wood in the hanging wood",
|
||||
"avoid": "it holds the head wall and nothing else; the col is a longer climb and it is clear"
|
||||
"harmedBy": "anything, but the Troll only stays down if fire touches it; there is wood in the hanging wood",
|
||||
"avoid": "it holds the head wall and nothing else; the col is a longer climb and it is clear",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
},
|
||||
"nightmare": {
|
||||
"line": "1 Wraith on the col, 1 Troll, 1 Ogre and 2 Dire Wolves",
|
||||
@@ -381,7 +382,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest, fire for the Troll",
|
||||
"avoid": "do not run this without an appeasement route open"
|
||||
"avoid": "do not run this without an appeasement route open",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1170,4 +1172,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,8 +362,9 @@
|
||||
"note": "fearless"
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the Skeletons — say so before initiative",
|
||||
"avoid": "it wants the count right; give it a name off the register and it stops to check"
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the Skeletons",
|
||||
"avoid": "it wants the count right; give it a name off the register and it stops to check",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
},
|
||||
"nightmare": {
|
||||
"line": "1 Wraith, 1 Ogre off the common and 5 Skeletons",
|
||||
@@ -397,7 +398,8 @@
|
||||
}
|
||||
],
|
||||
"harmedBy": "blessed, silvered or magical weapons for the Wraith ONLY; anything for the rest",
|
||||
"avoid": "do not run this without an appeasement route open"
|
||||
"avoid": "do not run this without an appeasement route open",
|
||||
"beforeInitiative": "Say so before initiative."
|
||||
}
|
||||
},
|
||||
"motifs": {
|
||||
@@ -1186,4 +1188,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,9 +104,8 @@ export function renderMarkdown(d) {
|
||||
L.push('');
|
||||
|
||||
if (R) {
|
||||
// No appended "say so before initiative" — the packs that need it already say it, and three
|
||||
// battle rosters carry the phrase verbatim, so the addendum printed it twice.
|
||||
L.push(`**${cap(a.encounter.heat)} — ${R.line}.** Harmed by ${R.harmedBy}. *${R.avoid}.*`);
|
||||
L.push(`**${cap(a.encounter.heat)} — ${R.line}.** Harmed by ${R.harmedBy}.`
|
||||
+ `${R.beforeInitiative ? ` **${R.beforeInitiative}**` : ''} *${R.avoid}.*`);
|
||||
L.push('');
|
||||
L.push('| Foe | atk | def | Grit | Nerve | |');
|
||||
L.push('|---|---|---|---|---|---|');
|
||||
|
||||
Reference in New Issue
Block a user