feat: robustness in Module 5 (nesting guard, Death Phase limit, well-formed Assemble, multi-summon order)
A trigger is never queued while that same (minion, trigger) is resolving;
more than DEATH_PHASE_LIMIT = 64 Death Phases is an error ('Death Phase
limit'); Assemble refuses and never offers ill-formed text (wellFormed /
well_formed); summon count > 1 places tokens in summon order. Modules 05-10,
both tracks. Four new Module 5 tests, a tools test that every shipped card
is well-formed, lessons 2, 3, 5, 13 and harness.md updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
372c99c306
commit
21fb40c6f5
81 files changed
+1880
-528
No files matched your search
@@ -143,6 +143,28 @@ export function compile(def: CardDef, inPool: boolean): Card {
|
||||
|
||||
export const hasTrigger = (card: Card, on: TriggerOn): boolean => card.triggers.some((t) => t.on === on);
|
||||
|
||||
/**
|
||||
* Does `text` mean what it says? For a minion, every effect clause belongs to a
|
||||
* trigger (none comes before the first trigger, or after an aura or keyword), and
|
||||
* every trigger has at least one effect before the next trigger, aura, keyword or
|
||||
* the end. The rule is for minions (Assemble makes only minions): a spell passes.
|
||||
*/
|
||||
export function wellFormed(text: readonly Clause[], type: CardDef["type"]): boolean {
|
||||
if (type !== "minion") return true;
|
||||
// The trigger whose effects are being listed: none, one with no effect yet, or one with some.
|
||||
let open: "none" | "empty" | "filled" = "none";
|
||||
for (const clause of text) {
|
||||
if (clause.kind === "effect") {
|
||||
if (open === "none") return false;
|
||||
open = "filled";
|
||||
} else {
|
||||
if (open === "empty") return false;
|
||||
open = clause.kind === "trigger" ? "empty" : "none";
|
||||
}
|
||||
}
|
||||
return open !== "empty";
|
||||
}
|
||||
|
||||
/** Every card the game can create, looked up by name. */
|
||||
export class CardLibrary {
|
||||
private readonly cards = new Map<string, Card>();
|
||||
|
||||
Reference in new issue
Block a user