Skip to content

Let a member avert their eyes or fight by a mirror against a gaze - #196

Merged
mmacy merged 3 commits into
mainfrom
chunk/avert-eyes
Oct 30, 2026
Merged

mmacy merged 3 commits into
mainfrom
chunk/avert-eyes

Conversation

@mmacy

@mmacy mmacy commented Oct 30, 2026

Copy link
Copy Markdown
Owner

A basilisk's or medusa's gaze petrified every member in melee each round, and no command let a member defend. #180 added the gazes and noted the gap. This adds the SRD's two defenses and the basilisk's surprise gaze.

What changed

  • BattleDeclaration has a new field, gaze_defense, set to "avert_eyes" or "mirror" with any action. It lasts the round, whichever side acts first.
    • Averting eyes: the gaze passes the member by. Every attack roll they make that round takes −4, and a basilisk or medusa gains +2 against them ("Averting eyes: -4 penalty to-hit; the basilisk gains a +2 bonus to attack").
    • Mirror: the gaze passes them by, and their attack rolls take −1 ("Fighting by looking in a mirror incurs a -1 penalty to attack"). The member must carry a mirror, or the round is refused with battle.declaration.no_mirror.
  • A basilisk that surprises the party gazes at every member in its free round, back rank included ("Characters surprised by a basilisk meet its gaze"). That gaze replaces the front-rank gaze for the round. The medusa's entry has no such rule, so her free round is unchanged.
  • The basilisk's surprise ability and both gazers' averting_eyes abilities are no longer manual. A gazer seeing its reflection in a mirror is still left to the referee, and the register says so.

What to check

  • The −4 applies to every attack the averting member makes, not only attacks on the gazer, because the SRD's sentence names no target. The +2 goes only to the gazer.
  • tests/goldens/phase5_milestone.json changes only by "gaze_defense": null on each logged declaration. No outcome changed.
  • One line in docs/spec.md changes, because it said mirror counterplay stays manual.

https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD

mmacy added 3 commits October 30, 2026 14:45
Add BattleDeclaration.gaze_defense, a per-round stance of avert_eyes or
mirror that goes with any action. The field is a stub with no behavior.
The docstrings, the adaptations register, and the spec line on mirrors
describe the contract from the basilisk and medusa entries: averting
spares the gaze at -4 to every attack roll and +2 to a gazer's attacks
on the averter, a carried mirror spares it at -1, and a basilisk that
surprises the party gazes at every member in its free round.

tests/test_avert_eyes.py holds the acceptance tests, marked
xfail(reason="chunk: avert-eyes", strict=True), and unmarked guards.

The phase 5 milestone golden is regenerated with
tests/generate_phase5_goldens.py. Its command log now serializes the
new field as "gaze_defense": null on each logged declaration. No event,
draw, or other value in it changed.

Claude-Session: https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD
A BattleDeclaration's gaze_defense now takes effect. With avert_eyes,
the session gives the member the averted_eyes condition from the moment
the round is accepted until it ends, so resolve_gaze passes them by,
and every attack roll they make that round takes -4. A monster whose
averting_eyes ability isn't manual, the basilisk or the medusa, gains +2
on its attacks against a member with the condition. With mirror, the
member is left out of the front rank the gaze reaches, and every attack
roll they make that round takes -1. A member who carries no mirror is
refused with the new code battle.declaration.no_mirror. Neither stance
draws or emits an event.

In the monsters' free round after they surprise the party, a monster
whose surprise ability has meets_gaze, the basilisk, gazes once at
every living member at any distance, in place of the front-rank gaze.

The compiler pins the basilisk's surprise ability and both monsters'
averting_eyes abilities as not manual, and the regenerated
monsters.json carries that. The mirrors abilities stay manual, because
a gazer that sees its own reflection is left to the referee.

No golden file changed.

Claude-Session: https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD
@mmacy
mmacy merged commit b4caae6 into main Oct 30, 2026
5 checks passed
@mmacy
mmacy deleted the chunk/avert-eyes branch October 30, 2026 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant