It is currently 25 Apr 2024, 11:35
   
Text Size

Cards with counters.

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

Re: Cards with counters.

Postby Rob Cashwalker » 08 Jan 2009, 18:50

Counters don't have functionality by themselves. They exist to be counted by other effects and game rules. They shouldn't need dedicated classes.

Don't forget, a +1/+1 counter is different than a +2/+2 counter. (they do exist, along with +1/+0 counters, -0/-1 counters, but they're rare now, Wizards said they won't use them anymore) And a -1/-1 counter will annihilate the +1/+1 counter, but won't affect the +2/+2, a -2/-2 counter would. The counter shouldn't modify the power/toughness directly.

There's nothing wrong with assigning "+1/+1" to the string for the counter type. If you want to get fancy, the add counter and get counter can convert them to all CAPS before actually being added to the list, so "Loyalty" is the same as "loyalty", which is the same as "LoYaLtY".

Hashtables are not intuitive to new programmers.... I've been programming for 14 years, but I don't know how they work or how to use them. But the string arrays are super simple.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Cards with counters.

Postby GandoTheBard » 08 Jan 2009, 19:52

As I understand them Hashtables make accessing otherwise hard to manage arrays much simpler and tons faster.

In javascript I use hashtables even for relatively small arrays (100 or so elements) because it really speeds up access time. The concept is fairly simple. Each element not only has an elemental number id but also has a unique id made up of its elemental id (usually) and often a string. This means you can call the contents of an array element [String + ElID] and instead of having to increment through a loop to access it can just provide the parts from passed parameters or object members. There is alot more to it but this is basically it in a nutshell and I imagine you know some of this already at least. I don't know whether it is a good idea however. I am not at all conversant with the code for MTGForge (I have glanced at some of the files in curiousity but thats it) so I have no way of knowing whether the hashtable is warranted here. But since it is Rare's project if you are introducing code it should be stuff he can grasp and utilize. Well that's my thinking anyway. That is to say I agree with you Rob. Strings (arrays of characters) are fairly easy to use and manipulate as are arrays of strings.
visit my personal homepage here: http://outofthebrokensky.com

Listen to my podcast with famed AJ_Impy "Freed from the Real" on http://puremtgo.com
User avatar
GandoTheBard
Tester
 
Posts: 1043
Joined: 06 Sep 2008, 18:43
Has thanked: 0 time
Been thanked: 0 time

Re: Cards with counters.

Postby Orpheu » 09 Jan 2009, 10:48

Hashtable essencially is a struct that index the key elements, in a larger array that wouldn't normally be required to contain that number of elements. This larger space occupied is compensated by his constante time acessing. What do I mean with constante time acess?

Imagine that you have a key element that is a string, "aa" for instance. What hashtable does is calculate using this key, the index of this element in a array. That hashfunction ( the real name of this index calculation ), can be for example the sum of all the ASCII code of the caracters contained by the string and then calculate the rest of the division of this number by the hashtable array size. Sounds dificult?

Lets see an example:

Let's imagine that we have our string "aa" has a key and that the ascii code of 'a' is 97, and that our hashtable is in fact a array with 80 positions of elements of the type <String,Integer>.

So by what I described what the computer will do is sum 97 for each 'a' in the string "aa", so will end up with 2 * 97 = 194. However this index doesn't really exist in our 80 positions array, so we need to convert this number in a such a way that we can garante that this index exist in this hashtable array. To do just that we take this number and get the rest of the division of this number by the array size. So we will find out the rest of the division of 194 by 80 and get 34. So if the element with the key "aa" exist in this hashtable, it will be in position 34.

This will be done each time we need to search, insert or remove an element that could be in the hashtable, allowing to skip the need to run the array one position at a time and save ALOT of the search time needed.

Obviously you can allways have what we call "collisions", because you have a potencially infinite domain in string and you are reducing this infinite domain to a [0...array size-1] domain. This can be solved using a list of collisions in each hashtable element. However this conlision list should be has reduced as possible, or else you will lose the advantage of using a hashtable, and will end up with a search in list problem, the one you are trying to avoid from the start. Normally the optimal hashtable occupacy is around 20% of the space available, so when you come very far from this value you will need to make the hashtable array grow and rehash all the items. However this is a very computer expensive process and should be avoid to use. Using this method it's clear that you will end up with a large amount of the positions in this array with no elements inside, and this is why the hashtable in terms of space is pretty inefficient, however in terms of acess time is trully unbeatable specially if you got millions of elements.

