Page 4 of 4

Re: spRaiseDead

PostPosted: 25 Oct 2009, 19:18
by Chris H.
I felt that the name of this keyword was too long with too many characters. This keyword is based on the code from the Raise Dead spell. So, In a moment of creativity, I decided that I would rename this keyword:

spRaiseDead

Re: spRaiseDead

PostPosted: 25 Oct 2009, 19:20
by Chris H.
silly freak wrote:the mystery is now solved... it turns out that the changeling spells are missing "Tribal" in cards.txt

i'm correcting this, and will commit the file
`
I just checked this out by editing my keyword back to:

list = list.getType(targetTypeToReturn);

and I changed:

Nameless Inversion
1 B
Tribal Instant Shapeshifter
Changeling. Target creature gets +3/-3 until end of turn.
Changeling


And it works, thank you. That was a great catch! 8) =D>

It looks like there are a few other Tribal spells that do not have changeling and also has the incomplete Type line.

Re: spRaiseDead

PostPosted: 25 Oct 2009, 20:48
by Chris H.
I have a question for the rules experts. The Ramosian Lieutenant can currently use it's ability to "4, tap: Search your library for a Rebel permanent card with converted mana cost 3 or less and put it into play." and the list will display the new spell "Bound in Silence".

Is this a correct ruling? Note that the Bound in Silence spell looks like this in the cards.txt file:

Bound in Silence
2 W
Tribal Enchantment Rebel Aura
Enchanted creature can't attack or block.
Enchant creature


Does this mean we should update all of the other existing Tribal cards and make sure that they include the full type line of designations?

Re: spReturnGraveyardHandCreature

PostPosted: 25 Oct 2009, 21:17
by Sloth
Chris H. wrote:Is this a correct ruling?
Yes. This is how it should be, according to the rules of MtG.

Chris H. wrote:Does this mean we should update all of the other existing Tribal cards and make sure that they include the full type line of designations?
Since the goal of MtG Forge should be to be as close to the paper game, I would say yes. (Even if it would mean that some bugs with individual cards will appear and need to be fixed).

Re: spRaiseDead

PostPosted: 25 Oct 2009, 21:34
by Chris H.
Sloth wrote:Yes. This is how it should be, according to the rules of MtG.

Since the goal of MtG Forge should be to be as close to the paper game, I would say yes. (Even if it would mean that some bugs with individual cards will appear and need to be fixed).
`
OK, sounds good to me. I want to see what Dennis has to say.

He has added a lot of code over the last year and may be in the best position to determine if correcting the Tribal spells would cause a problem.

If Dennis agrees with this, I can finish the coding for my keyword and I can provide a list of Tribal spells for correction.

Re: spReturnGraveyardHandCreature

PostPosted: 25 Oct 2009, 22:11
by DennisBergkamp
Yeah, sure, sounds good to me. Also, Tarmogoyf uses Tribal as a type to count for it's P/T.

Re: spRaiseDead

PostPosted: 25 Oct 2009, 22:20
by Chris H.
DennisBergkamp wrote:Yeah, sure, sounds good to me. Also, Tarmogoyf uses Tribal as a type to count for it's P/T.
`
Great, I should be able to get the code and cards.txt changes up on this forum before I go to sleep tonight.

Re: spRaiseDead

PostPosted: 25 Oct 2009, 22:49
by Chris H.
Silly Freak mentioned that he planned to update the Tribal spells and commit them to the SVN. It is possible that he may have already made these changes.

One Tribal spell that I will not list below is Lignify. This spell is buggy and I do not know what to do about it.

The Tribal card corrections:

Code: Select all
Bitterblossom
1 B
Tribal Enchantment Faerie
At the beginning of your upkeep, you lose 1 life and put a 1/1 black Faerie Rogue creature token with flying into play.

Crib Swap
2 W
Tribal Instant Shapeshifter
Changeling. Remove target creature from the game. Its controller puts a 1/1 colorless Shapeshifter creature token into play.
Changeling

Feudkiller's Verdict
4 W W
Tribal Sorcery Giant
You gain 10 life. Then if you have more life than an opponent, put a 5/5 white Giant Warrior creature token into play.

Morsel Theft
2 B B
Tribal Sorcery Rogue
Target player loses 3 life and you gain 3 life. (NOTE: "Prowl" is not implemented.)
spLoseLifeGainLife:3

Nameless Inversion
1 B
Tribal Instant Shapeshifter
Changeling. Target creature gets +3/-3 until end of turn.
Changeling

Reach of Branches
4 G
Tribal Instant Treefolk
Put a 2/5 green Treefolk Shaman creature token into play.  Whenever a Forest comes into play under your control, you may return Reach of Branches from your graveyard to your hand.

Wings of Velis Vel
1 U
Tribal Instant Shapeshifter
Changeling. Target creature becomes 4/4 and gains flying until end of turn.
Changeling

Re: spReturnGraveyardHandCreature

PostPosted: 25 Oct 2009, 23:51
by silly freak
i only corrected the three changeling spells. I thought they were the only ones, because Tarfire had it. I assumed that it was right for all the non-changelings

Re: spRaiseDead

PostPosted: 26 Oct 2009, 00:43
by Chris H.
silly freak wrote:i only corrected the three changeling spells. I thought they were the only ones, because Tarfire had it. I assumed that it was right for all the non-changelings
`
Thank you for the help. :)

