From 14b51fe9f4544f4b1b77c318420f2bb915248aae Mon Sep 17 00:00:00 2001 From: matthewevans Date: Thu, 13 Aug 2026 00:37:43 -0700 Subject: [PATCH 1/6] test(engine): cover Overencumbered token ownership Drive Overencumbered through the cast, player-Aura attachment, and ETB trigger pipeline. Assert each token in its shared Clue/Food/Junk sequence is created under the enchanted opponent rather than the Aura controller. --- .../issue_5271_overencumbered_tokens.rs | 48 +++++++++++++++++++ crates/engine/tests/integration/main.rs | 1 + 2 files changed, 49 insertions(+) create mode 100644 crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs diff --git a/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs b/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs new file mode 100644 index 0000000000..08023e99f9 --- /dev/null +++ b/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs @@ -0,0 +1,48 @@ +use engine::game::scenario::{GameScenario, P0, P1}; +use engine::types::mana::ManaCost; +use engine::types::phase::Phase; + +const OVERENCUMBERED_ORACLE: &str = "Enchant opponent\n\ +When this Aura enters, enchanted opponent creates a Clue token, a Food token, and a Junk token.\n\ +At the beginning of combat on enchanted opponent's turn, that player may pay {1} for each artifact they control. If they don't, creatures can't attack this combat."; + +/// CR 111.2 + CR 303.4b + CR 608.2c: a player Aura's ETB resolves its +/// shared-verb token list for the enchanted opponent, not the Aura's controller. +#[test] +fn issue_5271_overencumbered_etb_gives_every_token_to_enchanted_opponent() { + let mut scenario = GameScenario::new(); + scenario.at_phase(Phase::PreCombatMain); + let aura = { + let mut builder = scenario.add_spell_to_hand_from_oracle( + P0, + "Overencumbered", + false, + OVERENCUMBERED_ORACLE, + ); + builder + .as_enchantment() + .with_subtypes(vec!["Aura", "Curse"]) + .with_mana_cost(ManaCost::zero()); + builder.id() + }; + + let mut runner = scenario.build(); + runner.cast(aura).target_player(P1).resolve(); + + for token_name in ["Clue", "Food", "Junk"] { + let token = runner + .state() + .objects + .values() + .find(|object| object.name == token_name && object.is_token) + .unwrap_or_else(|| panic!("Overencumbered must create a {token_name} token")); + assert_eq!( + token.owner, P1, + "{token_name} must be owned by the enchanted opponent" + ); + assert_eq!( + token.controller, P1, + "{token_name} must be controlled by the enchanted opponent" + ); + } +} diff --git a/crates/engine/tests/integration/main.rs b/crates/engine/tests/integration/main.rs index 08895c900c..db44946329 100644 --- a/crates/engine/tests/integration/main.rs +++ b/crates/engine/tests/integration/main.rs @@ -599,6 +599,7 @@ mod issue_5247_kinetic_ooze_conditional_multi_target; mod issue_5252_additional_sacrifice_after_mana_abilities; mod issue_5254_declaration_in_stone_clue_owner; mod issue_5268_invincible_iron_man; +mod issue_5271_overencumbered_tokens; mod issue_5274_call_the_spirit_dragons; mod issue_5279_grave_sifter; mod issue_5282_nissa_ultimate_emblem_search; From b89ffc6a7e602d8dace0b10d1206d48737ae09b4 Mon Sep 17 00:00:00 2001 From: matthewevans Date: Thu, 13 Aug 2026 00:40:18 -0700 Subject: [PATCH 2/6] fix(parser): cite Aura host rules correctly --- crates/engine/src/parser/oracle_effect/subject.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/engine/src/parser/oracle_effect/subject.rs b/crates/engine/src/parser/oracle_effect/subject.rs index afaea1a751..57cf3a51b6 100644 --- a/crates/engine/src/parser/oracle_effect/subject.rs +++ b/crates/engine/src/parser/oracle_effect/subject.rs @@ -2533,7 +2533,7 @@ pub(super) fn parse_subject_application( is_optional: false, }); } - // CR 303.4b + CR 702.5a + CR 701.17a (issues #5947, #5271): "enchanted + // CR 303.4b + CR 303.4m + CR 702.5a (issues #5947, #5271): "enchanted // player" / "enchanted opponent" name the Aura's attached player host — // `AttachedTo`, not a Typed EnchantedBy filter (which is object-only). // The opponent qualifier constrains attachment when the Aura enters; its From fcdd2548b41cb4499eaf476e891b8647f4907c42 Mon Sep 17 00:00:00 2001 From: matthewevans Date: Thu, 13 Aug 2026 01:01:31 -0700 Subject: [PATCH 3/6] test(engine): resolve Overencumbered ETB trigger --- .../engine/tests/integration/issue_5271_overencumbered_tokens.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs b/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs index 08023e99f9..d06b69119b 100644 --- a/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs +++ b/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs @@ -28,6 +28,7 @@ fn issue_5271_overencumbered_etb_gives_every_token_to_enchanted_opponent() { let mut runner = scenario.build(); runner.cast(aura).target_player(P1).resolve(); + runner.advance_until_stack_empty(); for token_name in ["Clue", "Food", "Junk"] { let token = runner From 16fde51941ac65e5c78b9bf7b4d424b1f8123850 Mon Sep 17 00:00:00 2001 From: matthewevans Date: Thu, 13 Aug 2026 01:32:02 -0700 Subject: [PATCH 4/6] test(engine): model Overencumbered as an Aura --- .../integration/issue_5271_overencumbered_tokens.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs b/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs index d06b69119b..73bceab9bc 100644 --- a/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs +++ b/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs @@ -13,16 +13,12 @@ fn issue_5271_overencumbered_etb_gives_every_token_to_enchanted_opponent() { let mut scenario = GameScenario::new(); scenario.at_phase(Phase::PreCombatMain); let aura = { - let mut builder = scenario.add_spell_to_hand_from_oracle( - P0, - "Overencumbered", - false, - OVERENCUMBERED_ORACLE, - ); + let mut builder = scenario.add_creature_to_hand(P0, "Overencumbered", 0, 0); builder .as_enchantment() .with_subtypes(vec!["Aura", "Curse"]) - .with_mana_cost(ManaCost::zero()); + .with_mana_cost(ManaCost::zero()) + .from_oracle_text(OVERENCUMBERED_ORACLE); builder.id() }; From 60fa689b2141dbd031d235afcf8f3b883c811b54 Mon Sep 17 00:00:00 2001 From: matthewevans Date: Thu, 13 Aug 2026 02:00:14 -0700 Subject: [PATCH 5/6] test(engine): assert Aura host before ETB --- .../tests/integration/issue_5271_overencumbered_tokens.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs b/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs index 73bceab9bc..42d3f3c21b 100644 --- a/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs +++ b/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs @@ -1,3 +1,4 @@ +use engine::game::game_object::AttachTarget; use engine::game::scenario::{GameScenario, P0, P1}; use engine::types::mana::ManaCost; use engine::types::phase::Phase; @@ -24,6 +25,11 @@ fn issue_5271_overencumbered_etb_gives_every_token_to_enchanted_opponent() { let mut runner = scenario.build(); runner.cast(aura).target_player(P1).resolve(); + assert_eq!( + runner.state().objects.get(&aura).unwrap().attached_to, + Some(AttachTarget::Player(P1)), + "the resolving Aura must attach to its chosen opponent before its ETB resolves" + ); runner.advance_until_stack_empty(); for token_name in ["Clue", "Food", "Junk"] { From 5e5af85d861d46b7d73e0c231794e9abbdf12054 Mon Sep 17 00:00:00 2001 From: matthewevans Date: Thu, 13 Aug 2026 02:17:31 -0700 Subject: [PATCH 6/6] test(engine): model Overencumbered enchant keyword --- .../tests/integration/issue_5271_overencumbered_tokens.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs b/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs index 42d3f3c21b..b3e69cee66 100644 --- a/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs +++ b/crates/engine/tests/integration/issue_5271_overencumbered_tokens.rs @@ -19,7 +19,7 @@ fn issue_5271_overencumbered_etb_gives_every_token_to_enchanted_opponent() { .as_enchantment() .with_subtypes(vec!["Aura", "Curse"]) .with_mana_cost(ManaCost::zero()) - .from_oracle_text(OVERENCUMBERED_ORACLE); + .from_oracle_text_with_keywords(&["Enchant opponent"], OVERENCUMBERED_ORACLE); builder.id() };