When you open a booster pack, how do you read cards? They have symbols and text, and of course you can read them and determine what they do. However, the card can't do anything, because you're not playing a game.
During a game, the card has a complex context that influences how you read it; For example, its color may have changed.
Humans can read a card outside the game and inside the game, but it's hard for a computer. The difference between these two views is very important and currently makes me some problems. A card outside the game (template), like the one from the booster, is a constant thing - it can't change between different copies. This means that multipe cards inside the game can share the same template, but those are then individuals. They have the same template, but that's it.
The same thought can be applied to abilities and spells, I think. Abilities and spells have another, even harder problem: Their effects. While cards just sit there, spells and abilities can directly influence the game, and what influence that is depends on how the spell/ability was played.
So what's the solution to the problem? Well, in a nutshell, the data structure for cards, spells and abilities is duplicated.
Outside of the game is CardTemplate and CardParts, inside the game is CardObject and CardCharacteristics. A CardCharacteristics is assigned to a CardObject is responsible for providing the characteristics, respecting effects and the layer system, but also taking into account the values "printed" on a CardParts object.
Outside the game is ActivatedAbility, inside the game is ActivateAction, PlayInformation and AbilityObject.
- ActivatedAbility has a method getPlayInformation() which takes an ActivateAction and returns a PlayInformation.
- The PlayInformation is the real worker of abilities and implements modes, targeting, costs, effects etc. It depends on the game, so an activated ability can only create the PlayInformation if a game is provided.
- And to make things easier, the activate action has some additional infos like who played the ability and what card the ability is on (like I said, ActivatedAbility is outside the game, so it doesn't know which cards it is on. the ActivateAction knows).
I hope that you had a chance to look into my program; I know that this is very hard to imagine without directly looking at the code, So I won't try to go into more detail unless you wish so ;)