Luckly this is all implemented and optimized by the java guys, and we don't have to worry about this kind of things, but the key point of all this bla bla bla is to have some kind of ideia of what a hashtable is and why it should be prefered comparing to list option.
Orpheu
 
Posts: 25
Joined: 13 Dec 2008, 09:43
Has thanked: 0 time
Been thanked: 0 time

Re: Cards with counters.

Postby Rob Cashwalker » 09 Jan 2009, 15:21

and this is why the hashtable in terms of space is pretty inefficient, however in terms of acess time is trully unbeatable specially if you got millions of elements.
And ^This^ is why it should be a simple string array. Any given card object's counters array is going to be empty 99% of the time. That 1% of the time it'll have what, maybe up to 10 elements (planeswalker loyalty, primarily) very rarely much more than that.

Your original suggestion was to maintain the counters from an external object for all cards in play that have counters. In that case, sure, a hashtable would work to good advantage.

Besides, hash belongs in a pipe, and not in tables......... :rolleyes:
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Cards with counters.

Postby GandoTheBard » 09 Jan 2009, 15:53

Actually I prefer hash in my stomach or on my plate :D
visit my personal homepage here: http://outofthebrokensky.com

Listen to my podcast with famed AJ_Impy "Freed from the Real" on http://puremtgo.com
User avatar
GandoTheBard
Tester
 
Posts: 1043
Joined: 06 Sep 2008, 18:43
Has thanked: 0 time
Been thanked: 0 time

Re: Cards with counters.

Postby DennisBergkamp » 09 Jan 2009, 17:13

Besides, hash belongs in a pipe, and not in tables......... :rolleyes:
:lol:

By the way, Orpheu, have you implemented any new cards with counters yet, I'd love to add them into the next version :)
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Cards with counters.

Postby Orpheu » 09 Jan 2009, 17:20

Every single good Computer Engineer that has a problem with this description, that is given a key value getting the object, would say that you should use a hashtable. Trust me on this one. :)
Orpheu
 
Posts: 25
Joined: 13 Dec 2008, 09:43
Has thanked: 0 time
Been thanked: 0 time

Re: Cards with counters.

Postby Orpheu » 09 Jan 2009, 17:22

DennisBergkamp wrote:
Besides, hash belongs in a pipe, and not in tables......... :rolleyes:
:lol:

By the way, Orpheu, have you implemented any new cards with counters yet, I'd love to add them into the next version :)
No man. Alot of work to do... :( I promise that next week I will try to put at least one of them to work! :)
Orpheu
 
Posts: 25
Joined: 13 Dec 2008, 09:43
Has thanked: 0 time
Been thanked: 0 time

Re: Cards with counters.

Postby Incantus » 09 Jan 2009, 17:58

Rob Cashwalker wrote:
and this is why the hashtable in terms of space is pretty inefficient, however in terms of acess time is trully unbeatable specially if you got millions of elements.
And ^This^ is why it should be a simple string array. Any given card object's counters array is going to be empty 99% of the time. That 1% of the time it'll have what, maybe up to 10 elements (planeswalker loyalty, primarily) very rarely much more than that.
OK Rob, imagine a card has a fade counter, a +1/+1 counter, a +2/+2, and a +1/+0 counter. Using your array of strings approach, how would you calculate the power/toughness of this creature? Would you parse each counter string each time to see if it matches "+n/+m" and then add those values? Considering that SBEs check power/toughness a lot, this seems pretty inefficient and slow.

Although Orpheu, I'm not sure how your hashtable approach would work with my example either, unless you lumped all P/T modifying counters into one list in the hashtable (otherwise you would have to calculate all combinations of +n/+m to see if those counters exist on the card).
Incantus
DEVELOPER
 
Posts: 267
Joined: 29 May 2008, 15:53
Has thanked: 0 time
Been thanked: 3 times

Re: Cards with counters.

Postby GandoTheBard » 09 Jan 2009, 18:33

Yeah I think you still end up having to look up each counter and then calculate them enmass. So there would need to be a function to do that I think.
visit my personal homepage here: http://outofthebrokensky.com

Listen to my podcast with famed AJ_Impy "Freed from the Real" on http://puremtgo.com
User avatar
GandoTheBard
Tester
 
Posts: 1043
Joined: 06 Sep 2008, 18:43
Has thanked: 0 time
Been thanked: 0 time

Re: Cards with counters.

Postby Rob Cashwalker » 09 Jan 2009, 19:01

