Create your own cards

Heads up: Civilization III Free on Humble store if you get it before 10/21 10am PST. (note: affiliate link)

Important: This page is out of date, instead, please use our Wiki documentation

This text has been updated on 2009/08/31. Information is valid for Wagic 0.8.1

This is an explanation on how to add your own cards to Wagic. Please try to create your own sets and share them with everyone !

The cards used in Wagic can be found in the Res/sets/ folder.
This folder is split into “sets”, although this is not really important and matters only when buying boosters or starters.

These subfolders all contain a “_cards.dat” file. As long as this file is included in a subdirectory of the “sets” folder, the cards it describes will be automatically loaded into the game.

For example : Res/sets/MYSet/_cards.dat

The current variety of cards you can automatically add to the game without recompiling it is quite low, but it’s still better than having to wait for a new release, right ?

So what does this _cards.dat file look like ?
Well you can open one of those with any text editor (notepad, for example), and you’ll see that it is a list of:
[card]
***content***
[/card]



So what can be put in contents ?
Contents is a list of keys and values spearated by a “=” sign. the keys can be the following:
id
name
text
rarity
type
subtype
power
toughness
mana
target
abilities
auto
alias


id,name,rarity,type, are compulsory
. The other ones, in some circumstances, are needed as well (such as toughness and power for “regular” creatures). Text is compulsory if you do not plan to add pictures (or pictures that do not have that text) to your set.

id

id is a unique integer identifying the card. This id cannot be the same as an other id used in this set or in any other set. For Magic cards, I suggest you use the id referenced at Magic gatherer’s site.
For example : http://ww2.wizards.com/gatherer/CardDetails.aspx?&id=49 (Bad Moon alpha), the id is 49, as you can see from the URL
This id will be used when you build your decks, or the ai’s deck
id will also be used to retrieve the picture for the card. the picture associated to card id 123 in set MySet, will be at Res/sets/MySet/123.jpg. The associated thumbnail will be at Res/sets/MySet/thumbnails/123.jpg
Thumbnails must be 45x64px and pictures must be 200×285.

name

name is the name of the card

text

text is a text describing the effects of the card

rarity

rarity describes the probability of a card to be found in a booster or a starter. Valid values are C,U,R,M,L and respectively mean Common,Uncommon, Rare, Mystic rare

type

type describes the type of the card. Valid values are Sorcery,Instant,Creature,Artifact, Artifact Creature, Enchantment, Basic Land, Land

subtype

subtype describes the subtypes of the cards, separated by a space symbol. for example, human wizard.

power

power is an integer describing the power of the card, for creatures

toughness

toughness is an integer describing the toughness of the card, for creatures

mana

mana describes the cost needed to put the card in play. Mana costs are represented into brackets, like this : {W}{R}{R} , or {1}{G} , etc…
possible values are (W)hite, (G)reen, (R)ed, (B)lack, bl(U)e, and integers.
To represent hybrid mana, you put two mana symbols inside the same brackets. For example {WR} or {2U}

target

target describes the potential targets for some spells. The syntax is the following:
target_type_1[s][,target_type_2[s]][|area1[,area2]]
valid keywords for target_type are everything that can be found in the type and subtype keys of all cards, player, and the * symbol meaning all cards
adding a “s” to a target means “1 target or more”. otherwise, it is 1 target.
targets can be followed by strings inside brackets([]) to give more specific information on them. Keywords allowed inside the brackets are :attacking,blocking, tapped,red,green,blue,black,white,artifact and all abilities described in the “abilities” section, such as flying.
keywords inside brackets are spearated by a semicolon(;), and can be prefixed by a minus() sign that means “not”.
valid keywords for areas are : inplay,myinplay,opponentinplay,graveyard,mygraveyard,opponentgraveyard,stack,mystack,opponentstack,library,mylibrary,opponentlibrary * . inplay means anywhere in play. graveyard means any graveyard. stack means any spell on the stack(doesn’t matter who the controller is). library means any library (yours or your opponents).  * means any area of the game. The other ones are self explanatory.
The default value for areas is inplay
Sounds complex, but it’s not. Let’s see some working examples:

