fix(engine): scope hexproof-bypass statics to their beneficiary (Glaring Spotlight)#5389
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the static hexproof bypass parser to optionally consume the 'you control' qualifier and adds a corresponding test. The review feedback highlights that the comments and tests cite the incorrect Comprehensive Rules section (CR 702.11b instead of CR 702.11e / CR 609.4) and identifies a multiplayer rules fidelity gap because the engine currently discards this qualifier rather than parameterizing the static mode.
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.
| // CR 702.11b: an optional "you control" qualifier scopes WHICH spells and | ||
| // abilities bypass hexproof (Glaring Spotlight, Detection Tower, Kaya, | ||
| // Bane of the Dead). The bypass is a targeting permission on the affected | ||
| // permanents regardless of whose spell/ability targets them, so the | ||
| // qualifier doesn't change the emitted `IgnoreHexproof` — it just has to | ||
| // be consumed. Nowhere to Run omits it (bare "of spells and abilities"). |
There was a problem hiding this comment.
[HIGH] Incorrect CR citation and unhandled multiplayer rules difference. Evidence: crates/engine/src/parser/oracle_static/shared.rs:35-40.
Why it matters:
- CR Citation (R6): CR 702.11b only defines the basic hexproof keyword on a permanent. The rules governing "as though" targeting permissions and hexproof bypasses are CR 702.11e and CR 609.4.
- CR Fidelity (Pillar 2): Glaring Spotlight restricts the bypass to spells and abilities you control, whereas Nowhere to Run allows any player's spells and abilities to target the affected creatures in multiplayer. Discarding the qualifier and emitting the same unqualified
IgnoreHexproofstatic mode creates a functional rules discrepancy in multiplayer games.
Suggested fix: Update the comment to cite CR 702.11e / CR 609.4 and document this engine gap. Ideally, StaticMode::IgnoreHexproof should be parameterized with Option<ControllerRef> (per R2/R3) in a follow-up engine PR to fully resolve the multiplayer rules difference.
| // CR 702.11b: an optional "you control" qualifier scopes WHICH spells and | |
| // abilities bypass hexproof (Glaring Spotlight, Detection Tower, Kaya, | |
| // Bane of the Dead). The bypass is a targeting permission on the affected | |
| // permanents regardless of whose spell/ability targets them, so the | |
| // qualifier doesn't change the emitted `IgnoreHexproof` — it just has to | |
| // be consumed. Nowhere to Run omits it (bare "of spells and abilities"). | |
| // CR 702.11e / CR 609.4: an optional "you control" qualifier scopes WHICH spells and | |
| // abilities bypass hexproof (Glaring Spotlight, Detection Tower, Kaya, | |
| // Bane of the Dead). Note: Currently, the engine's IgnoreHexproof static mode | |
| // does not distinguish this scope from unqualified bypasses (like Nowhere to Run), | |
| // which is a multiplayer rules fidelity gap to be addressed in the engine. |
References
- Strict fidelity to the MTG Comprehensive Rules (CR) — every game rule, validation, and computed value matches the CR exactly. Convenience shortcuts that get rules wrong are not simpler; they are wrong. (link)
- CR annotations are mandatory and verified. Every rules-touching line of engine code must carry a comment of the form CR : . (link)
| /// CR 702.11b: Glaring Spotlight — "Creatures your opponents control with | ||
| /// hexproof can be the targets of spells and abilities YOU CONTROL as though | ||
| /// they didn't have hexproof." The optional "you control" qualifier between | ||
| /// "spells and abilities" and "as though" must be consumed; the bypass is a | ||
| /// targeting permission on the affected permanents, so it emits the same single | ||
| /// `IgnoreHexproof` as the unqualified Nowhere to Run form, scoped to opponents' | ||
| /// creatures. |
There was a problem hiding this comment.
[MEDIUM] Incorrect CR citation in test documentation. Evidence: crates/engine/src/parser/oracle_static/tests.rs:524.
Why it matters: CR 702.11b only defines the basic hexproof keyword on a permanent. The rules governing "as though" targeting permissions and hexproof bypasses are CR 702.11e and CR 609.4.
Suggested fix: Update the test documentation to cite CR 702.11e and CR 609.4.
| /// CR 702.11b: Glaring Spotlight — "Creatures your opponents control with | |
| /// hexproof can be the targets of spells and abilities YOU CONTROL as though | |
| /// they didn't have hexproof." The optional "you control" qualifier between | |
| /// "spells and abilities" and "as though" must be consumed; the bypass is a | |
| /// targeting permission on the affected permanents, so it emits the same single | |
| /// `IgnoreHexproof` as the unqualified Nowhere to Run form, scoped to opponents' | |
| /// creatures. | |
| /// CR 702.11e / CR 609.4: Glaring Spotlight — "Creatures your opponents control with | |
| /// hexproof can be the targets of spells and abilities YOU CONTROL as though | |
| /// they didn't have hexproof." The optional "you control" qualifier between | |
| /// "spells and abilities" and "as though" must be consumed; the bypass is a | |
| /// targeting permission on the affected permanents, so it emits the same single | |
| /// IgnoreHexproof as the unqualified Nowhere to Run form, scoped to opponents' | |
| /// creatures. |
References
- CR annotations are mandatory and verified. Every rules-touching line of engine code must carry a comment of the form CR : . (link)
matthewevans
left a comment
There was a problem hiding this comment.
[MED] you control is consumed but not represented, so Glaring Spotlight gets a broader hexproof bypass than printed. Evidence: crates/engine/src/parser/oracle_static/shared.rs:35 says the qualifier does not change the emitted IgnoreHexproof, and crates/engine/src/parser/oracle_static/tests.rs:524 only asserts the parser emits the unqualified mode. The existing runtime contract for object-scoped IgnoreHexproof is source-controller-independent (see targeting.rs's Nowhere to Run multiplayer coverage), which is correct for unqualified “spells and abilities” but wrong for “spells and abilities you control.” Why it matters: this would make opponents’ and third players’ spells/abilities able to target the affected hexproof creatures, falsely marking Glaring Spotlight supported with stronger behavior than Oracle grants. Suggested fix: model the source-controller axis on the bypass authority, or leave the you control form unsupported until the runtime can enforce it.
Parse changes introduced by this PRBaseline pending for |
phase-rs#5386) Glaring Spotlight's "Creatures your opponents control with hexproof can be the targets of spells and abilities you control as though they didn't have hexproof" dropped to Unimplemented. `parse_ignore_hexproof_static` matched the bypass phrase verbatim as "of spells and abilities as though", so the optional "you control" qualifier some cards insert (Glaring Spotlight) failed the match and the `IgnoreHexproof` static was never emitted. Split the phrase and consume an optional " you control" between "spells and abilities" and "as though". The qualifier scopes which spells/abilities bypass hexproof but the bypass is a targeting permission on the affected permanents, so the emitted `IgnoreHexproof` is unchanged — Nowhere to Run (no qualifier) still parses identically. Glaring Spotlight now emits `IgnoreHexproof` scoped to opponents' hexproof creatures. Closes phase-rs#5386. Test: the "you control" form emits a single `IgnoreHexproof` scoped to opponents' creatures; existing Nowhere to Run tests unchanged.
…e-rs#5386) Address review on phase-rs#5386: the "you control" qualifier on a hexproof-bypass static is semantically load-bearing in multiplayer. Glaring Spotlight — "Creatures your opponents control with hexproof can be the targets of spells and abilities YOU CONTROL as though they didn't have hexproof" — restricts the bypass to the static controller's spells and abilities, whereas Nowhere to Run's unqualified form opens the affected creatures to every player. The prior commit consumed and discarded the qualifier, emitting an identical unrestricted IgnoreHexproof for both — wrong in multiplayer. Parameterize the bypass beneficiary via a new StaticDefinition `bypass_beneficiary: Option<ControllerRef>` field (mirrors the existing mode-specific `attack_defended` / `source_controller` optional fields): - None = every player's spells and abilities (Nowhere to Run) - Some(You) = the static controller's only (Glaring Spotlight) `target_ignores_hexproof` now takes the targeting source's controller and honors the beneficiary before granting the bypass. Also corrects the CR citations to CR 702.11e / CR 609.4 (the "as though ... no hexproof" targeting-permission rules) instead of CR 702.11b (which only defines hexproof itself). CR 702.11e / CR 609.4 / CR 109.5.
8b49313 to
f4f4901
Compare
|
Thanks — both points addressed in the latest push. CR citation (MEDIUM): corrected to CR 702.11e / CR 609.4 (the "as though ... no hexproof" targeting-permission rules) in the code, tests, and doc comments; CR 702.11b remains only where it's cited as the definition of hexproof itself. Multiplayer fidelity (HIGH): the
|
matthewevans
left a comment
There was a problem hiding this comment.
Maintainer review: current head represents the Glaring Spotlight beneficiary qualifier and covers the multiplayer targeting split; auto-merge will wait for pending checks.
Closes #5386.
What
Glaring Spotlight — "Creatures your opponents control with hexproof can be the targets of spells and abilities you control as though they didn't have hexproof." — restricts the hexproof bypass to the static controller's spells and abilities. Nowhere to Run's unqualified form ("...can be the targets of spells and abilities as though they didn't have hexproof") opens the affected creatures to every player.
The parser previously consumed the
you controlqualifier and discarded it, emitting an identical unrestrictedIgnoreHexprooffor both cards. That is correct in 1v1 but wrong in multiplayer: a third player would wrongly be able to target the affected creatures through Glaring Spotlight.How (building block, not a special case)
Parameterize the bypass beneficiary on
StaticDefinition— mirroring the existing mode-specific optional fieldsattack_defended(CantAttack) andsource_controller(lure statics):oracle_static/shared.rs):opt(tag(" you control"))now drivesbypass_beneficiary = you_control.then_some(ControllerRef::You)instead of being discarded.static_abilities::target_ignores_hexproof): now takes the targeting source's controller and gates the grant throughignore_hexproof_beneficiary_allows—None⇒ any player;Some(You)⇒ only the static controller (CR 109.5); other refs fail closed.CR
Corrects the citations flagged in review: the "as though it didn't have hexproof" targeting permission is CR 702.11e / CR 609.4, not CR 702.11b (which only defines hexproof itself). Beneficiary resolution is CR 109.5.
Tests
you control⇒Some(You); unqualified ⇒None.targeting.rs): controller can target the affected creature; a third player cannot (revert-probe) — alongside the existing Nowhere to Run "any player" test.Verification
cargo fmt --all✓ · full engine lib suite 15,775 pass / 0 fail ✓ ·clippy -p engine -p phase-ai --all-targets -D warningsclean ✓