OK Rob, imagine a card has a fade counter, a +1/+1 counter, a +2/+2, and a +1/+0 counter. Using your array of strings approach, how would you calculate the power/toughness of this creature? Would you parse each counter string each time to see if it matches "+n/+m" and then add those values? Considering that SBEs check power/toughness a lot, this seems pretty inefficient and slow.
The card object has a method, getPower. Right now, it just returns the private member variable that stores this value. We would have to flesh out the card object power and toughness set/get methods to preserve the printed base values, while providing methods to allow the code to submit "boosts" (+ or -). Then all code references to modifying the power and toughness need to be changed to match those methods. Finally, the getPower method will add the printed value, the boosts aggregate value, and then count all counters. This way the "layers" are applied correctly, and the searching/counting only needs to be performed when some other code needs to know.

Truthfully, p/t counters open a huge can of worms. But providing the counters array structure now, opens up all the simpler uses of counters.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Cards with counters.

Postby Orpheu » 09 Jan 2009, 19:11

If I had to implement from scratch power up effects such as counter or enchantments, I would simply use "into play" method to power up all affected creatures, and another method to take away this effect when this counters or enchantments leave play.

For instance when I add a counter in addCounter function I would just check if this counter is a P/T counter and react accordingly. The reverse process would be applied in the removeCounter function. This way the only time I need to worry about acessing the hashTable/array/list/wtv, would be inserting, removing, or searching a counter, not to calculate power/Thougness values. This values would be at any time correct.
Orpheu
 
Posts: 25
Joined: 13 Dec 2008, 09:43
Has thanked: 0 time
Been thanked: 0 time

Re: Cards with counters.

Postby Orpheu » 11 Jan 2009, 23:54

Hi there! :)

I'm programming Mirrodin's Core Card. However I got stuck when i tryied to produce mana. How can i create 1 mana of any color when I remove a counter from this card? Any suggestions?

Code: Select all
if(cardName.equals("Mirrodin's Core"))
    {
       final Ability_Tap ability_add_counter = new Ability_Tap(card)
        {
          public String getStackDescription()
            {
              return "This card has "+(this.getSourceCard().getCounters(Counters.MANA)+1)+" counter";
            }
          
          public void resolve()
          {
            this.getSourceCard().addCounter(Counters.MANA,1);
          }
        };

        ability_add_counter.setDescription("Add Counter");
        ability_add_counter.setBeforePayMana(new Input_NoCost_TapAbility(ability_add_counter));
        card.addSpellAbility(ability_add_counter);
       
        final Ability_Tap ability_del_counter = new Ability_Tap(card)
        {   
           public String getStackDescription()
             {
               return "This card has "+(this.getSourceCard().getCounters(Counters.MANA)-1)+" counter";
             }
           
           public boolean canPlay(){
              return this.getSourceCard().getCounters(Counters.MANA)>=1;
           }
           
          public void resolve()
          {
            this.getSourceCard().subtractCounter(Counters.MANA,1);
          }
        };
       
        ability_del_counter.setDescription("Add Mana");
        ability_del_counter.setBeforePayMana(new Input_NoCost_TapAbility(ability_del_counter));
        card.addSpellAbility(ability_del_counter);
    }
Thanks alot! :)
Orpheu
 
Posts: 25
Joined: 13 Dec 2008, 09:43
Has thanked: 0 time
Been thanked: 0 time

Re: Cards with counters.

Postby Rob Cashwalker » 12 Jan 2009, 17:50

you can't, because MTGForge (v1) can't deal with a "mana pool". The only way you can do this is by hacking the function that interprets the keyword "tap: add _" search for it in the code.

We've discussed the possibility of hacking that code to interpret "pain: add _" to allow the current core set dual lands. My suggestion would be to hack that code to interpret "remctr: add _". But you'd have to use the following in card.txt:

Mirrodin's Core
0
Land
tap: Put a charge counter on Mirrodin's Core
tap: add 1
remctr: add W
remctr: add U
remctr: add B
remctr: add R
remctr: add G
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Cards with counters.

Postby Orpheu » 12 Jan 2009, 18:30

Hummm.... It's sounds like a little bit of a waste to use a keyword just to do this ability, but I buy that one... :)

How can I add a new keyword check then? That's the keyword handle class in run forge?
Orpheu
 
Posts: 25
Joined: 13 Dec 2008, 09:43
Has thanked: 0 time
Been thanked: 0 time

PreviousNext

Return to Forge

Who is online

Users browsing this forum: No registered users and 178 guests


Who is online

In total there are 178 users online :: 0 registered, 0 hidden and 178 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 178 guests

Login Form