It is currently 27 Apr 2024, 07:11
   
Text Size

Cantrips

Post MTG Forge Related Programming Questions Here

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

Cantrips

Postby Rob Cashwalker » 19 Jan 2010, 05:07

This is mainly for Chris, as he has been the unofficial updater for "Draw a card." additions in cards.txt for Cantrip spells.

While testing new spPumpTgt functionality, I ran into a few cantrip cards, which previously used the card text instead of the spell description.
The new approach to including the spell description in the keyword line, would leave only "Draw a card." in the card text. But it was appearing before the spell description.

So, I went to the horse's mouth and did what we should have done from the beginning - I modified Card.getText().
If the Instant or Sorcery includes "Draw a card." as a keyword, "Draw a card." is appended after the spell description.

cards.txt will need to be gone over to change "Cantrip" to "Draw a card." and the text changed accordingly. After I merge the new spPumpTgt code, a pump spell cantrip will look like this:
Code: Select all
Pump Draw Spell
1 G
Instant
no text
spPumpTgt:+3/+3
Draw a card.
Card.java
Code: Select all
  public String getText()
  {
    if(isInstant() || isSorcery())
    {
      String s = getSpellText();
      StringBuilder sb = new StringBuilder();
      sb.append(s);
     
      SpellAbility[] sa = getSpellAbility();
      for(int i = 0; i < sa.length; i++)
        sb.append(sa[i].toString() + "\r\n");
     
      // Cantrip -> Draw a card.
      if (getKeyword().contains("Draw a card."))
         s += "Draw a card.\r\n";

      return sb.toString();
    }
ComputerUtil.java
Code: Select all
final static public void playStack(SpellAbility sa)
  {
     if (canPayCost(sa))
     {
        if (AllZone.GameAction.isCardInZone(sa.getSourceCard(),AllZone.Computer_Hand))
             AllZone.Computer_Hand.remove(sa.getSourceCard());
    
    
        if (sa.getSourceCard().getKeyword().contains("Draw a card."))
               AllZone.GameAction.drawCard(sa.getSourceCard().getController());
        payManaCost(sa);
       
        AllZone.Stack.add(sa);
     }
    
  }
 
  final static public void playNoStack(SpellAbility sa)
  {
    if(canPayCost(sa))
    {
      if(sa.isSpell())
      {
       if (AllZone.GameAction.isCardInZone(sa.getSourceCard(),AllZone.Computer_Hand))
          AllZone.Computer_Hand.remove(sa.getSourceCard());
        //probably doesn't really matter anyways
        //sa.getSourceCard().comesIntoPlay(); - messes things up, maybe for the future fix this
      }

      if(sa instanceof Ability_Tap)
        sa.getSourceCard().tap();

      if (sa.getSourceCard().getKeyword().contains("Draw a card."))
         AllZone.GameAction.drawCard(sa.getSourceCard().getController());
     
      payManaCost(sa);
      sa.resolve();

      //destroys creatures if they have lethal damage, etc..
      AllZone.GameAction.checkStateEffects();
    }
  }//play()
Input_StackNotEmpty.java
Code: Select all
  public void selectButtonOK()
  {
    updateGUI();

    SpellAbility sa = AllZone.Stack.pop();
    Card c = sa.getSourceCard();

    if (sa.getSourceCard().getKeyword().contains("Draw a card."))
         AllZone.GameAction.drawCard(sa.getSourceCard().getController());
   

    final Card crd = c;
    if (sa.isBuyBackAbility())
    {
       c.addReplaceMoveToGraveyardCommand(new Command() {
         private static final long serialVersionUID = -2559488318473330418L;

         public void execute() {
            PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, crd.getController());
              AllZone.GameAction.moveTo(hand, crd);            
         }
       });
    }
   
    sa.resolve();
    AllZone.GameAction.checkStateEffects();

    //special consideration for "Beacon of Unrest" and other "Beacon" cards
    if((c.isInstant() || c.isSorcery())     &&
       (! c.getName().startsWith("Beacon")) &&
       (! c.getName().startsWith("Pulse")) &&
       !AllZone.GameAction.isCardRemovedFromGame(c)) //hack to make flashback work
    {
      if (c.getReplaceMoveToGraveyard().size() == 0)
         AllZone.GameAction.moveToGraveyard(c);
      else
         c.replaceMoveToGraveyard();
    }
   

    //update all zones, something things arent' updated for some reason
    AllZone.Human_Hand.updateObservers();
    AllZone.Human_Play.updateObservers();
    AllZone.Computer_Play.updateObservers();

    if(AllZone.InputControl.getInput() == this)
      AllZone.InputControl.resetInput();
  }
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: Cantrips

