magefree / mage

Magic Another Game Engine
http://xmage.today
MIT License
1.9k stars 773 forks source link

Non-stack delayed triggers must be reworked? #12111

Open JayDi85 opened 7 months ago

JayDi85 commented 7 months ago

It's not a critical problem, can be related to some rare bugs with commander moves, counters conditional and other state base things. See example: #4025

Affected cards

[[Banisher Priest]], [[Grasp of Fate]] and other with rules like "exile ... until {this} leaves the battlefield". Search problem cards by usesStack = false or new OnLeaveReturnExiledAbility. shot_240411_222040

Problem

Current code do not support full rules like "nothing happens between the two events, including state-based actions" (see related test in StateBaseTriggeredAbilityTest::test_GraspOfFate_DelayedTriggerMustResolveImmediately).

Non-stack delayed triggers are xmage's workaround to support specific cards instead replacement effects usage. I don't find any MTG rules about non-stack triggers. That effects must be resolved immediately like mana abilities does -- but it uses triggers lifecycle instead (all triggered collects in shared list and executes one by one on new game cycle).

Related rules:

Banisher Priest's ability causes a zone change with a duration, a new style of ability that's somewhat reminiscent of older cards like Oblivion Ring. However, unlike Oblivion Ring, cards like Banisher Priest have a single ability that creates two one-shot effects: one that exiles the creature when the ability resolves, and another that returns the exiled card to the battlefield immediately after Banisher Priest leaves the battlefield. (2013-07-01)

The exiled card returns to the battlefield immediately after Banisher Priest leaves the battlefield. Nothing happens between the two events, including state-based actions. The two creatures aren't on the battlefield at the same time. For example, if the returning creature is a Clone, it can't enter the battlefield as a copy of Banisher Priest. (2013-07-01)

In a multiplayer game, if Grasp of Fate's owner leaves the game, the exiled cards will return to the battlefield. Because the one-shot effect that returns the cards isn't an ability that goes on the stack, it won't cease to exist along with the leaving player's spells and abilities on the stack. (2015-11-04)

Possible solutions

I'm tried to fix it by immediately resolve like mana abilities does but it not work due new game cycle usage (ApplyEffects) on active/resolve. See details docs by code search state.addTriggeredAbility or related commit 367defd9958ac88b28206c6841771a71ee9b3ef5.

So only cards rework can help here. All related cards must migrate to existing replacement effects due card rules (example replacement effect on zone move). Make sure it support resolve on controller leave (delayed triggers does). The last one very important feature of delayed triggers: #4025.

github-actions[bot] commented 7 months ago

Banisher Priest - (Gatherer) (Scryfall) (EDHREC)

{1}{W}{W} Creature — Human Cleric 2/2 When Banisher Priest enters the battlefield, exile target creature an opponent controls until Banisher Priest leaves the battlefield. (That creature returns under its owner's control.)

Grasp of Fate - (Gatherer) (Scryfall) (EDHREC)

{1}{W}{W} Enchantment When Grasp of Fate enters the battlefield, for each opponent, exile up to one target nonland permanent that player controls until Grasp of Fate leaves the battlefield. (Those permanents return under their owners' control.)

JayDi85 commented 5 months ago

Another problem: different duration in delayed triggers (see related PR in #12253):

Delayed triggers can be used with different duration:

Old contract:

New contract after #12253:

What can be checked:

github-actions[bot] commented 5 months ago

Aggravated Assault - (Gatherer) (Scryfall) (EDHREC)

{2}{R} Enchantment {3}{R}{R}: Untap all creatures you control. After this main phase, there is an additional combat phase followed by an additional main phase. Activate only as a sorcery.

Magus of the Unseen - (Gatherer) (Scryfall) (EDHREC)

{1}{U} Creature — Human Wizard 1/1 {1}{U}, {T}: Untap target artifact an opponent controls and gain control of it until end of turn. It gains haste until end of turn. When you lose control of the artifact, tap it.

Waylay - (Gatherer) (Scryfall) (EDHREC)

{2}{W} Instant Create three 2/2 white Knight creature tokens. Exile them at the beginning of the next cleanup step.