feat: Module 12, Combat (attack as one Sequence, Taunt, defender-first as a queue priority, end of turn; Bonechewer Brawler as the Expansion Drop)

Adds course/12-combat: lesson, scenarios, nine test_12 tests in both tracks,
the cumulative reference (Module 11's plus combat) and the drop. The Damage
action carries per-target hits with a priority; react stable-sorts its Queue by
priority before order of play, so the triggers answering the defender's Damage
Event go first. orderAttack/canAttack/endTurn join the harness (orderAttack
because attack(id) already reads Attack). endOfTurn triggers fire, so Drakkari
Enchanter's data is live. Test Bell is scoped to Module 12's cards. Harness
contract, catalog, research notes and earlier lessons' forward pointers follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-11-11 13:34:20 +01:00
1 parent c8fff05ccb
commit fb9d0a4eb4
89 files changed
+11852 -6

No files matched your search

+2 -2
View File
@@ -216,7 +216,7 @@ With this queue order, Whirlwind on Armorsmith and Acolyte gives Armorsmith (its
When your tests pass, compare with the reference engine in `course/02-action-queue/reference/rust/src/engine/` or `course/02-action-queue/reference/ts/src/engine/`. The resolver is `queue.rs` / `queue.ts`; the content library is a list of card definitions, one short effect each.
> **How the real game differs**
> The course queues every trigger strictly in order of play. The real game has exceptions: Redemption "always Queues last", Poisonous "resolves in a queue with higher priority", and when a minion takes combat damage "the defender ALWAYS triggers first, regardless of order of play". Some area spells (the rulebook lists Lightning Storm, Elemental Destruction, Dark Iron Skulker and Lightbomb) resolve each Damage Event as soon as it is created instead of creating them all first ([Advanced rulebook](https://hearthstone.wiki.gg/wiki/Advanced_rulebook)). None of these are modelled in this course. Within the course itself: Fatigue is only an event and does nothing else; Armor is only a number, and nothing in this module damages a hero that has Armor (Module 4 makes Armor absorb damage: [A second interceptor: replacement](../04-interceptors/lesson.md#a-second-interceptor-replacement)); the game has no death step until Module 3.
> The course queues every trigger strictly in order of play. The real game has exceptions: Redemption "always Queues last", Poisonous "resolves in a queue with higher priority", and when a minion takes combat damage "the defender ALWAYS triggers first, regardless of order of play". Some area spells (the rulebook lists Lightning Storm, Elemental Destruction, Dark Iron Skulker and Lightbomb) resolve each Damage Event as soon as it is created instead of creating them all first ([Advanced rulebook](https://hearthstone.wiki.gg/wiki/Advanced_rulebook)). The combat rule arrives in [Module 12](../12-combat/lesson.md), as a priority on queue entries; the others are not modelled in this course. Within the course itself: Fatigue is only an event and does nothing else; Armor is only a number, and nothing in this module damages a hero that has Armor (Module 4 makes Armor absorb damage: [A second interceptor: replacement](../04-interceptors/lesson.md#a-second-interceptor-replacement)); the game has no death step until Module 3.
## Name it
@@ -404,7 +404,7 @@ This module doesn't build it: no Module 2 test damages a hero that has Armor. [M
## Further reading
- Jon Parham, [*Make a CCG – Action System*](https://theliquidfire.com/2017/09/11/make-a-ccg-action-system/) (The Liquid Fire, 2017). The most readable worked implementation of a Hearthstone-style reaction tree, in C#. Read `SortActions`: reactions are sorted by `priority` first and `orderOfPlay` only as the tie-breaker, which is where an engine would put Poisonous or Redemption. Also note the loop at the end, the "death reaper", which runs "to take care of any mortally wounded cards" after the root action. That is Module 3.
- Jon Parham, [*Make a CCG – Action System*](https://theliquidfire.com/2017/09/11/make-a-ccg-action-system/) (The Liquid Fire, 2017). The most readable worked implementation of a Hearthstone-style reaction tree, in C#. Read `SortActions`: reactions are sorted by `priority` first and `orderOfPlay` only as the tie-breaker, which is where an engine would put Poisonous or Redemption. [Module 12](../12-combat/lesson.md) puts the combat defender's triggers there. Also note the loop at the end, the "death reaper", which runs "to take care of any mortally wounded cards" after the root action. That is Module 3.
- Robert Nystrom, [*Event Queue*](https://gameprogrammingpatterns.com/event-queue.html) (*Game Programming Patterns*). The general pattern, and its warnings. Read the sections on feedback loops and on the world state having changed by the time an event is handled: "you have to be careful not to assume the current state of the world reflects how the world was". Your ids from Module 1 are part of the answer.
- Alchyr, [*Action Queue*](https://github.com/Alchyr/BasicMod/wiki/Action-Queue) (BasicMod wiki, Slay the Spire modding). A short practical page about a different game's queue, where the modder chooses where a new action goes: "In a card's use: add to bottom. In an action's update: add to top." Compare it with the depth-first rule: "add to top" is how Slay the Spire makes a reaction happen before the next sibling.
- [Advanced rulebook, hearthstone.wiki.gg](https://hearthstone.wiki.gg/wiki/Advanced_rulebook): Rule 2 (Queues), the depth-first section, and Rule DH1 on area damage.