Monday, March 9, 2009

Overriding Core Rules 2

Cards likes Mana Flare and Doran, the Siege Tower are hard to implement because they change the core rules of Magic. The basic way, which is perfectly fine, is to have various parts of the program look to see which cards are in play. This has the drawback that all of the card code for Doran is not in one place and cannot be easily used by different cards. (Although it doesn’t seem like Wizards will be printing variations on Doran.)

Let me get sidetracked for a minute and then I’ll return to the main topic. I think it is a good idea if all of the rules are encoded in one large class which is named something like RulesEngine. Various phases and actions in Magic are intertwined which makes even getting the card’s color complicated sometimes, Painter’s Servant says something like “All cards in play are white”. Since RulesEngine is handling all aspects of Magic, even the small ones, RulesEngine can just easily check to see if Painter’s Servant is in play and return the appropriate color.

Now back Doran, if RulesEngine has a method like changeRules(String), Doran can simply use changeRules(RulesEngine.ASSIGN_TOUGHNESS). The RulesEngine class could have a bunch of constants that could be passed to changeRules(). Doran doesn’t care how its ability is implemented in RulesEngine, it just knows that it will be handled. Likewise Mana Flare could call changeRules(RulesEngine.DOUBLE_MANA).

There is an old computer joke that says anything can be programmed with enough layers of indirection (methods calling other methods), which is often true. If RulesEngine handles all of the data and actions that happen in a game, implementing “hard” cards like Doran and Mana Flare should be simple.

The reason that MTG Forge currently cannot handle protection is because there isn’t a “global” canTarget() method which is used to check to see if that spell can target that permanent. And when I say “global”, I just mean that it is used everywhere that a target is assigned.

Separating WHAT from the HOW is very important. In HTML the "b" attribute tells the browser to put that text in bold. The b attribute doesn't tell the browser HOW to do it.

Painter’s Friend isn’t a great example but I couldn’t think of a better one. I know I’ve read cards that say something like “All cards are white” but I probably have the wrong wording. Just for reference here is Doran and Painter’s Servant.


Gando the Wandering Fool said...

yeah I think we discussed global targetting before. Tis a shame. a Global canTarget() method would be quite useful. Not just for protection but for shroud as well. Couldn't you use a "_flag" member in the card objects to determine this? Or is that too weird to even comtemplate?

Anonymous said...

And the AI must know that Doran, Mana Flare and other complex cards are in play...

Forge said...

Gando - "Couldn't you use a "_flag" member in the card objects to determine this? Or is that too weird to even comtemplate?"

I don't quite understand what you are saying. I can't think of any way of hacking protection without changing all of the places in CardFactory that select a target, while this is possible, it is quite boring.

If canTarget(Card target, Card spell) did work, you could easily add "Protection from black" as a keyword.

(Card objects in MTG Forge have a list of strings which are used for abilities like flying, fear but the strings have also been used for other more complicated abilities like regeneration, pump effects, and "this card gets fear".

About the AI knowing how to play Doran. The Doran AI code could check to see if the computer has many 0/4 creatures. This isn't an optimal solution, but it is usually "good enough".

Anonymous said...

I kind of "hacked" Doran into MTGForge, and the way I did this was through a lot of checks :)

In most cases, the AI will know about the correct P/T of a creature when Doran is in play, but I think I might have missed a few spots, since I've seen the AI not block a creature with Doran in play, where it definitely should have.

Then again, I've seen the AI not block a creature WITHOUT Doran in play, where it definitely should have :D

Forge said...

"Then again, I've seen the AI not block a creature WITHOUT Doran in play, where it definitely should have :D"

The AI randomly doesn't attack or block in order to make it unpredictable, sometimes it just ends up making the AI look stupid and dumb though.

Anonymous said...

Hiya, new to the whole magic thing. The one item I don't seem to see is a way to create decks that would be considered type II. I am not sure what all cards are in the program but it appears to be just card names.

I kind of want to construct some decks, however I don't know what cards belong to what sets, and therefore what cards would be considered Type II and whatnot. Let me know if I am just missing it somewhere or if there is an easy way to look it up. thanks!

Gando the Wandering Fool said...

solfuries welcome! Yeah MTGForge does not have sets per se. You can edit the common.txt, uncommon.txt, and rare.txt files to change the "the sets" available for booster and sealed draft but the only way to control what is in constructed decks is to make them yourself without resorting to the generate a deck option.

DCelso said...

When can I get those magic card images like this knight?
The first time that I saw that you put one I though that was a standalone custom image but i am seeing that there are serveral cards.

Forge said...

They are pictures of the card tokens, you can get them from online stores or this forum which has scans of every Magic card.