Welcome to TCG Creation, where you can ask questions and receive answers from other members of the community.

Alternatives for storing cards

3 like 0 dislike

As we want in the future for users to create their own cards, and we want to support many kinds of cards, the question is:

How should we store card information?

This is about both storing regular properties such as card name, attack/health, creature type, etc. but also about storing abilities/effects, such as "At the end of your turn, deal 2 damage to a random enemy B0T"

Note that this is only related to how it should be stored, no matter how it is stored it would be possible for us to write a tool for users to create cards easier.

asked Oct 8, 2014 by SimonAndréForsberg (2,670 points)
edited Oct 8, 2014 by SimonAndréForsberg

6 Answers

2 like 0 dislike
XML or JSON

Example:

<card>
<name>Super Card</name>
<description>Some interesting text</description>
<triggers>
   <trigger>
        <event>PhaseEndedEvent</event>
        <condition>javaReference::isMyEvent</condition>
        <action>
            <ref>javaReference::damage</ref>
            <parameter>2</parameter>
            <target>
                  <ref>javaReference::random</ref>
                  <condition>javaReference::isEnemyB0T</condition>
            </target>
        </action>
   </trigger>
</triggers>
</card>

Pros: Easy to use, good support in Jackson

Cons: Needs to have references to method and/or class names inside the data structure, will be very sensitive to refactoring. You can't change the name of a method without something breaking. As logic cannot be implemented directly into the XML, it *will need references to actual code*.
answered Oct 8, 2014 by SimonAndréForsberg (2,670 points)
0 like 0 dislike
Write Code

Pros: Easy to integrate, is the closest to what we already have
Cons: Harder to change, needs at least some degree of programming skill
answered Oct 8, 2014 by SimonAndréForsberg (2,670 points)
0 like 0 dislike
Parsing Strings (possibly with regex)

The easy parts of the card can be stored as XML or JSON, while the advanced actions / triggers is stored as a simple string and then parsed by our program:

<card>
<name>Super Card</name>
<description>Some interesting text</description>
<values>
    <attack>1</attack>
    <health>3</health>
    <manaCost>4</manaCost>
</values>
<cardFeatures>At the end of your turn, deal 2 damage to an enemy B0T</cardFeatures>
</card>

I am thinking that the string "At the end of your turn, deal 2 damage to an enemy B0T" can be parsed like this:

"At [event], [action]"
Where [event] is "the end of [your] turn"
And action: "deal [x] damage to [target]"

Pros: Probably the easiest to read. Easiest to export as a card list, as the description of the card is already there.
Cons: Needs validation to make sure the string is correct. Need to make a parser to parse such a string and make it executable game logic.
answered Oct 8, 2014 by SimonAndréForsberg (2,670 points)
0 like 0 dislike

DBMS / SQLite

SELECT name, description, FROM CardShifter.Cards;

Pros: Easy to maintain if the application code changes. Fast even with very large amount of data.

Cons: Has to connect to a central DB, or in the case of SQLite, be bundled with the application. Less flexible than XML / JSON. Cannot have any game logic stored other than references to actual code.

answered Oct 8, 2014 by Phrancis (1,920 points)
0 like 0 dislike

A variant of XML / JSON.

Thanks to a `Consumer<Entity>` interface, implementation of the features themselves can be done in a method that returns a `Consumer<Entity>`, this method can take some parameters for the details themselves, so a card could be for example the following: (this will be the same card as in my previous XML/JSON answer)

The ability is "At the end of your turn, deal 2 damage to a random enemy B0T"

<card>

<name>Super Card</name>

<description>Some interesting text</description>

<abilities>

    <ability method="Triggers.atEndOfTurn">

         <parameter method="Effects.damageToTarget">

               <parameter>2</parameter>

               <parameter method="toRandom">

                      <parameter method="Filters.and">

                            <parameter method="Filters.isEnemy" />

                            <parameter method="Filters.isCreatureType">

                                   <parameter>B0T</parameter>

                            </parameter>

                     </parameter>

               </parameter>

          </parameter>

    </ability>

</abilities>

The following methods would then be used:

Consumer<Entity> atEndOfTurn(Consumer<Entity> effect);

Consumer<Entity> damagetoTarget(int damage, BiPredicate<Entity, Entity> filter);

BiPredicate<Entity, Entity> and(BiPredicate<Entity, Entity> filter1, BiPredicate<Entity, Entity> filter2);

BiPredicate<Entity, Entity> isEnemy();

BiPredicate<Entity, Entity> isCreatureType(String creatureType);

Then these parameters and methods are used using reflection.

Or, if you would make one method to do everything, simply:

<card>

<name>Super Card</name>

<description>Some interesting text</description>

<abilities>

    <ability method="deal2damageToRandomEnemyBotAtEndOfTurn" />

</abilities>
</card>
answered Feb 8, 2015 by SimonAndréForsberg (2,670 points)
edited Feb 8, 2015 by SimonAndréForsberg
0 like 0 dislike

I finished making my own JS card loader where cards can be loaded like the following:

 

{
    name: "Ragnaros",
    attack: 8,
    hitpoints: 8,
    keywords: ["cant_attack"],
    onMainPhaseEnd: function (game, event) {
        game.opponent().characters().pickRandom(1).dealDamage(8);
    }
}

 

It's really nothing more than a JavaScript object.

You can define the resources/attributes as expected, and effects can be defined as callbacks into already existing Java events. An example here is the PhaseEndEvent.

answered Mar 13, 2015 by skiwi (500 points)
...