Wednesday, November 25, 2009

Forge's Architecture

The architecture for a computer program is very important since everything else in that program relies on it. Computer architecture is very similar to constructing a physical building. The program's architecture is the concrete foundation that you build on. If the foundation is cracked or broken, then you have a BIG problem. (I hope you understand that a program's architecture is very important even though you cannot see it.)

Forge's architecture restricts which cards are supported. Some cards cannot be added because the architecture isn't flexible enough. Cards like planeswalkers aren't really supported but were added by using elaborate hacks. The same thing applies to cards like Hypnotic Specter and Glorious Anthem. Even activated abilities that tap a card like Royal Assassin have to be "hacked" a little.

All of these "little hacks" add up and causes something later that "should work", not to work. Protection was a major update that required all of the targeting code for all of the cards to be changed. I didn't think about protection when I was creating Forge so all of the cards have to be changed one at a time in order to support protection.

Dennis, Rob, Zerker and others from the forums have donated weeks of their time toward Forge. And although I created Forge, these are the guys that keep it going.

5 comments:

nantuko84 said...

it is the second time when I read that it was big deal to implement protection as it needed to update ALL targeting cards. it's awesome and a little bit suprised me as I spent only a hour or so to implement it in MagicWars that, you know, has the same architecture for targeting (I believe because of using your architecture in MW%))

so I've just looked into mtgforge source code (dated 09-18-forge-full, not recent, but I could find the canTarget method there)

yep, now "all" targeting spells have CardFactoryUtil.canTarget(card, getTargetCard()).
ant the question is: wasn't it easier to add checking before sa.resolve() and say\log\print message about spell or ability fizzle. I believe it's more flexible and takes less time;)
or may be I misunderstood something, did I?

Rob Cashwalker said...

nantuko-
I agree that you could make that determination in one location before the sa.resolve() call.

However, the AI for a card needs to check if a target is good before deciding on it as a target, so that was one location multiplied by the hundreds of cards where it was needed.
If the game can prevent you from playing the effect against an illegal target, then it's more fun, because you can avoid wasting resources for an effect to just simply fizzle anyway. (the game allows so many other stupid plays)

The canTarget method was in the code a LONG time before protection was added. Some cards used it, many did not. Its presence was actually one of my first question to Forge.

DennisBergkamp said...

Although the original canTarget was found in GameAction.java (added mine in CardFactoryUtil, wasn't even aware one existed in GameAction until later :) ).

Forge said...

Yeah, this is probably the 2nd or 3rd time I've written about protection being a huge change. I'm just very impressed with it.

Forge said...

"Although the original canTarget was found in GameAction.java (added mine in CardFactoryUtil, wasn't even aware one existed in GameAction until later :) )"

In the back of my mind I knew that I might want to implement protection later but I decided to ignore the "protection issue" since it also applies to damage and combat.

(When you are just starting, it is hard to worry about "big issues" like protection which seem very far down the road.)