Original Post — Direct link

#WotcStaff

As you’ve all hopefully now seen, the patch from yesterday fixed several prominent bugs with DFT cards. I thought I’d give a quick behind-the-scenes look at three of them:

Elvish Refueler

The bug: during your turn, if you hadn’t activated an exhausted ability, your opponent could activate their exhaust abilities as often as they had mana to do so

The cause: This was entirely my fault. When I started working on [[Elvish Refueler]], I did what one always does in a situation like that, which is to poke around and try to find a similar, already existing card. And, fortunately, there was one:

[[Birgi, God of Storytelling]]

The conditions are a bit different, but it’s basically doing the same thing… in specific situations, it is relaxing a “you can’t activate this because you’ve already activated it” restriction.

So I used that as a model, rearranged some things, and, presto, thought I had it all working.

But to see where I went wrong, let’s look a bit more closely at the precise text of Birgi’s ability, expanding one of the words slightly, with some brackets:

[Creatures you control] can activate [boast abilities] twice during each of your turns rather than once.

There are basically two important nouns here…. One noun is what objects actually have the relevant activated abilities (creatures you control) and one is what type of ability is being activated (boast abilities).

Compare that to (the relevant part of) Elvish Refueler:

[you] may activate [exhaust abilities] as though they haven’t been activated.

So, there are again two nouns. But there is no longer a noun that represents the object. Now there’s one that represents the player. And while writing the new code for Elvish Refueler, I got rid of the “what object it is” noun from Birgi, but failed to add the new “what player it is” noun from Refueler.

And of course what then made things worse was that it still passed all my tests (and all the tests from our QA team), because what we were busy testing was tricky cases like “does it work with Loot’s exhaust ability, which is the only exhaust ability that is a mana ability” and “does it properly apply the ‘as long as you haven’t activated an exhaust ability this turn’” and “does it only apply (to you) on your turn”, not whether or not it applies to your opponents on your turn.

Cursecloth Wrappings

The bug: if you targeted the same creature multiple times with [[Cursecloth Wrappings]], it would cease to be embalmable. (This often came up with spells with cost reductions, because a player would try to embalm for the reduced cost, would be (correctly) unable to do so, and then would try again on a later turn…. But the actual bug was not related to cost reductions.)

The cause: When Cursecloth Wrappings resolves, it creates a little object which represents the embalm ability, and attaches that object to the targeted card. During the cleanup step, that object gets removed from the targeted card (as it only gains embalm until end of turn), BUT, the object is not actually destroyed. It continues to exist. (Objects continuing to exist after they have been “destroyed” is useful for a number of different reasons in the rules engine, such as last-known-information, so it’s something we do all the time that is usually harmless).

Now, to make embalm work, we need three “CLIPS rules”:

(1) If a creature in the GY has an embalm ability, create an action that the player can take

(2) If the player takes that action, set the cost of the action (paying mana equal to the card’s mana value and exiling the card)

(3) When that ability resolves, create a token that’s a copy of the card (and set various characteristics)

The problem was that rule (2) was written slightly wrong, such that the no-longer-relevant embalm ability from a previous turn would also cause the rule to fire… meaning that the cost would get “set” twice. Meaning that the cost would end up being “twice the creature’s mana cost, plus exile the creature card, plus exile the creature card”. So you’d start to activate that ability, you’d exile the creature card, and then you’d be unable to exile the creature card a second time, as it was already exiled, and you’d be unable to embalm.

(Note that the “unapayble cost” error message has nothing to do with mana… we generally let you try to pay any mana cost, and if you can’t, it’s up to you to give up and click cancel. This message shows up in cases where we allowed you to take an action which required some sort of non-mana cost; sacrificing or exiling or discarding or whatever; because we saw before you started taking the action that the necessary objects existed and could be sacrificed/exiled/discarded. BUT, by the time you got to the point where it was time to actually sacrifice/exile/discard, you no longer had the necessary object. For instance, cast [[Fling]] with only one creature in play, then sacrifice that creature as part of a mana ability to pay the mana cost for Fling.)

Dune Drifter

The bug: if [[Dune Drifter]] entered the battlefield without being cast, its triggered ability could target any artifact or creature card in your graveyard, regardless of mana cost.

The cause: This comes down to the question of “if X is not defined, what is the value of X?”. And the answer, in magic rules, is 0. So we have a function in our codebase that says “get me the value of X”, and if it can’t, it returns 0. That’s how most things work most of the time. So if you flicker [[Gadwick the Wizened]], you draw zero cards.

BUT, there’s one entire context in which it makes a lot of sense to treat undefined X as “could be anything”, which is targeting. In particular, something we call “predictive targeting”.

On Arena, if you have [[Doom Blade]] in your hand, but there are no nonblack creatures on the battlefield, Doom Blade won’t be highlighted as castable. To make this whole feature work, we need to be constantly checking whether all your targeted spells or activated abilities have any legal targets. Which requires being able to check “would this object be a legal target for this (not actually cast) spell”.

But what if the card in your hand wasn’t Doom Blade, but [[Disembowel]]? What happens when we try to check “could this creature be a legal target for Disembowel”? Well, Disembowel hasn’t been cast. It certainly doesn’t have a defined X. So, by the rules of Magic, X must be zero. So, following that logic, we’d end up in a state where you could only cast Disembowel to begin with if there was an [[Ornithopter]] on the battlefield.

To fix that, we have a special version of the “get X” function which returns “if X isn’t defined, then X can be any integer whatsoever”, which we use during targeting. Which, until now, worked great. During predictive targeting, any creature could be a legal target for Disembowel regardless of its mana cost. But once you actually start casting Disembowel, you have to choose an X. Once X is chosen, then Disembowel can only legally target creatures with that mana value, and everything works fine from then on.

Trouble is, triggered abilities like Dune Drifter’s work differently. There is no predictive targeting at all. Rather, we jump straight to the “real” targeting. And, in the case of Dune Drifter, if it gets flickered, you'll go straight to real targeting without having chosen X, in which case, because we are using the undefined-X-can-be-anything function, we get the bug.

Now, if you’ve read this far and are paying attention, I bet you’ve come up with what seems like a clever solution, which is to use the undefined-X-can-be-anything function for predictive targeting, but the undefined-X-is-zero function for real targeting. And in fact, that’s precisely what I did. However, that broke this card:

[[Relentless Dead]]

Which has some very awkward templating, in which there’s an X constraint during targeting, but in which the act of choosing the target actually defines the X. (Note that similar recent cards such as [[Halo Forager]] use a reflexive trigger, so that X is always defined before targeting, which makes things much clearer, both for the player and for Arena).

So the “real targeting uses undefined-X-is-zero” did solve things, but only after carving out a special case exception for Relentless Dead.

External link →
2 days ago - /u/WotC_Jay - Direct link

Originally posted by Tepid_Tarf

Is there a reason these incoming fixes weren't mentioned in the weekly announcements?

Two reasons: Exposure and timing
As others have noted here, when there's a bug that's exploitable, we don't like to give it visibility before we have a fix. More players read our weekly announcements than Reddit, so even if it's been posted several times here, we could still be exposing it to a wider range of players.

Also, these weekly announcements are usually written up ~Thurs of the preceding week (to allow time for review, gathering images/screenshots, web staging, etc.). The timeline for putting together our post-release patch is very compressed, and some of these bugs didn't get fixed until shortly before Tuesday's release. The Cursecloth Wrapping and Dune Drifter bugs were literally fixed after the weekly announcements were published.

We do list all of the fixes in the patch notes: Patch Notes - 2025.45.10 – MTG Arena