Postby Chris H. » 19 Jan 2010, 11:53

Thank you Rob. Yes, I had noticed the same thing. :)

I see that you merged this new code into the SVN late last night.

I will go through the cards.txt file and change the keyword over and I will also remove the "Draw a card." from the text description line.
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: Cantrips

Postby Rob Cashwalker » 19 Jan 2010, 12:31

Just a small task.... But a much cleaner implementation.
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: Cantrips

Postby Chris H. » 19 Jan 2010, 15:50

Ok, I have changed the cards.txt file over to the new format. There are several cards that have the cantrip hard coded, ex: Brainbite; Dismiss; Exclude; Opt; Remand; Repulse; Reviving Dose. I can take care of these later this week. :)


For some reason the "Draw a card." text string is not appearing in the deck editor for those cards with the new "Draw a card." keyword. I took a peak at the StringBuilder code in the Card.java file … What is happening?

I ran a test with a Zap deck and this spell will draw a card after it resolves, but I do not have the "Draw a card." text string displaying in the card detail panel. Strange.
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: Cantrips

Postby DennisBergkamp » 19 Jan 2010, 16:05

Change this line:

Code: Select all
         s += "Draw a card.\r\n";
to:

Code: Select all
        sb.append("Draw a card.\r\n");
I'm using a StringBuilder there, and returning sb.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Cantrips

Postby Chris H. » 19 Jan 2010, 17:11

DennisBergkamp wrote:Change this line:

Code: Select all
         s += "Draw a card.\r\n";
to:

Code: Select all
        sb.append("Draw a card.\r\n");
I'm using a StringBuilder there, and returning sb.
`
OK, I will give this a try and will merge this fix and the updated cards.txt file to the SVN sometime today. :)
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: Cantrips

Postby Chris H. » 19 Jan 2010, 18:38

Chris H. wrote:I will give this a try and will merge this fix and the updated cards.txt file to the SVN sometime today. :)
`
I tried the code change and then looked at all of the cards that were converted from the old cantrip keyword and most of them look great.

Several of the cards display "Draw a card." twice. It looks like the setText() command is being executed twice(?)

Cards that use the spDestroyTgt keyword and the spell Runeboggle are the cards impacted by the double printing of the "Draw a card." string. The other cards and keywords are OK. :)
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: Cantrips

Postby DennisBergkamp » 19 Jan 2010, 19:56

For Runeboggle and those other cards, just remove the "Draw a card." from the card's text in cards.txt:
Code: Select all
Runeboggle
2 U
Instant
Counter target spell unless its controller pays 1.
Draw a card.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Cantrips

Postby Chris H. » 19 Jan 2010, 20:55

Yeah, I have removed the Draw a card from the text line in the cards.txt file. The cards that are printing twice look like this now in cards.txt:

Code: Select all
Annihilate
3 B B
Instant
Destroy target nonblack creature. It can't be regenerated.
spDestroyTgt:Creature.nonBlack:NoRegen
Draw a card.

Aura Blast
1 W
Instant
Destroy target enchantment.
spDestroyTgt:Enchantment
Draw a card.

Execute
2 B
Instant
Destroy target white creature. It can't be regenerated.
spDestroyTgt:Creature.White:NoRegen
Draw a card.

Implode
4 R
Sorcery
Destroy target land.
spDestroyTgt:Land
Draw a card.

Runeboggle
2 U
Instant
Counter target spell unless its controller pays 1.
Draw a card.

Slay
2 B
Instant
Destroy target green creature. It can't be regenerated.
spDestroyTgt:Creature.Green:NoRegen
Draw a card.

