Page 1 of 1

Circular dependencies w/ static abilities

PostPosted: 04 Sep 2009, 23:18
by telengard
I've run into an issue and I'm sure there is an easy way to deal with this. I'll try to put this in terms of MtG.

Let's say a card while in play has a static ability that says "This card is the color of all of your other in play cards" (for all I know some card like this exists). Now let's say that there are 2 of them in play. How do you handle that?

In this example I would have a hookable function called "get_colors" or something similar and in it I would do this (pseudo-code)

Code: Select all
colors get_colors(card)

if (in_play(card) and card == this_card)
  foreach (c in cards_i_have_in_play)
     (if c != this_card)
        colors += get_colors(c)
        // for now just ignore handling duplicates etc
return colors
The issue is that the call of get_colors inside of the hook will get into an infinite recursion scenario when more than 1 of this type of card is in play (and will happen when other similar abilities are in play).

I'm trying to come up with a clean way to deal with this sort of thing and for some reason after a few hours of thinking about it, nothing good (read: not a hack) has popped up.

Any ideas?

~telengard

Re: Circular dependencies w/ static abilities

PostPosted: 05 Sep 2009, 06:24
by Marek14
My solution would be to solve these cases with exception fields... basically, if a card is asked "what's your color?" during execution of a function that wants to determine its color, it answers "no damn business of yours" and returns nothing instead of running the recursion further.

This doesn't occur with color in actual Magic cards, but it can, and does, occur with cards that produce mana based on mana that COULD be produced by something else:

Benthic Explorers
Exotic Orchard
Fellwar Stone
Harvester Druid
Mana Web
Quirion Explorer
Reflecting Pool
Squandered Resources
Star Compass
Sylvok Explorer

Ideally, the system should allow for scenario where I only control Exotic Orchard, opponent controls Exotic Orchard and City of Brass, and his Exotic Orchard can tap for any color.

Re: Circular dependencies w/ static abilities

PostPosted: 10 Sep 2009, 19:24
by mtgrares
Have one object that implements all of the rules and answers all of the rules questions. RulesManager.getColor(Card) returns an array of colors. Having a "big object" isn't all that great but it may solve some of the trickier rules questions.

Re: Circular dependencies w/ static abilities

PostPosted: 10 Sep 2009, 22:03
by telengard
I figured this out in a way I'm happy with, although I haven't done a lot of testing with it yet. It doesn't blow up from stack overflow now, so that's good.

My implementation w/ fix can be seen here:

http://pastebin.com/m1bdbc19b

I'm not sure I can fully articulate why this works (I get it in my head but for some reason can't verbal-ize it).

Thanks everyone for the ideas!!

~telengard

Re: Circular dependencies w/ static abilities

PostPosted: 21 Nov 2009, 22:45
by nantuko84
I know the thread is rather old, but I'd like to say that I have similar problem (to be exact, with Exotic Orchard and Reflecting Pool) and I solved it this way:
1. When Orchard enters the battlefield, I subscribe it to two events:
@addToTable - triggers when new card appears, and I will recalculate mana can be produced by Exotic Orchard
and
@changeManaCanBeProduced - triggers when permanent begins to produce new mana type

so let say both players (player and opponent) have Exotic Orchard in play (both of them produce no mana)
then the opponent puts City of Brass that will fire @addToTable event
player's Exotic Orchard will get opportunity to produce any mana and fire @changeManaCanBeProduced event
opponent's Orchard will get opportunity to produce any mana as well and fire @changeManaCanBeProduced
player's Orchard won't get any new mana to produce and process will be stopped

p.s. couldn't find your implementation, the url provided seems old

Re: Circular dependencies w/ static abilities

PostPosted: 21 Nov 2009, 22:50
by telengard
nantuko84 wrote:<snip>
p.s. couldn't find your implementation, the url provided seems old
Yeah, pastebin only keeps it up for a little while, I've put it up again here (permanently):

http://pastebin.com/f74138f71

~telengard