creature
any creature in play
artifact,enchantment
any artifact or enchantment in play
*|graveyard
any card in any graveyard
creature,player
any creature or player in play
mountains
one or more mountains in play
artifact,enchantment|mygraveyard
any artifact or enchantment in your graveyard
creature[-black;-artifact]
any non black, non artifact creature in play (that’s what acutally used for terror)
*|stack
any spell on the stack

If you cannot describe the target with the available keywords, then you’re doomed, you cannot add the card to the game without coding.

abilities

abilities: automatic keywords that describe the abilities of the card, separated by a comma. Currently supported keywords are:

“trample”,
“forestwalk”,
“islandwalk”,
“mountainwalk”,
“swampwalk”,
“plainwalk”,
“flying”,
“first strike”,
“double strike”,
“fear”,
“flash”,
“haste”,
“lifelink”,
“reach”,
“shroud”,
“vigilance”,
“defender”,
“banding”,
“protection from green”,
“protection from blue”,
“protection from red”,
“protection from black”,
“protection from white”,
“unblockable”,
“wither”,
“persist”,
“retrace”,
“exalted”,
“legendary”,
“shadow”,
“reachshadow”,
“foresthome”,
“islandhome”,
“moutainhome”,
“swamphome”,
“plainshome”,
“flanking”,
“rampage”,
“cloud”,
“mustattack”,
“cantattack”,
“cantblock”,
“doesnotuntap”,
“opponentshroud”,
“indestructible”,

Note that despite being supported, some of them don’t work like you would expect them to, due to some limitations in the engine.

auto

auto is the most complex one, as it allows to program the behavior of the cards to some extent. If you cannot add what you want with auto, it means you cannot add the card to the game without recompiling it.
Unlike other parameters, auto can appear several times in one card description.
Please note that the “auto” parameter is changing very often, and I cannot guarantee that future releases will be backward compatible !
an “auto” value is generally composed of two parts : a cost and an effect. For some cards, the cost of the auto ability is null, because it needed to be paid only when you cast the spell. See below for a description of the cost.
The values for auto can be:
[{cost}:]regenerate [target] regenerate target creature

[{cost}:]bury [target] : destroys target, cannot be regenerated

[{cost}:]destroy [target]: destroy target

[{cost}:]Damage:n [target|playerTarget] Does n damage to target

[{cost}:]n/m [target] : gives +n/+m to creature. n and m can be negative values. For auras, instants and sorceries, cost is usually empty. For instants, sorceries, and activated abilities, the effect lasts until end of turn. For auras, it lasts as long as the aura is present.

[{cost}:][-]ability [target] : gives ability to target. “ability” can be any of the keywords described in the ability section previously. For auras, instants and sorceries, cost is usually empty. For instants, sorceries, and activated abilities, the effect lasts until end of turn. For auras, it lasts as long as the aura is present.If a minus sign is used, this removes the ability from target.

[{cost}:]add{mana} : Mana producer. Adds mana if the user pays {cost}. {cost} can be emtpy, or contain only {t}, which is the case for basic lands

[{cost}:]lord(targets) ability [other]: ability is any ability that would work in the “auto=” line. For example, lord of Atlantis is lord(merfolk) islandwalk. other is used if the ability is not valid for the lord card itself.

[{cost}:]all(targets) ability:all works the same as lord, but guarantees that the action will occur only once. Whenever you have problems with “lord”, try to use “all” instead. For example: bury all(creature)