Smash
2 R
Instant
Destroy target artifact.
spDestroyTgt:Artifact
Draw a card.
`
The code for the cards above are calling setText twice and therefore are getting the test for the keyword performed twice. I modified the test and it now only prints the "Draw a card." once. This one stretched my brain. :wink:

The cards above now print the "Draw a card." on the same line as the spell description. The text for Annihilate looks like this now:

Code: Select all
Destroy target nonblack creature. It can't be regenerated.Draw a card.
`
We are almost there, the code in question now looks like this:

Code: Select all
if (getKeyword().contains("Draw a card.") && ! sb.toString().endsWith("Draw a card.\r\n\r\n"))
    sb.append("Draw a card.\r\n");
`
I think that we need to strip off the "Draw a card.\r\n" and then add it back on. I may figure out how to do this. :mrgreen:
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: Cantrips

Postby Rob Cashwalker » 19 Jan 2010, 21:11

DennisBergkamp wrote:Change this line:

Code: Select all
         s += "Draw a card.\r\n";
to:

Code: Select all
        sb.append("Draw a card.\r\n");
I'm using a StringBuilder there, and returning sb.
OK, I don't know how that sneaked itself back in there, because I thought I DID change that to sb.append.
When I first went to update Card.java, I got conflicts because of the change to StringBuilder. I went through, using the conflict comparison view, and it seemed like I made all the right changes. Then when I went to update again, all of my changes were reverted to my original changes (using s +=). I went through the conflict merge again, and then tried a commit, which complained about unresolved conflicts.... But my code and the SVN code looked the same, except for the three added lines (which had been changed to use sb).
I then looked at the Team menu and found a resolve conflicts function, and told it to use my copy to resolve conflicts, then I was allowed to commit it.

How that s+= got back in, is like figuring out how an elephant got into my pajamas....
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: Cantrips

Postby DennisBergkamp » 19 Jan 2010, 21:33

SVN craziness :rolleyes:
I've seen some weird things happen too when using it.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Cantrips

Postby Chris H. » 19 Jan 2010, 23:35

Chris H. wrote:I think that we need to strip off the "Draw a card.\r\n" and then add it back on. I may figure out how to do this. :mrgreen:
`
I found a way to implement my idea of stripping off the first "Draw a card.\r\n" that is printed. The current SVN r282 is good to go.

This is the final version of the code:

Code: Select all
if (getKeyword().contains("Draw a card."))
{
  if (sb.toString().endsWith("Draw a card.\r\n\r\n"))
  {
      sb.delete(sb.toString().length() - 16, sb.toString().length() - 2);
  }
  sb.append("Draw a card.\r\n");
}
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: Cantrips

Postby Rob Cashwalker » 20 Jan 2010, 00:53

I'm not too keen on that code.

I'd be more comfortable with:
Code: Select all
if (getKeyword().contains("Draw a card.") && !sb.toString().contains("Draw a card."))
  sb.append("Draw a card.\r\n");
Bad habit to be tied to the exact pattern with all the "\r\n"'s and the 16 characters....
Basically, it only matters that if the text already includes "Draw a card." then don't add it again.
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: Cantrips

Postby silly freak » 20 Jan 2010, 13:19

hardcodend string lengths are no good...
Code: Select all
    if (getKeyword().contains("Draw a card."))
    {
      String drawCard = "Draw a card.\r\n\r\n";
      if (sb.toString().endsWith(drawCard))
      {
          sb.delete(sb.toString().length() - drawCard.length(), sb.toString().length() - 2);
      }
      sb.append("Draw a card.\r\n");
    }
...better! but then again, the response from above. but remember it for other cases. I remember this being a problem previously in a keyword...
___

where's the "trust me, that will work!" switch for the compiler?
Laterna Magica - blog, forum, project, 2010/09/06 release!
silly freak
DEVELOPER
 
Posts: 598
Joined: 26 Mar 2009, 07:18
Location: Vienna, Austria
Has thanked: 93 times
Been thanked: 25 times

Re: Cantrips

Postby Rob Cashwalker » 21 Jan 2010, 00:52

Dennis - when you made this method for the counterspells,
why did you include a Cantrip check? The spellability is added to the stack in this code, but it hasn't been resolved yet. The Cantrip (and now the scry code I'm adding) should execute only after the spellability.resolve method is executed.