I had not realized that the missing types from the Tribal spells would cause a problem.

Re: spRaiseDead

PostPosted: 26 Oct 2009, 00:45
by Chris H.
@ Dennis:


You can comment out the "Raise Dead" code block.

There are currently four spells cards using the "Raise Dead" code and they can be converted to this keyword. I renamed this keyword, so you should use these instead:

Code: Select all
Disentomb
B
Sorcery
no text
spRaiseDead:1

Raise Dead
B
Sorcery
no text
spRaiseDead:1

Recover
2 B
Sorcery
Draw a card.
spRaiseDead:1
Cantrip

Return to Battle
B
Sorcery
no text
spRaiseDead:1
`
This is the code:

Code: Select all
   // spRaiseDead
   private final int shouldSpRaiseDead(Card c){
       ArrayList<String> a = c.getKeyword();
       for (int i = 0; i < a.size(); i++)
          if (a.get(i).toString().startsWith("spRaiseDead"))
             return i;
       
       return -1;
   }
`
Code: Select all
   //Spell Return target creature card from your graveyard to your hand (like Raise Dead)
   if (shouldSpRaiseDead(card)  != -1)
   {
      int n = shouldSpRaiseDead(card);
      if (n != -1)
      {
         String parse = card.getKeyword().get(n).toString();
         card.removeIntrinsicKeyword(parse);
         String k[] = parse.split(":");         // charm descriptions will appear at k[2] and k[3]
         final String kk[] = k[1].split("/");   // numCreatures = kk[0], other fields = kk[1] through kk[2]
         int numFieldsKK = kk.length;
         final int numCreatures = Integer.parseInt(kk[0]);
         boolean quantifier = false;
         String tmpTgt = "Creature";
         
         for (int i=2; i<=numFieldsKK; i++)
         {
            if (kk[(i-1)].equals ("Some"))
            {
               quantifier = true;
            }
            else   // can only be a specific creature type at his time, Goblin for goblin creatures and Tarfire
            {
               tmpTgt = kk[i-1];
            }
         }
         
         final String targetTypeToReturn = tmpTgt;
         final boolean weReturnUpTo = quantifier;
         final String spDesc[] = {"none"};
         final String stDesc[] = {"none"};
         
         if (k.length > 2)
            spDesc[0] = k[2];
         if (k.length > 3)
            stDesc[0] = k[3];
         
         final SpellAbility spell = new Spell(card)
         {
            private static final long serialVersionUID = 6938982619919149188L;
            public boolean canPlayAI() {return getGraveCreatures().size() >= numCreatures;}

            CardList targets;
            public void chooseTargetAI()
            {
               CardList grave = getGraveCreatures();
               targets = new CardList();
               
               if (targetTypeToReturn.equals ("Creature"))
               {
                  for (int i=0; i<numCreatures; i++)
                  {
                     Card c = CardFactoryUtil.AI_getBestCreature(grave);
                     targets.add(c);
                     grave.remove(c);
                  }
               }
               else      // this is for returning Goblins and Tarfire (and Changelings ?)
               {
                  for (int i=0; i<numCreatures; i++)
                  {
                     Card c = CardFactoryUtil.getRandomCard(grave);      // getRandomCard(grave);
                     targets.add(c);
                     grave.remove(c);
                  }
               }
            }

            public void resolve()
            {
               if (card.getController().equals(Constant.Player.Human))
               {
                  CardList grave = getGraveCreatures();
                  targets = new CardList();
                  
                  if (weReturnUpTo)      // this is for spells which state Return up to X target creature card
                  {
                     for (int i=0; i<numCreatures ; i++)
                     {
                        Card c = AllZone.Display.getChoiceOptional("Select card", grave.toArray());
                        targets.add(c);
                        grave.remove(c);
                     }
                  }
                  
                  else if (grave.size() > numCreatures)      // this is for spells which state Return target creature card
                     for (int i=0; i<numCreatures ; i++)
                     {
                        Card c = AllZone.Display.getChoice("Select card", grave.toArray());
                        targets.add(c);
                        grave.remove(c);
                     }
                  else targets = grave;
               }

               PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController());
               PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController());
               for (Card c : targets)
                  if (AllZone.GameAction.isCardInZone(c, grave))
                     AllZone.GameAction.moveTo(hand, c);
            }//resolve()
            
            public boolean canPlay()
            {
               return getGraveCreatures().size() >= numCreatures;
            }
            
            CardList getGraveCreatures()
            {
               PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController());
               CardList list = new CardList(grave.getCards());
               String cardController = card.getController();
               
               if (cardController.equals ("Human") || (cardController.equals ("Computer")) && (targetTypeToReturn.equals ("Creature")))
               {
                  list = list.getType(targetTypeToReturn);
               }
               else   // prevent the computer from using a Boggart Birth Rite to return a Boggart Birth Rite
               {
                  CardList tempList = new CardList(grave.getCards());
                  tempList = list.getType(targetTypeToReturn);
                  list = new CardList();
                  for (int i=0; i<tempList.size(); i++)
                  {
                     if (! cardName.equals (tempList.get(i).getName()))
                     {
                        list.add(tempList.get(i));
                     }
                  }
               }
               return list;
            }
         };//SpellAbility
         
         if (spDesc[0].equals("none"))   // create the card descriptiopn
         {
            spDesc[0] = ("Return ");
            if (weReturnUpTo)
            {   spDesc[0] = (spDesc[0] + "up to ");   }
            if (numCreatures > 1)
            {   spDesc[0] = (spDesc[0] + numCreatures + " ");   }
            spDesc[0] = (spDesc[0] + "target ");
            if (targetTypeToReturn.equals ("Creature"))
            {   spDesc[0] = (spDesc[0] + "creature");   }
            else
            {   spDesc[0] = (spDesc[0] + targetTypeToReturn);   }
            if (numCreatures > 1)
            {   spDesc[0] = (spDesc[0] + "s");   }
            spDesc[0] = (spDesc[0] + " card");
            if (numCreatures > 1)
            {   spDesc[0] = (spDesc[0] + "s");   }
            spDesc[0] = (spDesc[0] + " from your graveyard to your hand.");
         }
         
         if (stDesc[0].equals("none"))   // create the card stack descriptiopn
         {
            stDesc[0] = (card.getName() + " - returns target card");
            if (numCreatures > 1)
            {   stDesc[0] = (stDesc[0] + "s");   }
            stDesc[0] = (stDesc[0] + " from " + card.getController() + "'s graveyard to " + card.getController() + "'s hand.");
         }
         
         spell.setDescription(spDesc[0]);
         spell.setStackDescription(stDesc[0]);
         card.clearSpellAbility();
         card.addSpellAbility(spell);
      }
   }// spRaiseDead

Re: spReturnGraveyardHandCreature

PostPosted: 26 Oct 2009, 21:19
by DennisBergkamp
Nice, I've merged this and also tested it, good job Chris :)

Re: spRaiseDead

PostPosted: 26 Oct 2009, 21:54
by Chris H.
DennisBergkamp wrote:Nice, I've merged this and also tested it, good job Chris :)
`
Thank you, Dennis.