This article is a little long but it fully explains MTG Forge's card objects.
I was very happy when MTG Forge version 2 was able to accomplish the steps needed in order to play a card. While paying a mana cost doesn't seem difficult, in reality it involves many little steps that have to be programmed.
First let me give you a little bit of background on how MTG Forge 1 and 2 actually encodes a Magic card. (I'm skipping a lot of details that I have described elsewhere and in the actual code. And remember that an object is just another term for a group of Java statements.) A card object is very basic and holds the card's name, type (like sorcery or creature) and any creature subtypes (like Elf or Goblin). A card object holds one or more SpellAbility objects. SpellAbility objects are used to represent all spells and activated abilities. SpellAbility objects implement the actual function of a card, like destroying all creatures.
So when you play a card, you are playing the SpellAbility object that the card is holding. The potential problem is that a card may hold many SpellAbility objects. The Royal Assassin card holds two SpellAbility objects, one is the normal summon creature spell and the other SpellAbility represents Royal Assassin's "tap: destroy target tapped creature" ability.
SpellAbility also has a method called "canPlay()" which returns true if it can currently be played and false if it cannot. A sorcery like Wrath of God has a SpellAbility that allows it to be played from your hand. Activated abilities like Royal Assassin's have SpellAbility objects that can only be used when the card is in play.
To get back to my original question, "The potential problem is that a card may hold many SpellAbility objects." When you click on a card to play it, each SpellAbility is checked to see whether it can be played. If you try to play Royal Assassin from your hand, the summon creature SpellAbility can be played while the SpellAbility representing the activated ability cannot.
Using the same object, SpellAbility, to represent all spells and abilities has saved me a TON of extra work. At first I was coding spells and activated abilities differently but after stepping back from the problem, I was able to handle both situations with the same code. Finding simple solutions takes a lot of hard work, lol.
(The stack in MTG Forge only holds SpellAbility objects. The computer AI also uses SpellAbility. In the beginning I had to write a card for you, the player, and then rewrite the whole card for the computer. The computer uses SpellAbility canPlayAI() method to determine if it should play the card. With a card like Naturalize, the computer will only play it if you have an artifact or enchantment.)
Below is a listing of the relevant methods for Card and SpellAbility. Be aware that Card objects don't have a mana cost, only SpellAbility does. Currently SpellAbility doesn't easily handle activated abilities that have additional costs like "tap" or "sacrifice this card" and I'm still working on this problem. The resolve() method in SpellAbility is where the function of a card is put like "destroy all creatures" or "target creature gets +3/+3 until end of turn."
getSpellAbility() : SpellAbility
canPlay() : boolean
canPlayAI() : boolean
getManaCost() : String
The Card object also holds extra information like a creature's attack and defense. While conceptual this might be a little incorrect, the code was easy to write. Usually I have trouble coding something if my design is wrong.