Skip to content

fix: gate attacks-alone triggers on zero co-attackers (closes #5159)#5162

Merged
matthewevans merged 5 commits into
phase-rs:mainfrom
RealDiligent:fix/issue-5159-attacks-alone-trigger-gate
Jul 7, 2026
Merged

fix: gate attacks-alone triggers on zero co-attackers (closes #5159)#5162
matthewevans merged 5 commits into
phase-rs:mainfrom
RealDiligent:fix/issue-5159-attacks-alone-trigger-gate

Conversation

@RealDiligent

Copy link
Copy Markdown
Contributor

Summary

  • Parse "attacks alone" on attack triggers into TriggerCondition::MinCoAttackers { minimum: 0 } (CR 508.3a — zero co-attackers).
  • Wire the same condition through mtgish-import WhenACreatureAttacksAlone.
  • Add integration tests for Agent 13, Sharon Carter: solo attack investigates once; multi-creature attack does not.

Closes #5159.

Test plan

  • trigger_samurai_or_warrior_attacks_alone parser unit test
  • issue_5159_solo_attack_investigates_once
  • issue_5159_multi_attack_does_not_investigate
  • CI green

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements support for the "attacks alone" trigger qualifier by encoding it as a zero-co-attacker gate (TriggerCondition::MinCoAttackers { minimum: 0 }) in both the native parser and the mtgish-import converter, accompanied by integration tests. The review feedback identifies violations of R1 due to using standard string methods (strip_prefix) instead of nom combinators in the parser, as well as violations of R6 regarding missing or incorrect CR citations (citing CR 508.3a instead of CR 506.5).

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/engine/src/parser/oracle_trigger.rs Outdated
Comment on lines +8365 to +8370
if attacks_alone {
def.condition = Some(TriggerCondition::MinCoAttackers {
minimum: 0,
filter: None,
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

[MEDIUM] Missing mandatory CR annotation on rules-touching code. Evidence: crates/engine/src/parser/oracle_trigger.rs:8365.
Why it matters: R6 requires every rules-touching line of engine code to carry a comment of the form CR <number>: <description> to ensure compliance and traceability. Suggested fix: Add a comment citing CR 506.5 above the condition block.

Suggested change
if attacks_alone {
def.condition = Some(TriggerCondition::MinCoAttackers {
minimum: 0,
filter: None,
});
}
if attacks_alone {
// CR 506.5: A creature attacks alone if it's the only creature declared as an attacker.
def.condition = Some(TriggerCondition::MinCoAttackers {
minimum: 0,
filter: None,
});
}
References
  1. R6. CR annotations are mandatory and verified. Every rules-touching line of engine code must carry a comment of the form CR : . (link)

Comment thread crates/mtgish-import/src/convert/trigger.rs Outdated

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking this on, but the current encoding does not implement the attacks alone gate.

TriggerCondition::MinCoAttackers is an at-least condition: the runtime counts same-controller co-attackers and checks co_attacker_count >= minimum. Setting minimum: 0 therefore always passes, including when the source attacks with one or more other creatures. That means the new parser/converter shape still allows the Agent 13 trigger to fire during multi-creature attacks, which is the bug this PR is meant to fix.

Rules evidence: CR 506.5 defines a creature as attacking alone only when it is attacking and no other creatures are. Please model this as an exact/maximum zero co-attacker gate, or add an appropriate parameterized condition shape, and keep the multi-attacker regression covering that runtime behavior. Also note the PR is currently DIRTY against base and still needs the parse-diff evidence before it can be considered for approval.

@matthewevans matthewevans added the bug Bug fix label Jul 6, 2026
@RealDiligent RealDiligent force-pushed the fix/issue-5159-attacks-alone-trigger-gate branch from a09ccd4 to 77f564b Compare July 7, 2026 13:31
@RealDiligent

Copy link
Copy Markdown
Contributor Author

Addressed the review in 77f564b (rebased onto current main):

Encoding fix: attacks alone now uses Not(MinCoAttackers { minimum: 1 }), matching the Exalted synthesis path - zero same-controller co-attackers, not minimum: 0 which always passed.

Parser: switched strip_attack_alone_qualifier to a nom tag combinator (R1).

Rules cite: CR 506.5 (not 508.3a).

Integration test issue_5159_attacks_alone_investigate unchanged - it already asserts multi-attacker silence. CI running.

RealDiligent and others added 2 commits July 7, 2026 21:35
…rs#5159)

Parse "attacks alone" into MinCoAttackers { minimum: 0 } so Sharon Carter /
Exalted-class triggers fire only when a single creature attacks.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Parse changes introduced by this PR · 91 card(s), 13 signature(s) (baseline: main b62ec5558e3d)

58 card(s) · trigger/Attacks · field condition: not (with 1+ other attackers)

Examples: A-Akki Ronin, A-Ancestral Katana, A-Asari Captain (+55 more)

27 card(s) · trigger/Phase · field valid target: parent target's controller

Examples: Aggression, Apathy, Dance of the Dead (+24 more)

1 card(s) · trigger/Attacks · field condition: first combat phase of the turnnot (with 1+ other attackers) and first combat phase of the turn

Examples: Finest Hour

1 card(s) · ability/ChooseOneOf · added: ChooseOneOf (duration=until end of turn, kind=activated)

Examples: Jeweled Spirit

1 card(s) · ability/TargetOnly · added: TargetOnly (duration=until end of turn, kind=activated, target=another you control creature)

Examples: Giver of Runes

1 card(s) · ability/TargetOnly · added: TargetOnly (duration=until end of turn, target=you control artifact or you control creature)

Examples: Apostle's Blessing

1 card(s) · ability/TargetOnly · added: TargetOnly (duration=until end of turn, target=you control creature or you control planeswalker)

Examples: Angelic Intervention

1 card(s) · ability/TargetOnly · added: TargetOnly (duration=until end of turn, target=you control permanent)

Examples: Razor Barrier

1 card(s) · ability/grant Protection · removed: grant Protection (affects=parent target, duration=until end of turn, grants=grant Protection, kind=activated, target=another you control creature)

Examples: Giver of Runes

1 card(s) · ability/grant Protection · removed: grant Protection (affects=parent target, duration=until end of turn, grants=grant Protection, target=you control artifact or you control creature)

Examples: Apostle's Blessing

1 card(s) · ability/grant Protection · removed: grant Protection (affects=parent target, duration=until end of turn, grants=grant Protection, target=you control creature or you control planeswalker)

Examples: Angelic Intervention

1 card(s) · ability/grant Protection · removed: grant Protection (affects=parent target, duration=until end of turn, grants=grant Protection, target=you control permanent)

Examples: Razor Barrier

1 card(s) · ability/grant Protection · removed: grant Protection (affects=self, duration=until end of turn, grants=grant Protection, kind=activated)

Examples: Jeweled Spirit

@RealDiligent

Copy link
Copy Markdown
Contributor Author

Follow-up on your review (e10188a, rebased onto current main):

  • Encoding: �ttacks alone now uses Not(MinCoAttackers { minimum: 1 }) (same as Exalted synthesis) — zero co-attackers, not minimum: 0.
  • CI fixes: integration test imports corrected (super::rules::{GameScenario, P0}); nom tag return type fixed.
  • Parse-diff: bot posted 59-card signature showing condition: ∅ → not (with 1+ other attackers) on Attacks triggers.
  • R6: CR 506.5 annotation added on the condition block.

Integration tests cover solo vs multi-attacker investigate. CI re-running.

@matthewevans matthewevans self-assigned this Jul 7, 2026

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer sign-off: attacks-alone now uses the existing Not(MinCoAttackers { minimum: 1 }) building block, has discriminating combat tests, and the parse diff is limited to the attacks-alone class.

@matthewevans matthewevans enabled auto-merge July 7, 2026 20:03
@matthewevans matthewevans removed their assignment Jul 7, 2026
auto-merge was automatically disabled July 7, 2026 20:47

Head branch was pushed to by a user without write access

@matthewevans matthewevans self-assigned this Jul 7, 2026

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer sign-off refreshed for current head: attacks-alone uses the existing Not(MinCoAttackers { minimum: 1 }) condition, parse diff is limited to the attacks-alone trigger class, and solo/multi-attacker runtime tests discriminate the fix.

@matthewevans matthewevans added this pull request to the merge queue Jul 7, 2026
@matthewevans matthewevans removed their assignment Jul 7, 2026
Merged via the queue into phase-rs:main with commit f00ec65 Jul 7, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Card Bug] Agent 13, Sharon Carter triggering when attacking with multiple creatures

2 participants