[{cost}:]foreach(targets) ability [other] : For example, Keldon Warlord is foreach([creature[-wall]|myinplay) 1/1.

[{cost}:]aslongas(targets) ability [other]: For example, Kird Ape is aslongas(forest|myinplay) 1/2.

[{cost}:]moveTo(zone) [target]: moves target card into specified zone. allowed keywords for zone are : mygraveyard,opponentgraveyard,ownergraveyard,graveyard,
myinplay,opponentinplay,ownerinplay,
myhand,opponenthand,ownerhand,hand,
myremovedfromgame,opponentremovedfromgame,ownerremovedfromgame,removedfromgame

[{cost}:]tap [target]: taps a target. if no target is available, taps self

[{cost}:]untap [target]: untaps a target. if no target is available, untaps self

[{cost}:]token(name,types, p/t,abilities colors)[*n] puts n tokens with name “name”, types “types”, power p, toughness t, abilities “abilities” and colors “colors. For example, for Dragon Roost (10E): auto={5}{R}{R}:token(Dragon,creature dragon, 5/5,flying red). Default value for n is 1.

[{cost}:]Fizzle [target]: cancel a spell on the stack

[{cost}:]copy [target]: become a copy of target (used for clone)

[{cost}:]Counter(p/t,n) [target] put n p/t counters on target creature. If n is negative, remove -n p/t counters from target creature.

[{cost}:]Rampage(p/t,n) [target] Whenever target creature gets blocked, it gets +p/+t for each blocker beyond the nth.

[{cost}:]Draw:n [playerTarget]: draw n cards

[{cost}:]life:n [playerTarget] gain n life. if n is negative, lose n life

[{cost}:]Deplete:n [playerTarget]: move n cards from the top of the library to the graveyard

[{cost}:]Discard:n [playerTarget] randomly discard n cards

(values inside brackets are optional)

target

In all the above descriptions, targetis a value that allows you to code cards that have an ability allowing you to choose a new target each time you activate it. (think prodigal sorcerer). It is also used for cards that do not have real “targets”, but have effects on all cards matching some criteria, such as lords.
[target] is written in the form : target(targettype) where targettype is any string that would be accepted in the “target=” line. for example :

[card]
text={T}: Prodigal Sorcerer deals 1 damage to target creature or player.
id=1217
name=Prodigal Sorcerer
auto={T}:damage:1 target(creature,player)
rarity=C
type=Creature
mana={2}{U}
power=1
subtype=Human Wizard
toughness=1
[/card]

If that [target] value is not specified but a target is required, the value defined at the target= line will be used

playerTarget

In all the above descriptions, playerTarget is an optional value for effects that indirectly target a player. For example, Adarkar wastes say: Tap: Add W to your mana pool. Adarkar Wastes deals 1 damage to you. Since there is no target for the damage, we represent it like this in Wagic: {T}:Add {W} && Damage:1 controller

Valid values for playerTarget are controller,targetcontroller,opponent. When playerTarget is not specified, Wagic tries to use the most logical value for it: if a “target=” line is specified for an effect, Wagic will use this target if it’s a player, or the target’s controller if it is a card.

several auto effects

If several “auto” effects compete with each other, the game will automatically create a “choice” menu whenever a choice is needed. For example, this is the code for bayou:

[card]
auto={T}:Add {B}
auto={T}:Add {G}
id=1377
name=Bayou
rarity=R
type=Land
subtype=Swamp Forest
[/card]

You might want one cost to activate several actions, for example, Adarkar wastes say:{T}: Add {W} or {U} to your mana pool. Adarkar Wastes deals 1 damage to you.. This is done by putting the keyword && between to actions: auto={T}:Add {W} && Damage 1 controller.

Triggers

Triggers are declared with the keyword “@”. Accepted keywords are:

@[next] [my|opponent] (beginofturn|untap|upkeep|draw|firstmain|combatbegins|attackers|blockers|combatdamage|combatends|secondmain|endofturn|cleanup|beforenextturn): ability . Triggers the ability at specific phase changes.
Here is an example from Ice Age:

[card]
text=Draw a card at the beginning of the upkeep of the turn after Krovikan Fetish comes into play. Target creature gets +1/+1.
id=2464
target=creature
auto=:1/1
auto=@next upkeep:draw:1
name=Krovikan Fetish
rarity=C
type=Enchantment
mana={2}{B}
subtype=aura
[/card]

@movedTo(target) [from(zone)]: ability. Triggers the ability whenever a card matching “target” comes from “zone”. For example, @movedTo(creature|graveyard) from(inplay) means: Whenever a creature is put into a graveyard from play. From is optional, and defaults to “everywhere”. For example, @movedTo(*|stack) means: whenever a spell is cast

The abilities triggered by triggers can NOT have a cost currently, due to engine limitations

Cost description

Costs can contain mana, tap, and sacrifice. mana are represented the way you represent them in the manalines, for example {1}{B}{B}. Tap is represented with {T}, so tap for one colorless mana is represented with {T}:Add {1}.
Sacrifice is a bit more difficult. It can be as simple as {S} to sacrifice the card itself, or, {S(target)}, where target would be anything that can be represented on the target line. For example, {S(creature|myinplay)}. Note that for consistency, you always have to add |myinplay, because you cannot sacrifice anything else than stuff that you currently control. But this wil allow us to use the {s} keyword for other things in the future maybe. For example, Nantuko Husk (10E) says: Sacrifice a creature: Nantuko Husk gets +2/+2 until end of turn. , which is represented by: auto={s(creature|myinplay)}:2/2.
Sacrifice currently does not work in the “mana=” line, it would crash the game if you did that, but hopefully we’ll remove this limitation in the future.

When…comes into play, you may…

the may keyword is use to represent the text “When…comes into play, you may…”. This keyword is a bit experimental right now, but will be improved with time. For example, here is the code for Clone:

[card]
text=As Clone comes into play, you may choose a creature in play. If you do, Clone comes into play as a copy of that creature.
auto=may copy target(creature)
id=1193
name=Clone
rarity=U
color=Blue
type=Creature
mana={3}{U}
power=0
subtype=Shapeshifter
toughness=0
[/card]

alias

alias is used to reuse existing code, if you create a new card that has the same effects as an existing one. For example, Prodigal pyromancer (id 134752) has the same abilities as prodigal sorcerer (id 1217), so its card description could look like :

[card]
text={T}: Prodigal Pyromancer deals 1 damage to target creature or player.
id=134752
alias=1217
name=Prodigal Pyromancer
rarity=C
color=Red
type=Creature
mana={2}{R}
power=1
subtype=Human Wizard
toughness=1
[/card]

Note that alias copies the behavior of the card, but NOT its cost=, target=, abilities= lines ,or any other thing that describes the card. Only its special effects.
Use alias with care. The only time you can be 100% sure that it’s correct to use alias is when the card is a reprint of an existing card. For example, Hypnotic Specter 10E aliases to Hypnotic specter RV

Now, the best piece of advice I can give you is to look at the existing _cards.dat files and get inspiration from there. If you want to dig deeper, you can have a look at TargetChooser.cpp and MTGAbility.cpp in the source code.
Good luck !

36 Responses

  1. Incantus says:

    Hey, nice work with building a basic card parser. I was going along this route, but then as I built more complex cards I found I had to implement more and more of a programming language, so in the end I just decided to have all the cards be python code (to make implementing them consistent).

    So will your approach for more difficult abilities require actual C++ coding in the rules engine? Maybe you can wrap all the core pieces with a scripting language like Lua to make it easy to build complicated cards (i’ve been slowly trying to build a mini magic DSL). If I ever port my rules engine from python to a compiled language I’ll probably take this route.

  2. wololo says:

    Incantus, I couldn’t agree more with you.
    The parser started as a simple piece of code that allowed simple things such as “first strike” and within a few months it became more and more complex. The only reason I’m not switching to LUA for the parser is laziness, but I think it has to be done at some point.
    Incantus being in Python, I’m not sure you would have any benefit switching to LUA ? Both are scripting languages, after all…
    And yes, right now complex cards require C++, and that’s a pain :p

  3. Roly says:

    Wow, this is awesome, I am impressed. I have played Magic for 15 years and always enjoyed it. I have some totally great decks put together that are mindbending fun to play.

    I have not purchased card for a long time (since stronghold) and am well aware of how the game has changed.

    When do you plan to implement phasing (Mirage), and I have not checked but are there cards available that product creatures (Thallids, Serpent Generators, etc).

  4. wololo says:

    Tokens are not implemented yet but are on the “high priority” list.
    I don’t know what phasing is (I havent played since 4thEd), but if it’s only in one set it will have low priority.

  5. Roly says:

    Yeah, phasing was only in one set (like shadow, I think).

  6. MageKing17 says:

    Shadow wasn’t only in one set (it appears in Time Spiral). Mind you, it’s no longer in Standard (since Time Spiral was shifted out), but it’s still post-8th, and I’d be surprised if we didn’t see it show up again. I’m currently building a deck (in the real world!) around Shadow, and it includes both Tempest and Time Spiral cards.

    Also, it’s so fun to see how other programs implement cards. Usually, it gives us a chance to point an laugh and their incorrect (rules-wise) approaches :P. Firemox, for instance, had Sengir Vampire create a delayed trigger (it should use a memory variable), and Channel produce green mana (it should produce colorless).

    Like your Bayou having two tap abilities for mana.

    Technically, it does… and that’s the way we used to do it. It’s not, however, correct. Instead, the abilities should be intrinsic, as a result of it being a Swamp Forest. That’s why our code for adding subtypes has special stuff happen whenever a basic land type is added or removed.

  7. wololo says:

    Yeah, I like Incantus’ approach of having everything correct from the start, it is really promising. When I started working on Wagic, I knew after a few weeks that I wouldn’t have a perfect implementation, however my goal is not to have a perfect implementation, but rather a fun single player game. Working on the graphics, the audio effects, the shop system would have been a waste of time if I was building only a simulator. But I’m creating a game. It has its flaw regarding some rules in MTG, but on the other hand, it does its job pretty well in terms of fun which is what I am aiming for.

    Regarding the mana abilities, I’ve already discussed that with Incantus, and unless we start having cards that actually “count” abilities associated to a given card, I still believe it is strictly equivalent.

    However I’ll probably have to switch to something similar to what you guys do for the mana if I ever want a card such as conversion to work in Wagic. 🙂

  8. JayzenFreeze says:

    none of that made any sense i got the magic the gathering pc game i thought i could put the cards on to wagic but this description i dont under stand that looks like a looooot of work per card if i cant use my pc cards i dont want to play this bland color game please help

  9. nantuko says:

    hi
    is it possible to find out from _cards.dat files or from somewhere or other such cards that are implemented only using parser and auto keyword and not hard coded? or is it possible only by searching for evert card in MTGAbility.cpp?

  10. wololo says:

    Right now, you can only find by browsing in MTGAbility.cpp unfortunately

  11. nantuko says:

    I started creating antlr grammar for your script 😉
    http://mwars.blogspot.com/2009/09/wagic-script-grammar.html

  12. nantuko says:

    btw, why do you have
    auto={T}:damage:1 target(creature,player)
    and
    target=creature,player
    auto=damage:2

    (shock vs Prodigal Sorcerer)

    why do you need such difference?
    why not have just auto=damage:2 target(creature,player) for Shock as well?

  13. Tckaile says:

    i LOVE this program…i have recently tried to get back into magic from a 5 year break and i love the new Alara editions…i originally found this game in a torrent so just to let you know, you’re probably getting more downloads than you’re monitoring. I would also love to say that this game (even in it’s minor flaws) far exceeds anything that WotC have yet to bring out as far as single player games in my opinion and i would have paid for something like this…congrats on a job very well done

    Also, when might we see Planeswalker implementation or will we have to wait for a new coding language?

  14. wololo says:

    nantuko: this is some legacy code. target=… means the target of a spell
    auto =… target(…) is the target for an activated ability

  15. BlueEyes says:

    HI! I recently found this program and absolutely LOVE it! It started when I was cleaning out a closet and was like “OMG, my old MTG deck!!!” LOL. ANYWAYS, im not very good at programming (if at all), and was wondering if at any time you were planning on putting an ability called Affininty into the code. (If it is already im sry) I am asking this because I would like to try to implement my own personal deck into the Wagic database. Here is an example of one of my favorite cards in my deck:

    http://gatherer.wizards.com/Pages/Card/Details.aspx?printed=true&multiverseid=46556

    If this ability called Affinity is indeed already in your coding, maybe could I have an example of how to word this card? Much appreciated! TY!!!

  16. jonrayz says:

    I just wanna share what I found out.

    A post made by Oklahoma of http://www.pinoypsp.com

    LINK: http://pinoypsp.com/index.php?topic=214136.0

    Included here are the complete images of all the cards in Wagic 0.81.

    All credits goes to NytCrawler and Wololo.

  17. DanTegTo says:

    Great program and great tuto. I just find it and it’s amazing
    Two questions:

    in Cost description, is there any way to pay lives?
    Any chance to have the dredge or fading abilities in a next release?

    Thanks

  18. wololo says:

    There is a tricky way to pay lives: you can pay them as an effect. For example : auto={R}:destroy target(creature) && life:-1 controller

    This “works” because we don’t have cards that allow you to have negative life, so basically you can’t trick the game into not paying the life, even if it’s an effect rather than a cost.

    Regarding game mechanics, we add them as we see fit, mostly based on the number of cards that handle them. Join the forum if you’re interested in that kind of discussion 🙂

  19. NightmareOn says:

    why does the game allwas say “Please check your deck [not enough cards?] when i wim with “my cards”?

  20. wololo says:

    I’m not entirely sure.
    Can you send me your files collection.dat and deck1.txt (they are in the Res/player folder) by email at wagic.the.homebrew at gmail dotcom ? I’ll try to see if it’s a bug.

  21. LeSkoog says:

    THANK YOU!!!, OK so i used this guide and i am currently building a Halo deck from the popular video game by Bungie. I have just started and im up to 3 basic cards, elite jackal and grunt. tomorrow im going to add a lot more Covenant and start with the unsc deck. i have tested the cards and they do work perfectly. i figured out the deck1.txt the sets and the mtg files. thank you wololo and your team for building an amazing homebrew!

  22. 1HandPlay says:

    i made the cards correctly but they don’t show up?

  23. wololo says:

    @1HandPlay: you need to unlock the set you created, I think. Please ask on the forums if you have more issues, you will get way more help 🙂

  24. 1HandPlay says:

    ok my deck is unlocked and the game so hard including the xbox arcade version

  25. leontas2007 says:

    I am trying to add a card to the 10th edition folder but it isn’t working. What I am doing wrong:
    [card]
    text=test (test.)
    id=2310
    name=Earth Sorcerer
    rarity=C
    type=Creature
    mana={2}{G}
    power=2
    subtype=Wizard
    toughness=6
    [/card]

    Please help me!

  26. wololo says:

    @leontas2007: did you check that this id is not used by another card? 2310 looks like a 3rd or 4th edition card id. Try to use a different number, something between 1000000 and 10000000 will definitely work because it’s not used by WOTC yet

  27. leontas2007 says:

    @wololo: It works! Thank you very very very much. Now I have a problem with my images. PLEASE HELP ME(again)! I have images of my card but it not work….Thumbnail is 45×64px jpg
    and the picture is 200×285px jpg and they have the same id with my card. So where is the problem….?

  28. leontas2007 says:

    @wololo: I find a solution to my problem 🙂 I can’t make cards with images in v0.9.2 but in 1.21 version they work!!! THANK YOU SO MUCH for your help and THANK YOU VERY VERY VERY MUCH about that GREAT GAME!

  29. squeels56 says:

    hi i think your cool.dude

  30. Ygredviper says:

    My comment to Incantus was really meant to be here.

  1. December 9, 2008

    […] more info here […]

  2. February 23, 2009

    […] you’re not a programmer and want to help, remember that you can still add your own cards to the game, or change the graphics and sounds to create cool mods! If you don’t feel like a creative […]

  3. April 24, 2009

    […] just updated the create your own cards article to match Wagic 0.6.0. People who want to add their own cards to Wagic will want to read […]

  4. August 31, 2009

    […] I also have real information: I updated the “create your own cards” page with the latest information and abilities available in […]

Leave a Reply to jonrayz Cancel reply

Your email address will not be published. Required fields are marked *

Most comments are automatically approved, but in some cases, it might take up to 24h for your comments to show up on the site, if they need manual moderation. Thanks for your understanding