Cantrips
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
Cantrips
by 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:
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.
- 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();
}
- 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()
- 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.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Cantrips
by 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.
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.
-
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
by Rob Cashwalker » 19 Jan 2010, 12:31
Just a small task.... But a much cleaner implementation.
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Cantrips
by 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.
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.
-
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
by DennisBergkamp » 19 Jan 2010, 16:05
Change this line:
- Code: Select all
s += "Draw a card.\r\n";
- Code: Select all
sb.append("Draw a card.\r\n");
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Cantrips
by Chris H. » 19 Jan 2010, 17:11
`DennisBergkamp wrote:Change this line:to:
- Code: Select all
s += "Draw a card.\r\n";
I'm using a StringBuilder there, and returning sb.
- Code: Select all
sb.append("Draw a card.\r\n");
OK, I will give this a try and will merge this fix and the updated cards.txt file to the SVN sometime today.
-
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
by 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.
-
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
by 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.
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Cantrips
by 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:
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.
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:
We are almost there, the code in question now looks like this:
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.
- 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.
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.
-
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
by Rob Cashwalker » 19 Jan 2010, 21:11
OK, I don't know how that sneaked itself back in there, because I thought I DID change that to sb.append.DennisBergkamp wrote:Change this line:to:
- Code: Select all
s += "Draw a card.\r\n";
I'm using a StringBuilder there, and returning sb.
- Code: Select all
sb.append("Draw a card.\r\n");
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.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Cantrips
by DennisBergkamp » 19 Jan 2010, 21:33
SVN craziness
I've seen some weird things happen too when using it.
I've seen some weird things happen too when using it.
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Cantrips
by 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.
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");
}
-
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
by Rob Cashwalker » 20 Jan 2010, 00:53
I'm not too keen on that code.
I'd be more comfortable with:
Basically, it only matters that if the text already includes "Draw a card." then don't add it again.
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");
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.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Cantrips
by 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");
}
___
where's the "trust me, that will work!" switch for the compiler?
Laterna Magica - blog, forum, project, 2010/09/06 release!
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
by 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:
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);
}
}
- 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()
- 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.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
19 posts
• Page 1 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 80 guests