
From time to time I like looking at how other Magic projects implemnt a card. I love Royal Assassin, this is how Firemox (formally the Magic-Project) and Incantus encode it. Incantus has card characteristics and if you read Magic’s comprehensive rules you will notice that it uses characteristics also. Since both Firemox and Incantus put each card in a separate file, all you have to do is download the file from the Internet and put it in the right directory and voila you have just added a new card.
In an effort to be complete, I’ll also show you the code for Royal Assassin taken from MTG Forge. The code is a little long and complicated compared to Firemox and Incantus. The Input class handles all mouse input, so a new Input object is created and used to target a tapped creature.
Incantus//filename: Royal Assassin
name = 'Royal Assassin'
cardnum = 174
type = characteristic('Creature')
supertype = characteristic('')
subtypes = characteristic(['Human', 'Assassin'])
cost = '1BB'
color = characteristic(['B'])
text = ['T Destroy target tapped creature.']
in_play_role = Creature(card, 1, 1)
in_play_role.abilities = [ActivatedAbility(card, TapCost(),
target=Target(target_types=isCreature.with(lambda c: c.tapped)),
effects=Destroy())
]
in_play_role.triggered_abilities = []
in_play_role.static_abilities = []
Firemox//filename: Royal_Assassin.xml
//all brackets were converted to quotes
//in order to be displayed correctly
"?xml version="1.0"?"
"card xmlns="http://sourceforge.net/projects/firemox" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=http://sourceforge.net/projects/firemox ../../validator.xsd name="Royal Assassin""
"rules-author-comment"By fabdouglas"/rules-author-comment"
"init"
"registers"
"register index="colorless" value="1"/"
"register index="black" value="2"/"
"register index="power" value="1"/"
"register index="toughness" value="1"/"
"/registers"
"colors"black"/colors"
"idcards"creature "/idcards"
"properties"assassin"/properties"
"/init"
"abilities"
"ability ref="cast-spell"/"
"activated-ability playable="instant" name="" zone="play""
"cost"
"action ref="T"/"
"action ref="target-creature""
"test"
"in-zone zone="playANDtapped"/"
"/test"
"/action"
"/cost"
"effects"
"action ref="destroy"/"
"/effects"
"/activated-ability"
"/abilities"
"/card"
MTG Forge//taken from the infamous CardFactory
if(cardName.equals("Royal Assassin"))
{
final Ability_Tap ability = new Ability_Tap(card)
{
public boolean canPlayAI()
{
CardList human =
CardFactoryUtil.AI_getHumanCreature();
human = human.filter(new CardListFilter()
{
public boolean addCard(Card c)
{return c.isTapped();}
});
CardListUtil.sortAttack(human);
CardListUtil.sortFlying(human);
if(0 < human.size())
setTargetCard(human.get(0));
return 0 < human.size();
}//canPlayAI()
public void resolve()
{
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c)
&& c.isTapped())
{
AllZone.GameAction.destroy(c);
}
}//resolve()
};//SpellAbility
Input target = new Input()
{
public void showMessage()
{
AllZone.Display.showMessage("Select target tapped creature to destroy");
ButtonUtil.enableOnlyCancel();
}
public void selectButtonCancel()
{stop();}
public void selectCard(Card c, PlayerZone zone)
{
if(c.isCreature() &&
zone.is(Constant.Zone.Play) &&
c.isTapped())
{
//tap ability
card.tap();
ability.setTargetCard(c);
AllZone.Stack.add(ability);
stop();
}//if
}//selectCard()
};//Input
card.addSpellAbility(ability);
ability.setDescription("tap: Destroy target tapped creature.");
ability.setBeforePayMana(target);
}