From ComputerUtil.java:
Code: Select all
//this is used for AI's counterspells
  final static public void playStack(SpellAbility sa)
  {
     if (canPayCost(sa))
     {
        if (AllZone.GameAction.isCardInZone(sa.getSourceCard(),AllZone.Computer_Hand))
             AllZone.Computer_Hand.remove(sa.getSourceCard());
    
    
        if (sa.getSourceCard().getKeyword().contains("Draw a card."))
               AllZone.GameAction.drawCard(sa.getSourceCard().getController());
        payManaCost(sa);
       
        AllZone.Stack.add(sa);
     }
    
  }
This is the changed section in playNoStack:
Code: Select all
  final static public void playNoStack(SpellAbility sa)
  {
    if(canPayCost(sa))
    {
      if(sa.isSpell())
      {
       if (AllZone.GameAction.isCardInZone(sa.getSourceCard(),AllZone.Computer_Hand))
          AllZone.Computer_Hand.remove(sa.getSourceCard());
        //probably doesn't really matter anyways
        //sa.getSourceCard().comesIntoPlay(); - messes things up, maybe for the future fix this
      }

      if(sa instanceof Ability_Tap)
        sa.getSourceCard().tap();
     
      payManaCost(sa);
      sa.resolve();

      if (sa.getSourceCard().getKeyword().contains("Draw a card."))
           AllZone.GameAction.drawCard(sa.getSourceCard().getController());

      for (int i=0; i<sa.getSourceCard().getKeyword().size(); i++)
      {
         String k = sa.getSourceCard().getKeyword().get(i);
         if (k.startsWith("Scry"))
         {
            String kk[] = k.split(" ");
            AllZone.GameAction.scry(sa.getSourceCard().getController(), Integer.parseInt(kk[1]));
         }
      }

      //destroys creatures if they have lethal damage, etc..
      AllZone.GameAction.checkStateEffects();
    }
  }//play()
Similar change in Input_StackNotEmpty:
Code: Select all
  public void selectButtonOK()
  {
    updateGUI();

    SpellAbility sa = AllZone.Stack.pop();
    Card c = sa.getSourceCard();

    final Card crd = c;
    if (sa.isBuyBackAbility())
    {
       c.addReplaceMoveToGraveyardCommand(new Command() {
         private static final long serialVersionUID = -2559488318473330418L;

         public void execute() {
            PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, crd.getController());
              AllZone.GameAction.moveTo(hand, crd);            
         }
       });
    }
   
    sa.resolve();
   
    if (sa.getSourceCard().getKeyword().contains("Draw a card."))
         AllZone.GameAction.drawCard(sa.getSourceCard().getController());
   
    for (int i=0; i<sa.getSourceCard().getKeyword().size(); i++)
    {
       String k = sa.getSourceCard().getKeyword().get(i);
       if (k.startsWith("Scry"))
       {
          String kk[] = k.split(" ");
          AllZone.GameAction.scry(sa.getSourceCard().getController(), Integer.parseInt(kk[1]));
       }
    }
   
    AllZone.GameAction.checkStateEffects();

    //special consideration for "Beacon of Unrest" and other "Beacon" cards
    if((c.isInstant() || c.isSorcery())     &&
       (! c.getName().startsWith("Beacon")) &&
       (! c.getName().startsWith("Pulse")) &&
       !AllZone.GameAction.isCardRemovedFromGame(c)) //hack to make flashback work
    {
      if (c.getReplaceMoveToGraveyard().size() == 0)
         AllZone.GameAction.moveToGraveyard(c);
      else
         c.replaceMoveToGraveyard();
    }
   

    //update all zones, something things arent' updated for some reason
    AllZone.Human_Hand.updateObservers();
    AllZone.Human_Play.updateObservers();
    AllZone.Computer_Play.updateObservers();

    if(AllZone.InputControl.getInput() == this)
      AllZone.InputControl.resetInput();
  }
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

Next

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 80 guests


Who is online

In total there are 80 users online :: 0 registered, 0 hidden and 80 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 80 guests

Login Form