As said before, the rules of the games are described in the file mtg.xml in the src/main/resources/tbs directory. You will often search withing this file to get some already written tests, actions or abilities, so let's see the structure of this file.
The mtg.xml starts with the <tbs> element, which stands for "Turn Based Strategy". Some of the attributes specify the XML schema location, the XML namespace, some others specify the name of the game, the version and the author. We also have information about the picture of the back of the cards file.
Magic Project also implements a database management for informations on cards not related to the rules, like the picture of the card, the flavor text or the artist. All these informations can be grabbed automatically from various sites by just providing a well formed XML proxy file.
The <database-properties> element in the mtg.xml file is used to declare the different informations understood by Magic Project. You will find below an extract of this element from the mtg.xml file.
<database-properties> <property name="card.artist-credit" type="java.lang.String" translate="false" /> <property name="card.flavor-text" type="java.lang.String" translate="false" /> <property name="card.sets" type="java.util.List" translate="true" /> <property name="card.text" type="java.lang.String" translate="false" /> <property name="card.id" type="java.lang.String" translate="false" /> <property name="card.set" type="java.lang.String" translate="true" /> <property name="card.version" type="java.lang.String" translate="false" /> </database-properties>
Magic Project dynamically download the mana symbols needed to display the abilities from the Wizards of the Coast website for copyright considerations. The <mana-symbols> element stands for giving Magic Project all the information needed to properly download these symbols.
The element <license> just give a description of the license linked to the game referenced in the mtg.xml file. You will find an extract of this license description below :
<licence> This program is not published, produced or supported by Wizards Of The Coast(TM), Inc. Magic The Gathering(TM) and Wizards Of The Coast(R) Inc. are registered trademarks owned by Wizards Of The Coast(R) Inc., a subsidiary of Hasbro, Inc. </licence>
Most of the elements of the Magic the Gathering game implementation in Magic Project are referenced by integer values. To make rules readable by a human, we can also use aliases for specific integer values, which are declared within the <aliases> element.
Let's look at the different availables aliases.
These aliases are used in many different situations :
Name of the alias |
none |
all |
abortme |
abort |
destroy |
manapool |
manacost |
threshold |
All the different types of damage can be tested using this set of available aliases :
Name of the alias |
damage-normal |
damage-combat |
damage-cannot-be-prevented |
damage-cannot-be-redirected |
damage-cannot-be-regenerated |
damage-cannot-be-prevented-redirected |
damage-can-prevent |
The position of a card in a zone can be referenced using these aliases :
Name of the alias |
top |
bottom |
The following aliases are used in damage prevention :
Name of the alias |
damage-any |
damage-combat-only |
damage-combat-can-be-prevented |
damage-can-be-prevented |
damage-can-be-redirected |
damage-can-be-regenerated |
The following aliases are used for phase indexes :
Name of the alias |
precombat-main |
eoc.index |
postcombat-main |
The following aliases are used for game static indexes, they are reseted each turn :
Name of the alias |
attack-step-index |
nb-attacking-group |
assignment-configuration |
assignment-configuration-int |
beginning-of-combat-target-lists |
normal-next-player |
skipping-turn |
turnid |
nbattacking |
The following aliases are used for registers dedicated to cards or players :
Name of the alias |
colorless |
black |
blue |
green |
red |
white |
state |
damage |
combat.assignedto |
free0 |
free1 |
The following aliases are used for registers dedicated to cards :
Name of the alias |
combat.toassign |
power |
toughness |
special-abilities |
The following aliases are used for registers dedicated to players :
Name of the alias |
poison |
life |
mulligan |
creatures-moved-in-graveyard-from-play-this-turn |
damage-dealt-this-turn |
hand-vibility-modifiers |
initialized |
land-remain-to-cast |
maxi-cards-in-hand |
playedland |
The following aliases are used for card types :
Name of the alias |
mana-source |
permanent |
instant |
sorcery |
The following aliases are used for permanent types :
Name of the alias |
enchantment |
local-enchantment |
global-enchantment |
land |
swamp |
island |
forest |
mountain |
plains |
creature |
artifact |
artifact-creature |
The following aliases are used for phases :
Name of the alias |
untap |
upkeep |
draw |
main |
declare-attack |
declare-attacking |
declare-blocking |
combat-deals |
eoc |
eot |
cleanup |
The following aliases are used for protection types :
Name of the alias |
protection-from-idcard |
protection-from-enchantments |
protection-from-creatures |
protection-from-artifacts |
protection-from-color |
protection-from-black |
protection-from-blue |
protection-from-green |
protection-from-red |
protection-from-white |
protection-from-property |
protection-from-goblins |
protection-from-kavu |
protection-from-gorgons |
protection-from-clerics |
protection-from-beasts |
protection-from-dragons |
protection-from-spirits |
protection-from-arcane |
The following aliases are used for categories of untargetable property :
Name of the alias |
untargetable-by-idcard |
untargetable-by-creature |
untargetable-by-sorcery |
untargetable-by-enchant |
untargetable-by-artifact |
untargetable |
The following aliases are used for card properties :
Name of the alias |
double-strike |
first-strike |
flying |
rampage |
trample |
snow |
protection-from-spells |
protection-from-abilities |
untap-under-condition |
basic-land |
attacks-if-able |
banding |
shadow |
fear |
islandwalk |
forestwalk |
swampwalk |
plainswalk |
mountainwalk |
block-as-flying |
attackingdoesnotcausetotap |
vigilance |
haste |
does-not-untap |
wall-can-attack |
cannot-attack |
cannot-block |
artifact-damage-reduced-to-0 |
spell-damage-reduced-to-0 |
creature-damage-reduced-to-0 |
damage-reduced-to-0 |
sorcery-damage-reduced-to-0 |
token |
defender |
indestructible |
unblockable |
cannot-be-enchanted |
enchant-world |
desert |
lair |
locus |
equipment |
desertwalk |
cannot-be-countered |
cannot-use-T |
sunburst |
protection-from-monocolored |
protection-from-multicolored |
protection-from-all-colors |
flash |
morph |
snow-islandwalk |
snow-forestwalk |
snow-swampwalk |
snow-plainswalk |
snow-mountainwalk |
nonbasic-landwalk |
convoke |
may-not-untap |
legendary-landwalk |
cannot-be-blocked-by-artifacts |
cannot-be-blocked-by-walls |
All the declared creatures types available in Magic Project are listed below :
Name of the alias |
FIRST_SUB_TYPE |
abomination |
aboroth |
advisor |
aladdin |
albatross |
alchemist |
ali-baba |
ali-from-cairo |
alligator |
ambush-party |
ancestor |
angel |
ant |
antelope |
ape |
archaeologist |
archer |
artificer |
asp |
assassin |
assembly-worker |
atog |
aurochs |
avatar |
avenger |
avizoa |
badger |
ball-lightning |
bandit |
banshee |
barbarian |
barishi |
basilisk |
bat |
bear |
beast |
bee |
beeble |
behemoth |
being |
berserker |
bird |
blinkmoth |
boar |
bodyguard |
bringer |
brother |
brownie |
brushwagg |
bull |
bureaucrat |
butterfly |
camarid |
camel |
caravan |
caribou |
carnivore |
carriage |
carrier |
cat |
cavalry |
cave-people |
centaur |
cephalid |
cheetah |
chicken |
chimera |
citizen |
clamfolk |
cleric |
clone |
cobra |
cockatrice |
constable |
cow |
crab |
crocodile |
crusader |
dandan |
demon |
dervish |
deserter |
devil |
devouring-deep |
dinosaur |
djinn |
dog |
doppelganger |
dragon |
dragonfly |
drake |
drill-sergeant |
drone |
druid |
dryad |
dwarf |
eater |
eel |
effigy |
efreet |
egg |
elder |
elemental |
elephant |
elf |
el-hajjaj |
enchantress |
entity |
erne |
essence |
exorcist |
faerie |
fallen |
farmer |
ferret |
fiend |
fish |
flagbearer |
flying-men |
force |
fox |
frog |
frostbeast |
fungus |
fungusaur |
gaea's-avenger |
gaea's-liege |
gargoyle |
gatekeeper |
general |
ghost |
ghoul |
giant |
gnome |
goat |
goblin |
golem |
gorgon |
graveborn |
gremlin |
griffin |
guardian |
gus |
gypsy |
hag |
harlequin |
hell's-caretaker |
heretic |
hero |
hipparion |
hippo |
homarid |
hornet |
horror |
horse |
horseman |
hound |
human |
hunter |
hydra |
hyena |
illusion |
imp |
incarnation |
infernal-denizen |
inquisitor |
insect |
island-fish |
jackal |
jellyfish |
kavu |
keeper |
kelp |
king |
kithkin |
knight |
kobold |
kraken |
lady-of-proper-etiquette |
leech |
legend |
legionnaire |
lemure |
leper |
leviathan |
lhurgoyf |
lichenthrope |
licid |
lion |
lizard |
lord |
lurker |
lycanthrope |
mage |
maggot |
maiden |
mammoth |
manticore |
mantis |
marid |
martyr |
master |
medusa |
meerkat |
mercenary |
merchant |
merfolk |
mindsucker |
minion |
minor |
minotaur |
miracle-worker |
mist |
mistfolk |
mob |
mold-demon |
monger |
mongoose |
monkey |
monster |
mosquito |
mummy |
murk-dwellers |
mutant |
myr |
mystic |
nameless-race |
narwhal |
necrosavant |
nekrataal |
niall-silvain |
nightmare |
nightstalker |
noble |
nomad |
octopus |
ogre |
ooze |
orb |
orc |
orgg |
ouphe |
ox |
oyster |
paladin |
peacekeeper |
pegasus |
pentavite |
people-of-the-woods |
pest |
phantasm |
phelddagrif |
phoenix |
pig |
pikemen |
pincher |
pirate |
pixie-queen |
plant |
poison-snake |
poltergeist |
pony |
preacher |
priest |
prism |
pyknite |
rabbit |
raider |
ranger |
rat |
rebel |
reflection |
rhino |
robber |
roc |
rock-sled |
rogue |
rukh |
sage |
salamander |
sand |
saproling |
satyr |
scavenger |
scorpion |
scout |
serf |
serpent |
shade |
shaman |
shapeshifter |
shark |
sheep |
ship |
shyft |
sindbad |
singing-tree |
sister |
skeleton |
slith |
sliver |
slug |
smith |
snake |
soldier |
sorceress |
spawn |
speaker |
specter |
spellshaper |
sphinx |
spider |
spike |
spirit |
sponge |
sprite |
spuzzem |
spy |
squire |
squirrel |
stangg-twin |
starfish |
stone |
strider |
survivor |
swarm |
tactician |
tarpan |
taskmaster |
tetravite |
thief |
the-biggest-baddest-nastiest-scariest-creature-you'll-ever-see |
thopter |
thrull |
thundermare |
tiger |
titan |
toad |
tombspawn |
tortoise |
townsfolk |
tracker |
treefolk |
troll |
turtle |
twin |
uncle-istvan |
undead |
unicorn |
vampire |
vedalken |
viashino |
villain |
viper |
volver |
vulture |
walking-dead |
fillette |
war-rider |
warrior |
warthog |
wasp |
wave |
whale |
whippoorwill |
wight |
wiitigo |
wildebeest |
will-o'-the-wisp |
wirefly |
witch |
wizard |
wolf |
wolverine |
wolverine-pack |
wolves-of-the-hunt |
wombat |
wood |
worm |
wraith |
wretched |
wurm |
yeti |
zombie |
horsemanship |
samurai |
monk |
urza-s |
cyclops |
arcane |
monl |
minor-demon |
archon |
wall |
construct |
LAST_SUB_TYPE |
A bunch of integer registers (like life) are allocated to each player. the elements <registers-first-player> and <registers-first-player> are decaded to the initialisation of these registers. You will find below an extract of theses elements from the mtg.xml file :
<registers-first-player> <register index="life" value="20" /> <register index="maxi-cards-in-hand" value="7" /> <register index="land-remain-to-cast" value="1" /> <register index="hand-vibility-modifiers" value="0" /> <register index="playedland" value="0" /> <register index="mulligan" value="7" /> </registers-first-player> <registers-second-player> <register index="life" value="20" /> <register index="maxi-cards-in-hand" value="7" /> <register index="hand-vibility-modifiers" value="0" /> <register index="playedland" value="0" /> <register index="mulligan" value="7" /> </registers-second-player>
The next element <phases> declare the differents phases of a turn in the implemented game. It also specifies which type of spells are playable during these phases.
For any card in game with a specific state (like summoning sickness), Magic Project interprets the <state-pictures> element to get the picture and the test associated to each state. If the index and state attributes are provided, Magic Project will make a bitwise compare with the index value of card's registers and the given state value. width and height values determines the size of the picture to display on the card. You can make Magic Project positionning automatically the picture (trailing) by setting the x and the y attributes to -1.
In Magic the Gathering game, some actions are linked to a picture. This is true for the action "tap" for example. The element <action-pictures> declares the different pictures associated to actions.
The element <tooltip-filters> informs Magic Project of the amount of informations to show on cards depending on various tests (for example, it is not necessary to show the colors of a land card since all of them are colorless).
The static modifiers are modifications that apply to cards automatically since they verify the associated test. They are declared with the <static-modifiers> element. We will find in this element, for example, the static modifiers that give any basic land type the ability to produce the associated mana by tapping it, the static modifier for a play-using-morph creature or the ability of cards with flash to be cast at any time.
You will find below an example of the static modifier for creatures with the morph ability :
<static-modifier zone="play"> <modifiers> <register-indirection index="power" value="2" operation="set" /> <register-indirection index="toughness" value="2" operation="set" /> <idcard-modifier idcard="creature" operation="set" /> <property-modifier operation="remove" property="all" /> <property-modifier operation="add" property="morph" /> <color-modifier operation="clear" /> </modifiers> <while> <and> <has-property property="morph" /> <not> <is-face-up /> </not> </and> </while> </static-modifier>
In the element <abilities>, we can find all the abilities associated directly to the general management of the game.
The element starts with the system abilities (declared with the <system-ability> elements) that allow players to play the attack phase, inits the game, implements the draw and the discard phase, implements the mulligan, manages and initializes the turn, manages the lethal damage or the manaburn, implements the legend rule, implements the enchant world rules or the limitation while playing lands.
These declarations are followed by the replacement abilities, which stand for abilities that trigger on specific actions and replace theses actions dynamically by other actions. They are declared using the <replacement-ability> element. We will find here the replacement abilities that trigger when a token goes to the graveyard (in fact it is put out of the game), that trigger when a card is played using flashback (when the spell resolves, it goes out of the game) or that trigger when a card is played with buyback (when the spell resolves, it goes to its owner's hand).
The layout of the game is also described in the XML file using the <layout> element. Common panels and zones are declared within.
This is the most important part of the XML file for card rules writers. Identified by the element <references>, it contains a set of tests, actions, abilities or attachments that can be referenced from your card XML code.
These are described withing the nested <tests> element. We can find the following references :
Reference name | Description |
has-imprinted-card | Returns true if there is an imprinted card on the current card. |
hellbent | Returns true if there is no cards in your hand. |
once-each-turn | Has this "once each turn" ability not been played ? |
tested-just-summoned | Has the tested card just been summoned ? |
just-summoned | Has the current card just been summoned ? |
before-attackers-declaration | Is the current phase your attackers declaration phase ? |
during-your-untap | Is the current phase your untap phase ? |
during-modifier-untap | Is the current phase the untap phase of controller of modifier creator ? |
during-your-upkeep | Is the current phase your upkeep phase ? |
during-your-draw | Is the current phase your draw phase ? |
threshold | Does the tested card controller graveyard contain at least an amount of cards greater or equal to the number identified by the threshold registry of that card ? |
tested-is-attacking | Is the tested card attacking ? |
first-target-is-attacking | Is the first card in the target list attacking ? |
is-attacking | Is the current card attacking ? |
saved-is-attacking | Is the saved card attacking ? |
tested-is-blocking | Is the tested card blocking ? |
first-target-is-blocking | Is the first card in the target list blocking ? |
is-blocking | Is the current card blocking ? |
tested-is-blocked | Has the tested card been blocked ? |
is-blocked | Has the current card been blocked ? |
is-untapped-under-condition | Has the tested card been untapped manually ? |
tested-has-combat-damage-to-assign | Does the tested card have combat damage to assign ? |
tested-is-unblocked | Has the tested card not been blocked ? |
is-unblocked | Has the current card not been blocked ? |
tested-in-combat | Is the tested card in combat ? |
in-combat | Is the current card in combat ? |
cantap | Can the current card tap ? |
can-use-T | Can the current card use the {T} ability (in addition to the previous test, this one tests whether the current card is not affected by a limitation that doesn't allow it to tap) ? |
has-counter | Is there a private card counter ? This counter is not visible for players. Also see init-counter ability. |
is-multicolored | Is the tested card a multicolored card (it has at least two colors) ? |
this-is-multicolored | Is the current card a multicolored card (it has at least two colors) ? |
is-monocolored | Is the tested card a monocolored card ? |
this-is-monocolored | Is the current card a monocolored card ? |
is-colored | Is the tested card a colored card (it has at least one color) ? |
this-is-colored | Is the current card a colored card (it has at least one color) ? |
is-targetable | Is the tested card targetable ? |
is-targetable-land | Is the tested card a targetable land ? |
is-targetable-spell | Is the tested card a targetable spell ? |
valid-damage-source | This test must return true to design a valid damage source. |
is-targetable-damage-source | This test must return true to design a targetable damage source. |
is-targetable-ability | To have an ability being targetted properly, this test must return true. |
is-targetable-creature | To have a creature being targetted properly, this test must return true. |
is-targetable-artifact | To have an artifact being targetted properly, this test must return true. |
is-targetable-tappable | To have an tappable permanent (creature, artifact or land) being targetted properly, this test must return true. |
is-basic-land | Is the tested card a basic land ? |
is-nonbasic-land | Is the tested card a non-basic land ? |
only-for-artifact-spell | Test used to apply restrictions on the use of mana that can only be used to pay artifact spells mana cost (Mishra's Workshop for example). |
only-for-colored-spell | Test used to apply restrictions on the use of mana that can only be used to pay multicolored spells mana cost. |
only-for-cumulative-upkeep | Test used to apply restrictions on the use of mana that can only be used to pay cumulative upkeep mana costs. (Mishra's Workshop for example). |
valid-block | To be chosen to block the current attacking, the tested card must verify that this test returns true. |
is-targetable-player | To have a player being targetted properly, this test must return true. |
is-targetable-dealtable | To have a dealtable (creature of player) being targetted properly, this test must return true. |
is-targetable-artifact-creature | To have an artifact creature being targetted properly, this test must return true. |
is-targetable-enchantment | To have an enchantment being targetted properly, this test must return true. |
is-targetable-local-enchantment | To have an aura being targetted properly, this test must return true. |
can-attack | Can the tested card attack ? |
valid-enchant | Test used for the attachment of an aura to the enchanted permanent. |
valid-enchant-land | Test used for the attachment of an aura to the enchanted land. |
valid-enchant-creature | Test used for the attachment of an aura to the enchanted creature. |
valid-enchant-enchantment | Test used for the attachment of an aura to the enchanted artifact creature. |
valid-enchant-artifact-creature | Test used for the attachment of an aura to the enchanted artifact creature. |
valid-enchant-artifact | Test used for the attachment of an aura to the enchanted artefact. |
valid-equip-creature | Test used for the attachment of an equipment to the equipped creature. |
valid-to-enchant | Internal test used to select a valid card to enchant (do not use this directly). |
valid-creature-to-enchant | Test used to select a valid creature to enchant. |
valid-enchantment-to-enchant | Test used to select a valid enchantment to enchant. |
valid-land-to-enchant | Test used to select a valid land to enchant. |
valid-permanent-to-enchant | Test used to select a valid permanent to enchant. |
valid-artifact-creature-to-enchant | Test used to select a valid artifact creature to enchant. |
valid-artifact-to-enchant | Test used to select a valid artifact to enchant. |
valid-to-equip | Internal test used check the equip stills valid (do not use this directly). |
valid-creature-to-equip | Internal test used check the equip stills valid for the equiped creature. |
valid-equip | Internal test used to select a valid card to equip (do not use this directly). |
valid-equip-creature | Test used to select a valid creature to equip. |
died-card | This test is used by update-toughness and update-damage abilities. |
priv_blocking-tested-counter | Test only used by combat-damage assignation ability to check the creatures blocking the super.tested card. |
priv_blocked-by-tested-counter | Test only used by combat-damage assignation ability to check the creatures blocked by the super.tested card. |
priv_currentplayer-has-to-discard | Test used during the discard phase to verify if the current player has to discard cards from his hand. |
flashback-used | Has the flashback been used ? |
buyback-used | Has the buyback been paid for this spell ? |
has-no-more-fading | Returns true if the current card has no more fading counter on it. |
can-regenerate | Can the creature generate ? This test cannot be used in event test. |
is-valid-blocking-creature-for-targeted-attacking | ? |
has-at-least-one-valid-blocking-creature | ? |
valid-creature-equip | Test used to select a proper target for an equipment. |
These are described withing the nested <actions> element. Some reference are MACRO([value],[test]), which means that you can dynamically append a test to the referenced action or pass a value to the referenced action (if value is specified in the parenthesis just after MACRO). We can find the following references :
Reference name | Description |
counter | Counters the spell(s) in the target list. |
use-once-each-turn | Marks the ability that referenced this action as already been used this turn. |
target-permanent-enchant | MACRO(test) : allows you to target a valid permanent to enchant. |
all-creatures | MACRO(test) : targets all the creatures in play. |
all-lands | MACRO(test) : targets all the lands in play. |
target-for-attachment | MACRO(test) : allows you to target a valid permanent to have the current card to be attached to this target (works for equipments and auras). |
target-creature-enchant | MACRO(test) : allows you to target a valid creature to enchant. |
target-land-enchant | MACRO(test) : allows you to target a valid land to enchant. |
target-artifact-enchant | MACRO(test) : allows you to target a valid artifact to enchant. |
target-damage-source | MACRO(test) : allows you to target a valid damage source. |
target-local-enchantment | MACRO(test) : allows you to target a valid aura in play. |
target-enchantment | MACRO(test) : allows you to target a valid enchantment in play. |
target-land | MACRO(test) : allows you to target a valid land in play. |
target-creature | MACRO(test) : allows you to target a valid creature in play. |
target-artifact | MACRO(test) : allows you to target a valid artifact in play. |
target-artifact-creature | MACRO(test) : allows you to target a valid artifact creature in play. |
target-permanent | MACRO(test) : allows you to target a valid permanent. |
target-noncreature-artifact | MACRO(test) : allows you to target a valid non-creature artifact in play. |
target-nonartifact-creature | MACRO(test) : allows you to target a valid non-artifact creature in play. |
target-tappable | MACRO(test) : allows you to target a valid permanent that can be tapped. |
target-player | MACRO(test) : allows you to target a valid player. |
target-opponent | MACRO(test) : allows you to target a valid opponent. |
target-dealtable | MACRO(test) : allows you to target a valid dealtable (which is either a player or a permanent that can be dealt damage). |
target-card | MACRO(test) : allows you to target a valid card in play (equivalent to target-permanent). |
target-spell | MACRO(test) : allows you to target a valid spell in the stack. |
target-ability | MACRO(test) : allows you to target a valid activated ability in the stack. |
search-lib-up-to | MACRO(value,test) : allows you to search within your library up to value cards (you can cancel the operation). |
search-lib-up-to-player | MACRO(value,test) : allows the player in the first position of the target list to search within his library up to value cards (he can cancel the operation). |
search-lib | MACRO(test) : allows you to search within your library for one card (you cannot cancel the operation). |
search-lib-player | MACRO(value,test) : allows the player in the first position of the target list to search within his library up to value cards (he cannot cancel the operation). |
reveal | Reveals the cards in the target list to everyone and wait until the opponent decide to stop looking at your revealed cards. |
look | Allows you to look at the cards in the target list and wait until you decide to stop looking at these cards. |
finish-spell | Moves the card referencing this action to its owner's graveyard. |
shuffle-in-lib | Moves the cards in the target list to their owner libraries and shuffle the library of owner of the last card. |
shuffle-in-libs | Moves the cards in the target list to their owner libraries and shuffle all libraries. |
prepare-extra-turn | Prepares the game to let you play another turn after this one. |
T | Tap the card referencing this action. |
remove-from-combat | Removes the cards in the target list from combat. |
regenerate | Adds to the card referencing this action a replacement ability that triggers when this card is dealt lethal damage and replaces this action by removing this card from combat (if apply) and removing all damages that apply to it. This ability lasts until the end of the turn. |
regenerate-target | Apply the regenerate action to the last card in the target list. |
regenerate-attached-to | Apply the regenerate action to the card attached to the card referencing this action. |
remove-all-damage | Removes all damages that apply to the cards in the target list. |
restore-library-visibility | Restores the visibility for you of the libraries of the players in the target list (TODO). |
restore-hand-visibility | Restores the visibility of the hands of the players in the target list for the opponent (checks whether the opponent has a special ability to permanently have the right to see your hand). |
add-1-1-until-eot | Cards in the target list get -1/-1 until the end of the turn. |
add-2-2-until-eot | Cards in the target list get -2/-2 until the end of the turn. |
add-3-3-until-eot | Cards in the target list get -3/-3 until the end of the turn. |
add-4-4-until-eot | Cards in the target list get -4/-4 until the end of the turn. |
add+1+1-until-eot | Cards in the target list get +1/+1 until the end of the turn. |
add+1+0-until-eot | Cards in the target list get +1/+0 until the end of the turn. |
add+1+2-until-eot | Cards in the target list get +1/+2 until the end of the turn. |
add+2+2-until-eot | Cards in the target list get +2/+2 until the end of the turn. |
add+3+3-until-eot | Cards in the target list get +3/+3 until the end of the turn. |
add+2+1-until-eot | Cards in the target list get +2/+1 until the end of the turn. |
add+3+0-until-eot | Cards in the target list get +3/+0 until the end of the turn. |
add+2+0-until-eot | Cards in the target list get +2/+0 until the end of the turn. |
add+2+0-until-eoc | Cards in the target list get +2/+0 until the end of the combat. |
add+1+0-until-eot | Cards in the target list get +1/+0 until the end of the turn. |
add+0+1-until-eot | Cards in the target list get +0/+1 until the end of the turn. |
add+0+2-until-eot | Cards in the target list get +0/+2 until the end of the turn. |
add+0+3-until-eot | Cards in the target list get +0/+3 until the end of the turn. |
add-2+0-until-eot | Cards in the target list get -2/+0 until the end of the turn. Example : Ivory Charm |
gain-1-1-until-eot | The card referencing this action gets -1/-1 until the end of the turn. |
gain+1+1-until-eot | The card referencing this action gets +1/+1 until the end of the turn. |
gain+1+0-until-eot | The card referencing this action gets +1/+0 until the end of the turn. |
gain+2+0-until-eot | The card referencing this action gets +2/+0 until the end of the turn. |
gain+0+1-until-eot | The card referencing this action gets +0/+1 until the end of the turn. |
unblockable-until-eot | Cards in the target list become unblockable until the end of the turn. |
flying-until-eot | Cards in the target list gain flying until the end of the turn. Example : Raka-Disciple |
fear-until-eot | Cards in the target list gain fear until the end of the turn (they are unblockable except by black or artifact creatures). |
shadow-until-eot | Cards in the target list gain shadow until the end of the turn (they can bloc or be blocked only by creatures with shadow). |
wall-can-attack-until-eot | Cards in the target list are allowed to attack this turn (if possible) even if they have defender. |
haste-until-eot | Cards in the target list gain haste until the end of the turn (they can attack the turn they came into play). |
trample-until-eot | Cards in the target list gain trample until the end of the turn. |
banding-until-eot | Cards in the target list gain banding until the end of the turn. |
first-strike-until-eot | Cards in the target list gain first strike until the end of the turn. |
vigilance-until-eot | Cards in the target list gain vigilance until the end of the turn (attacking does not cause them to tap). |
untargetable-until-eot | Cards in the target list can't be the target of spells of abilities until the end of the turn. |
return-to-hand | Returns the cards in the target list to their owner's hand. |
move-library-top | Moves the cards in the target list to the top of their owner's library. |
remove-from-game | Removes the cards in the target list from the game (they are moved to the side zone, [TODO] creating a dedicated zone for such cards should be considered). |
put-in-graveyard | Puts the cards in the target list in their owner's graveyard. |
draw-a-card | Makes the players in the target list draw a card. Example : Bandage |
remove-a-card-from-library | Makes the players in the target list removes the top card of their library from the game. The target list is cleared after this operation. |
remove-a-card-from-graveyard | Allows the players in the target list to choose a card from their graveyard to be removed from the game. The target list is cleared after this operation. |
draw-a-card-next-upkeep | Makes you draw a card during the next turn upkeep. Example : Heal |
opponent-draw-a-card-next-upkeep | Makes the opponent draw a card during the next turn upkeep. |
pay-life | MACRO(value) : makes the controller of the card referencing this action pay value points of life. Beware, a test must be used to check whether the player have enought life to play this action (check mtg.xml for more information). |
gain-life | MACRO(value) : makes the controller of the card referencing this action gain value points of life. |
gain-life-target | MACRO(value) : makes the controller of the card referencing this action gain value points of life. |
lose-life | MACRO(value) : makes the controller of the card referencing this action loose value points of life. |
lose-life-target | MACRO(value) : makes the players in the target list loose value points of life. |
discard | MACRO(value,test) : makes you choose value cards from your hand and discard them. |
opponent-discards | MACRO(value,test) : makes the opponent choose value cards from his hand and discard them. |
discard-a-player | MACRO(value,test) : makes you choose value cards from the hand of the players in the target list and discard them. |
player-discard | MACRO(value,test) : makes the player in the first position in the target list choose value cards from his hand and discard them. |
player-discard-up-to | MACRO(value,test) : makes the player in the first position in the target list choose up to value cards from his hand and discard them. |
discard-cards_noname | Moves the cards in the target list to their owner's graveyard (this action is not named). |
discard-cards | Moves the cards in the target list to their owner's graveyard. |
destroy | Destroys the cards in the target-list. |
bury | Destroys the cards in the target-list. The destroyed card cannot be regenerated. |
destroy-target-eot | Destroys the first card of the target-list at the end of turn. |
remove-from-game-target-eot | Removes from game the first card of the target-list at the end of turn. |
sacrifice-this | Sacrifices this card (Move the card into the graveyard of his/her owner). |
sacrifice-a-creature | MACRO(value,test) : Sacrifices value choosen creatures. |
sacrifice-a-permanent | MACRO(value,test) : Sacrifices value choosen permanents. |
opponent-sacrifice-a-creature | MACRO(value,test) : Makes the opponent sacrifices value choosen creatures. |
sacrifice-an-artifact | MACRO(value,test) : Sacrifices value choosen artifacts. |
sacrifice-an-enchantment | MACRO(value,test) : Sacrifices value choosen enchantments. |
opponent-sacrifice-an-artifact | MACRO(value,test) : Makes the opponent sacrifices value choosen artifacts. |
sacrifice-a-land | MACRO(value,test) : Sacrifices value choosen lands. |
opponent-sacrifice-a-land | MACRO(value,test) : Makes the opponent sacrifices value choosen lands. |
sacrifice | Sacrifices the cards of the target-list. |
redirect-all-to-this | Redirects the all damage from first target to this card until end of turn. |
redirect-1-from-this | Redirects the next 1 damage from this to the first target until end of turn. Example : Nomads en-Kor |
redirect-2-from-this | Redirects the next 2 damage from this to the first target until end of turn. |
redirect-3-from-this | Redirects the next 3 damage from this to the first target until end of turn. |
redirect-all-from-this | Redirects all damage from this to the first target until end of turn. |
redirect-all | Redirects the all damage from first target to the second target until end of turn. |
redirect-1 | Redirects the next 1 damage from first target to the second target until end of turn. |
redirect-2 | Redirects the next 2 damage from first target to the second target until end of turn. |
redirect-3 | Redirects the next 3 damage from first target to the second target until end of turn. |
redirect-1-to-this | Redirects the next 1 damage from first target to this card until end of turn. Example : Daughter of Autumn |
redirect-2-to-this | Redirects the next 2 damage from first target to this card until end of turn. |
redirect-3-to-this | Redirects the next 3 damage from first target to this card until end of turn. |
prevent-1-on-this | Prevents the next 1 damage dealt to this card until end of turn. Example : Ordruun Commando |
prevent-all-on-this | Prevents all damages dealt to this card until end of turn. Example : Deftblade Elite |
prevent-all-from-this | Prevents all damages dealt by this card until end of turn. Example : Deftblade Elite |
prevent-1 | Prevents the next 1 damage dealt to the last target card until end of turn. Example : Heal, Samite Healer |
prevent-2 | Prevents the next 2 damage dealt to the last target card until end of turn. Example : Elvish Healer |
prevent-3 | Prevents the next 3 damage dealt to the last target card until end of turn. Example : Healing Salve |
prevent-4 | Prevents the next 4 damage dealt to the last target card until end of turn. Example : Hallowed Healer |
prevent-5 | Prevents the next 5 damage dealt to the last target card until end of turn. Example : Abuna's Chant |
prevent-x | Prevents the next X damage dealt to the last target card until end of turn. Example : Alabaster Potion |
prevent-all | Prevents all damage dealt to the last target card until end of turn. Example : Circle of Protection: Black |
prevent-all-combat-damage | Prevents all combat damage this turn Example : Moment's Peace |
put-in-play | Put in play this card under owner's control. |
choose-damage-source | Chooses a card that could damage something. Example : Circle of Protection: Black |
buyback | Active the buyback option for the current spell. Example : Constant Mists |
flashback | Active the flashback option for the current spell. Example : Moment's Peace |
target-equipable-creature | Target a creature could be equiped by THIS. Example : Grifter's Blade |
radiance | Radiance option implementation. Example : Rally the Righteous |
morph | Morph option implementation : face up the card. Example : Aphetto Alchemist |
imprint-card | This imprints the last target of target list into the card owning this action. The imprinted card is stored as 'private-object' component in the card. |
load-imprinted-card | Load the imprinted card into the target list. If there is no imprinted card, an error is thrown. Use the 'has-imprinted-card' test. |
pay-x | Pay colorless X manas. Example : Fireball |
pay-xx | Pay colorless XX manas. Example : Decree of Justice |
These are described withing the nested <abilities> element. Using these references is the best way to accelerate card developement and maintenance since repetitive code are place in this place. So if you find some abilities appearing often in cards, this is the right place to add a reference to share with the community of card rules developers. The project team will make infinite effort to add this ability detection in our card generator for the Oracle. Some abilities work as macro by accepting one or two actions lists. We can find the following references :
Reference name | Description |
suspend | Trigerred ability relative to the management of the suspend ability. It is used by the cast-suspend ability. The ability triggers at the beginning of your upkeep and remove one time mark from the card that reference this ability then if there is no more time mark on this card, it is put into play. TODO : the card must be considered to have been played during the turn when the card has been put into play and not during the turn when the suspend ability has been cast, this information is relevant for all cards that use the storm ability. An example of the use of this ability is available throught the Lotus Bloom card. |
cast-suspend | MACRO(actions, actions) : this activated ability must be referenced by any card using the suspend ability. It allows the owner of the card to cast the spell associated through the suspension mode and dynamically add to the removed from the game card the suspend trigerred ability. The first actions macro is used to specify the cost of the suspend ability. The second actions is called after removing the card from the game and allows you to implement the addition of time marks to the card removed from the game. An example of the use of this ability is available throught the Lotus Bloom card. |
provoke | Provoke trigger implementation. |
graft | Graft trigger implementation. Moves a +1/+1 counter from this to a card coming into play. |
cycling | Moves the card referencing this action to its owner's graveyard, and allows the card's owner to draw a card from its library. This ability is a macro, an actions list must be provided as parameter. Example : Sunfire Balm |
forecast | Forecast {macro actions} : {macro actions}. |
tap-add-B | {T} : add one black mana to your mana pool. |
tap-add-U | {T} : add one blue mana to your mana pool. |
tap-add-G | {T} : add one green mana to your mana pool. |
tap-add-R | {T} : add one red mana to your mana pool. |
tap-add-W | {T} : add one white mana to your mana pool. |
tap-add-C | {T} : add one colorless mana to your mana pool. |
cast-enchant | {T} : to put in play a local enchantment into play, attached to a valid permanent. |
cast-spell | {T} : to put in play a permanent, paying it's manacost. |
cast-morph | {T} : to put in play a morph card, paying 3. |
cast-flash | {T} : to put in play a permanent using flash ability, paying it's manacost. |
cast-land | {T} : to play a land. |
echo | MACRO([action]) The echo ability. This reference accept as macro an action to substitute the default pay-mana action. |
prevent-all-on-this | Prevents all damages dealt to this card. |
prevent-all-on-attachedto | Prevents all damages dealt to attached card. |
deals-no-combat-damage | The saved card deals no combat damage. |
rampage1 | Rampage 1 implementation. Example : Balduvian War-Makers |
rampage2 | Rampage 2 implementation. Example : Balduvian War-Makers |
rampage3 | Rampage 3 implementation. Example : Craw Giant |
rampage4 | Rampage 4 implementation. Example : Teeka's Dragon |
eot-sacrifice | At end of turn, sacrifice this card. Example : Dragon Whelp |
regenerate | Regenerates the saved card if possible. This ability should appear directly within the card abilities but used with create-ability action. |
shapeshifter-ability | Whenever a creature comes into play, THIS becomes a copy of that creature and gains this ability. Example : Unstable Shapeshifter |
These are described withing the nested <attachments> element. We can find the following references :
Reference name | Description |
enchant-creature | Use this reference to attach 'enchant: creature' auras to a valid creature to enchant. |
Magic Project is also capable to apply constraints on actions if they match the <action> child elements. These constraints are dynamically appended using the given operation (usually set to "and") to the test associated with the matched action. Theses constraints are declared using the <action-constraints> element. You will find here constraints concerning the ability to equip a creature with an equipment artifact for example (it's impossible to equip a creature if the equipment is also a creature in addition to its artifact type) :
<constraint operation="and"> <test> <and> <not> <has-idcard idcard="creature" card="this" /> </not> <has-property property="equipment" card="this" /> </and> </test> <actions> <attach name="equip" /> </actions> </constraint> <constraint operation="and"> <test> <and> <not> <has-idcard idcard="creature" card="this" /> </not> <has-property property="equipment" card="this" /> </and> </test> <actions> <pay-mana /> </actions> </constraint>
Magic Project can manage additional costs using the <additional-costs> element.
The last part of the XML file is dedicated to the objects, which can be considerated as counters (ice, poison, +1/+1, etc.). These are declared using the <objects> element.
As mentioned before, each card in a game such Magic the Gathering can hold its own specific rules. In Magic Project, we have to write one XML file per card to implement. The content of the file describe the rules of the card in the same language than the large XML file of the card game.
The best way to describe the structure of these files is to look at an example, why not coding the card from the Starter edition, Angel of Light ?
This example will make you know what the most important parts of a XML card rules description XML file are. Below you will find a picture of this card :
Let's start by looking at this card code :
<?xml version="1.0" encoding="ISO-8859-1"?> <card xmlns="http://sourceforge.net/projects/magic-project" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://sourceforge.net/projects/magic-project ../../mpvalidator.xsd" name="Angel of Light"> <rules-author-comment>riclas</rules-author-comment> <init> <registers> <register index="white" value="1"/> <register index="colorless" value="4"/> <register index="power" value="3"/> <register index="toughness" value="3"/> </registers> <colors>white</colors> <idcards>creature</idcards> <properties>vigilance flying angel</properties> </init> <abilities> <ability ref="cast-spell"/> </abilities> </card>
The declaration of the card always starts with the <card> element. It must specify the parameters xmlns (the XML namespace of the current file), xmlns:xsi (the XML namespace for the schema related elements and attributes), xsi:schemaLocation (which specify the location of the XML schema used to validate the structure of the file) and the name (which stands for the card's name in English without replacing or deleting any characters).
<card xmlns="http://sourceforge.net/projects/magic-project" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://sourceforge.net/projects/magic-project ../../mpvalidator.xsd" name="Angel of Light">
This is immediately followed by the <rules-author-comment> element which usually holds information about the author of the XML code of the card (which is generally set to its name of pseudo).
<rules-author-comment>riclas</rules-author-comment>
This element can be followed by a comment reminding the Oracle version of the rules of the card if it has been generated by the Oracle to XML tool.
The next element is the <init> element which holds all the static informations of the card. You will find in this element :
In the example, the card costs 4W and it has a power/toughness of 3/3.
<registers> <register index="white" value="1"/> <register index="colorless" value="4"/> <register index="power" value="3"/> <register index="toughness" value="3"/> </registers>
In the example, the card is a white card.
<colors>white</colors>
The example shows that the card is a creature.
<idcards>creature</idcards>
The example shows that the creature is an Angel with Flying and Vigilance (attacking doesn't it to tap) abilities.
<properties>vigilance flying angel</properties>
The next element is dedicated to abilities. The only ability declared is a reference to the cast-spell ability from the mtg.xml file. This ability allows the owner of this card to pay the casting cost of it in order to play it from its hand.
<abilities> <ability ref="cast-spell"/> </abilities>
Now you are aware of the basic structure of a card, it's a good idea to look at example of cards somewhat more complicated to implement.
This card is somewhat complicated to implement : it has interactions with the events concerning movement of cards and it has to check whether two cards share a permanent type. Below you will find a picture of this card :
Let's start by looking at this card code :
<?xml version="1.0" encoding="ISO-8859-1"?> <card xmlns="http://sourceforge.net/projects/magic-project" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://sourceforge.net/projects/magic-project ../../mpvalidator.xsd" name="Cloudstone Curio"> <rules-author-comment>Hoani CROSS</rules-author-comment> <init> <registers> <register index="colorless" value="3"/> </registers> <idcards>artifact</idcards> </init> <abilities> <ability ref="cast-spell"/> <triggered-ability zone="play"> <moved-card> <source-test> <not> <in-zone zone="play"/> </not> </source-test> <destination-test> <and> <in-zone zone="play"/> <controller player="you"/> <not> <has-idcard idcard="artifact"/> </not> </and> </destination-test> </moved-card> <cost> <choice cancel="true"> <either> <target type="card" mode="choose" restriction-zone="play" raise-event="false"> <test> <and> <controller player="you"/> <not> <is targetable="context.card"/> </not> <sup right="0"> <left> <and> <left> <card-types card="context.card"/> </left> <right> <card-types card="tested"/> </right> </and> </left> </sup> </and> </test> </target> </either> </choice> </cost> <effects> <action ref="return-to-hand"/> </effects> </triggered-ability> </abilities> </card>
The <init> element let us know that this card is an artifact with a mana cost of 3.
<init> <registers> <register index="colorless" value="3"/> </registers> <idcards>artifact</idcards> </init>
Let's observe the abilities of the card because you will find there the most important parts of the card implementation.
The first ability is for sure used to let the owner of this card cast it.
<ability ref="cast-spell"/>
The main ability of the card is a trigerred ability that triggers only when the card is in play :
<triggered-ability zone="play">
The card abily starts with "Whenever a nonartifact permanent comes into play under your control". Thus the ability will trigger if a card is moved from a zone different from the play zone to the play zone and only if the moved card is an non-artifact card that you control.
<moved-card> <source-test> <not> <in-zone zone="play"/> </not> </source-test> <destination-test> <and> <in-zone zone="play"/> <controller player="you"/> <not> <has-idcard idcard="artifact"/> </not> </and> </destination-test> </moved-card>
This ability has a hidden cost : targetting a valid permanent to eventually return to its owner's hand. That's why the next element is a <cost> element :
<cost> <choice cancel="true"> <either> <target type="card" mode="choose" restriction-zone="play" raise-event="false"> <test> <and> <controller player="you"/> <not> <is targetable="context.card"/> </not> <sup right="0"> <left> <and> <left> <card-types card="context.card"/> </left> <right> <card-types card="tested"/> </right> </and> </left> </sup> </and> </test> </target> </either> </choice> </cost>
The controller of the card has the choice to target or not the permanent, that's why you'll see the following element with the attribute cancel set to true :
<choice cancel="true"> <either> <target type="card" mode="choose" restriction-zone="play" raise-event="false"> <test> <and> <controller player="you"/> <not> <is targetable="context.card"/> </not> <sup right="0"> <left> <and> <left> <card-types card="context.card"/> </left> <right> <card-types card="tested"/> </right> </and> </left> </sup> </and> </test> </target> </either> </choice>
Letting the controller of the card target a permanent is done by the following element (the raise-event attribute is set to false because the ability is not targetted) :
<target type="card" mode="choose" restriction-zone="play" raise-event="false"> <test> <and> <controller player="you"/> <not> <is targetable="context.card"/> </not> <sup right="0"> <left> <and> <left> <card-types card="context.card"/> </left> <right> <card-types card="tested"/> </right> </and> </left> </sup> </and> </test> </target>
The test must verify that the targeted permanent ("tested") is controlled by you and that it is not the card that triggered this ability ("context.card") and that it shares a card type with the card that triggered this ability :
<and> <controller player="you"/> <not> <is targetable="context.card"/> </not> <sup right="0"> <left> <and> <left> <card-types card="context.card"/> </left> <right> <card-types card="tested"/> </right> </and> </left> </sup> </and>
The effects of the triggered ability are declared with the following element :
<effects> <action ref="return-to-hand"/> </effects>
The "return-to-hand" action reference just return the card in the target list to their respective owner's hand.