Monday, August 15, 2011

Card Uniqueness - A Thorny Problem

Forge has a problem.  Technically Forge has many problems but today we are going to investigate one of them.  "Why does Momentary Blink not work?"
Let me briefly explain how Momentary Blink is supposed to work.  (Basically Momentary Blink saves your creature from damage or destruction.)

1. You play Elvish Piper, a puny 1/1 creature
2. Your opponent plays Shock and targets Elvish Piper
3. You play Momentary Blink
4. Shock is countered, aka fizzles, because it does not have a legal target

The problem is that Forge doesn't process Momentary Blink correctly and Shock is perceived to have a valid target thus putting your Elvish Piper in the graveyard.  The reason that Forge does this is because it sees both Elvish Piper's as being the same.  And you may ask, "Why?"

Forge uses card objects (Java source code) to represent physical, cardboard cards.  Card objects are used everywhere that a physical card is used: in hand, in the graveyard, on the battlefield, exiled or in your library.  Card objects are equal if they have the same unique number. 

The problem is that Forge doesn't assign a new unique card number to Elvish Piper after Momentary Blink resolves.  This error can be easily solved by giving each creature (and permanent) a new unique card number when it enters the battlefield.  But the issue of "card uniqueness" continues to be a complicated, thorny problem.

Keep on forging,

--Ideally the user interface wouldn't show each card's unique ID number but I didn't know how to draw fancy pointing arrows like Magic Online.

--I thought this was a great card picture from Magic upcoming set Innistrad and I wanted to show it off.


nantuko84 said...

yep, it is well known issue. and you know there is always at least another option to solve (almost) any issue.
having the same id over the game brings other advantages, so it is possible to think over solving the fizzling rule from another point of view - e.g. by reimplementing Target objects. So shock will have Target that may 'target' only players or creature permanents. So before resolving it, the legality will be checked and as it is not valid anymore - Elvish Piper in Exile zone since Momentary Blink resolution - Shock will be countered.

Forge said...

"it is possible to think over solving the fizzling rule from another point of view - e.g. by reimplementing Target objects."

Yes but using a stupid int for the unique card ID has worked so far and Forge is up to 8,000+ cards. I'm not saying that it is the only option but it is very simple.

DualSage said...

umm, I'm pretty new at java, but from my knowledge of game rules, Real world magic handles this by essentially having 2 ID's. The first is the physical card ie what seems to be currently implemented in forge, and the second is a board ID. Essentially on casting a card (put onto the stack not at resolution), it generates a new temporary ID for the card and when that card returns to hand, is exiled, is sent to deck, or is sent to graveyard, it's considered a new object and the temp id is changed. Effects then specify a combination of the temp id's.

so for the blink example it would be :
momentary blink(card 25): exile temp ID 94, note that card ID is 24
Elvish piper(card 24): exiled-> temp ID 94 becomes 101
momentary blink part 2: get noted card id's (24) new temp id (101), move temp id 101 to battlefield
shock(card 12): deal 2 damage to 94 (can't find 94 so counters itself);

this also solves the rare occasions where an effect moves a card from zone 1 to zone 2 for a period but a second effect moves that from zone 2 to zone 3 then back. The first effect should then no longer be able to move it from zone 2 back to 1 since by moving from zone 3 to 2, it's a new object. An issue you'd get if you only kept 1 card ID per card in a container object and checked if it was in a legal container at resolution.

sorry had to repost, misread blink thought it was like venser, no edit button

Forge said...

DuelSage - "Real world magic handles this by essentially having 2 ID's."

You are right, just one ID doesn't work correctly.

zethfox said...

in wagic, we handle this issue by making a new copy of the object everytime it enters a different zone, in some cases we tell the engine to skip a zone, in the case of lands, they enter an engine zone called temp, and resolve from there, on copy we tell it to copy the value of the zone it had before temp.

this way we can check validness of the target effect ( shock damage ) on resolve. if the target is not valid anymore then we fizzle the effect.

I can imagine without such a system you must run into a a lot of "edge cases" where effects don't quite resolve as they should.

zethfox said...

it is actually part of the comprehensive rules too btw. so if you decide to go that route, it would bring you more inline with mtg rules as a handy side effect :)

403.4. Whenever a permanent enters the battlefield, it becomes a new object and has no relationship to
any previous permanent represented by the same card, except for the cases listed in rule 400.7. (This
is also true for any objects entering any zone)

wololo said...

As Zethfox said we create a new object at each zone change in Wagic. I felt nostalgic and looked at the revision where we changed that: Febryary 16, 2009, more than 2 years ago :)

Forge said...

I did understand the comprehensive rules but sometimes it is hard to do decide how to specifically implement them. Errors will abound but hopefully that are fixable.

tablet pc windows said...

I completely agree with the post.