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

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 playartifact,enchantment any artifact or enchantment in play*|graveyard any card in any graveyardcreature,player any creature or player in playmountains one or more mountains in playartifact,enchantment|mygraveyard any artifact or enchantment in your graveyardcreature[-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:

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}:]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 :

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:

@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 :

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

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.

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

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.

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. 🙂

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

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?

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?

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:

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!

@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

@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….?

@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!

Archives

Disclaimer: Wololo.net is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to Amazon.com