spDiscard[Tgt|Opp]
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
25 posts
• Page 1 of 2 • 1, 2
spDiscard[Tgt|Opp]
by Rob Cashwalker » 09 Jul 2010, 11:49
Finally assembled this keyword.. I had begun working on it a couple months ago.
Right now it only handles basic discards, where the targeted player or opponent chooses. The reveal and choose type are next, and will be part of the same keyword.
Syntax:
Right now it only handles basic discards, where the targeted player or opponent chooses. The reveal and choose type are next, and will be part of the same keyword.
Syntax:
- Code: Select all
spDiscard[Tgt|Opp]:[TgtChoose|OppChoose|AtRandom|Hand]:<numCards>:<Drawback:Spell Description:StackDescription>
- Code: Select all
if (hasKeyword(card, "spDiscard") != -1)
{
int n = hasKeyword(card, "spDiscard");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean Tgt = k[0].contains("Tgt");
final boolean Opp = k[0].contains("Opp");
final String DiscardMethod = k[1];
final int NumCards[] = {-1138};
final String NumCardsX[] = {"none"};
final String UnlessType[] = {"none"};
if (k[2].length() > 1)
{
String kk[] = k[2].split("/");
if (kk[1].startsWith("UnlessDiscardType"))
{
String jk[] = kk[1].split("\\.");
UnlessType[0] = jk[1];
}
}
else if (k[2].matches("X"))
{
String xy = card.getSVar(k[2]);
if (xy.startsWith("Count$"))
{
String kk[] = xy.split("\\$");
NumCardsX[0] = kk[1];
}
}
else if (k[2].matches("[0-9]"))
{
NumCards[0] = Integer.parseInt(k[2]);
}
final String Drawback[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if (k[3].contains("Drawback$"))
{
String kk[] = k[3].split("\\$");
Drawback[0] = kk[1];
if (k.length > 4) spDesc[0] = k[4];
if (k.length > 5) stDesc[0] = k[5];
}
else
{
if (k.length > 3) spDesc[0] = k[3];
if (k.length > 4) stDesc[0] = k[4];
}
SpellAbility spDiscard = new Spell(card)
{
private static final long serialVersionUID = 837472987492L;
private int getNumCards() {
if(NumCards[0] != -1138) return NumCards[0];
if(!NumCardsX[0].equals("none")) return CardFactoryUtil.xCount(card, NumCardsX[0]);
return 0;
}
public boolean canPlayAI()
{
int nCards = getNumCards();
PlayerZone pzH = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Human);
int numHHand = pzH.size();
if (numHHand > (nCards - 1))
return true;
return false;
}
public void resolve()
{
int nCards = getNumCards();
if (DiscardMethod.equals("OppChoose"))
{
String opp = AllZone.GameAction.getOpponent(card.getController());
if (!UnlessType[0].equals("none"))
AllZone.GameAction.discardUnless(opp, nCards, UnlessType[0]);
else
AllZone.GameAction.discard(opp, nCards);
}
else if (DiscardMethod.equals("TgtChoose"))
{
if (!UnlessType[0].equals("none"))
AllZone.GameAction.discardUnless(getTargetPlayer(), nCards, UnlessType[0]);
else
AllZone.GameAction.discard(getTargetPlayer(), nCards);
}
else if (DiscardMethod.equals("AtRandom"))
{
AllZone.GameAction.discardRandom(getTargetPlayer(), nCards);
}
else if (DiscardMethod.equals("Hand"))
{
AllZone.GameAction.discardHand(getTargetPlayer());
}
if (!Drawback[0].equals("none"))
{
CardFactoryUtil.doDrawBack(Drawback[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), card.getController(), card, card);
}
}
};
if (Tgt)
spDiscard.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spDiscard));
else
spDiscard.setTargetPlayer(AllZone.GameAction.getOpponent(card.getController()));
spDiscard.setDescription(spDesc[0]);
spDiscard.setStackDescription(stDesc[0]);
card.clearSpellAbility();
card.addSpellAbility(spDiscard);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbDiscardTgt = spDiscard.copy();
bbDiscardTgt.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
bbDiscardTgt.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbDiscardTgt.setIsBuyBackAbility(true);
if (Tgt)
bbDiscardTgt.setBeforePayMana(CardFactoryUtil.input_targetPlayer(bbDiscardTgt));
else
bbDiscardTgt.setTargetPlayer(AllZone.GameAction.getOpponent(card.getController()));
card.addSpellAbility(bbDiscardTgt);
}
}//spDiscardTgt
- Code: Select all
Unnerve
3 B
Sorcery
no text
spDiscardOpp:OppChoose:2:Each opponent discards two cards.:Unnerve - opponent discards cards
Wheel and Deal
3 U
Instant
no text
spDiscardOpp:Hand:0:Drawback$OppDraw/7:Any number of target opponents each discards his or her hand and draws seven cards.:Wheel and Deal - target player discards cards
Draw a card.
Stupor
2 B
Sorcery
no text
spDiscardOpp:AtRandom:1:Drawback$OppDiscard/1:Target opponent discards a card at random, then discards a card.:Stupor - opponent discards cards
Mind Knives
1 B
Sorcery
no text
spDiscardOpp:AtRandom:1:Target opponent discards a card at random.:Mind Knives - opponent discards cards
Deception
2 B
Sorcery
no text
spDiscardOpp:OppChoose:2:Target opponent discards two cards.:Deception - opponent discards cards
Wit's End
5 B B
Sorcery
no text
spDiscardTgt:Hand:0:Target player discards his or her hand.:Wit's End - target player discards cards
Waking Nightmare
2 B
Sorcery Arcane
no text
spDiscardTgt:TgtChoose:2:Target player discards two cards.:Waking Nightmare - target player discards cards
Voices from the Void
4 B
Sorcery
no text
spDiscardTgt:TgtChoose:X:Domain - Target player discards a card for each basic land type among lands you control.:Voices from the Void - target player discards cards
Unhinge
2 B
Sorcery
no text
spDiscardTgt:TgtChoose:1:Target player discards a card.:Unhinge - target player discards a card
Draw a card.
Unburden
1 B B
Sorcery
no text
spDiscardTgt:TgtChoose:2:Target player discards two cards.:Unburden - target player discards cards
Cycling:2
Three Tragedies
3 B B
Sorcery Arcane
no text
spDiscardTgt:TgtChoose:3:Target player discards three cards.:Three Tragedies - target player discards cards
Specter's Wail
1 B
Sorcery
no text
spDiscardTgt:AtRandom:1:Target player discards a card at random.:Specter's Wail - target player discards a card
Mind Twist
X B
Sorcery
no text
spDiscardTgt:AtRandom:X:Target player discards X cards at random.:Mind Twist - target player discards cards
SVar:X:Count$xPaid
Mind Sludge
4 B
Sorcery
no text
spDiscardTgt:TgtChoose:X:Target player discards a card for each Swamp you control.:Mind Sludge - target player discards cards
SVar:X:Count$TypeYouCtrl.Swamp
Mind Shatter
X B B
Sorcery
spDiscardTgt:AtRandom:X:Target player discards X cards at random.:Mind Shatter - target player discards cards
SVar:X:Count$xPaid
Mind Rot
2 B
Sorcery
no text
spDiscardTgt:TgtChoose:2:Target player discards two cards.:Mind Rot - target player discards cards
Mind Peel
B
Sorcery
no text
spDiscardTgt:1:Target player discards a card.:Mind Peel - target player discards a card
SVar:Buyback:2 B B
Mind Burst
1 B
Sorcery
no text
spDiscardTgt:TgtChoose:X:Target player discards X cards, where X is one plus the number of cards named Mind Burst in all graveyards.:Mind Burst - target player discards cards
SVar:X:Count$NamedInAllYards.Mind Burst/Plus.1
Hymn to Tourach
B B
Sorcery
no text
spDiscardTgt:AtRandom:2:Target player discards two cards at random.:Hymn to Tourach - target player discards cards
Haunting Hymn
4 B B
Instant
no text
spDiscardTgt:TgtChoose:X:Target player discards two cards. If you cast this spell during your main phase, that player discards four cards instead.:Haunting Hymn - target player discards cards
SVar:X:Count$IfMainPhase.4.2
Fugue
3 B B
Sorcery
no text
spDiscardTgt:TgtChoose:3:Target player discards three cards.:Fugue - target player discards cards
Forget
U U
Sorcery
no text
spDiscardTgt:TgtChoose:2:Drawback$TgtDraw/2:Target player discards two cards, then draws as many cards as he or she discarded this way.:Forget - target player discards cards
Fill with Fright
3 B
Sorcery
no text
spDiscardTgt:TgtChoose:2:Target player discards two cards.:Fill with Fright - target player discards cards
Scry 2
Wrench Mind
B B
Sorcery
no text
spDiscardTgt:TgtChoose:2/UnlessDiscardType.Artifact:Target player discards two cards unless he or she discards an artifact card.:Wrench Mind - target player discards cards
Surging Dementia
1 B
Sorcery
no text
spDiscardTgt:TgtChoose:1:Target player discards a card.:Surging Dementia - Target player discards a card.
Ripple:4
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: spDiscard[Tgt|Opp]
by Sloth » 09 Jul 2010, 13:10
You're version of Forget seems to allow a player to draw two cards if it is the last card in his hand. This should not be possible with the oracle wording.
Syphon Mind has the same problem.
Syphon Mind has the same problem.
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: spDiscard[Tgt|Opp]
by Chris H. » 09 Jul 2010, 14:24
I merged my local copy up to r1390 and noticed a warning in CardFactory.java. The local variable Opp is never read. This is line 468.
Some of the cards you list use the Opp rather than the Tgt in k[0] … so I wild hold off on adding new cards or converting over the existing cards for the moment.
- Code: Select all
if (hasKeyword(card, "spDiscard") != -1)
{
int n = hasKeyword(card, "spDiscard");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean Tgt = k[0].contains("Tgt");
final boolean Opp = k[0].contains("Opp");
Some of the cards you list use the Opp rather than the Tgt in k[0] … so I wild hold off on adding new cards or converting over the existing cards for the moment.
-
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: spDiscard[Tgt|Opp]
by Rob Cashwalker » 09 Jul 2010, 15:25
No, go ahead with it. The "Opp" flag may become useful for the next stage.
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: spDiscard[Tgt|Opp]
by friarsol » 09 Jul 2010, 16:14
Could this keyword also work for "(You) Discard a card" as a cost? With Self as an option for the target. This could work great for spellshapers.
It may be easier for parsing to have the keyword just be spDiscard and let the first parameter be who is discarding.
Ex.
spDiscard:[Tgt|Opp|(Self)]:[TgtChoose|OppChoose|AtRandom|Hand]:<numCards>:<Drawback:Spell Description:StackDescription>
As for the second parameter, what is the difference betwen TgtChoose and OppChoose? It seems they might be "Discarding player chooses" and "Opponent of discarding player chooses". Maybe they can be clarified to OwnerChoose and OpponentChoose?
Although, I feel like that still may be confusing since the Opponent in the first parameter is different than the Opponent in the second parameter. Unless I'm confused myself.
It may be easier for parsing to have the keyword just be spDiscard and let the first parameter be who is discarding.
Ex.
spDiscard:[Tgt|Opp|(Self)]:[TgtChoose|OppChoose|AtRandom|Hand]:<numCards>:<Drawback:Spell Description:StackDescription>
As for the second parameter, what is the difference betwen TgtChoose and OppChoose? It seems they might be "Discarding player chooses" and "Opponent of discarding player chooses". Maybe they can be clarified to OwnerChoose and OpponentChoose?
Although, I feel like that still may be confusing since the Opponent in the first parameter is different than the Opponent in the second parameter. Unless I'm confused myself.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: spDiscard[Tgt|Opp]
by Rob Cashwalker » 09 Jul 2010, 16:27
No, discarding as a cost should be done as a cost. The AI for this assumes the intention is to make the player discard. Discarding as a cost should have AI that doesn't so much care about the discarding, more about the ultimate effect.
Same goes for how using "spDamageTgtP:0:Drawback$TgtDiscard:1" achieves the mechanical effect of "target player discards a card". However the AI for it assumes it's trying to deal damage to the player, so it would likely play the spell (if the AI calculation using zero damage even gets that far) even when the player had no cards in hand.
Tgt goes with TgtChoose and Opp goes with OppChoose. They're distinct effects - you could choose yourself if it's "target player" but not if it's "target opponent". However, we could probably drop the OppChoose, because the target player is set specifically to the opponent if not Tgt.
Same goes for how using "spDamageTgtP:0:Drawback$TgtDiscard:1" achieves the mechanical effect of "target player discards a card". However the AI for it assumes it's trying to deal damage to the player, so it would likely play the spell (if the AI calculation using zero damage even gets that far) even when the player had no cards in hand.
Tgt goes with TgtChoose and Opp goes with OppChoose. They're distinct effects - you could choose yourself if it's "target player" but not if it's "target opponent". However, we could probably drop the OppChoose, because the target player is set specifically to the opponent if not Tgt.
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: spDiscard[Tgt|Opp]
by Chris H. » 09 Jul 2010, 16:29
`Rob Cashwalker wrote:No, go ahead with it. The "Opp" flag may become useful for the next stage.
OK, no prob. I will add the cards and pic urls. Several cards will need to be converted. While I am at it I will put in a suppress warning.

-
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: spDiscard[Tgt|Opp]
by friarsol » 09 Jul 2010, 16:34
Ok, so this currently wouldn't handle a card like Coercion, because the Caster is the one who chooses (and not the target)?Rob Cashwalker wrote:Tgt goes with TgtChoose and Opp goes with OppChoose. They're distinct effects - you could choose yourself if it's "target player" but not if it's "target opponent". However, we could probably drop the OppChoose, because the target player is set specifically to the opponent if not Tgt.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: spDiscard[Tgt|Opp]
by Rob Cashwalker » 09 Jul 2010, 16:48
Right... RevealYouChoose will be the next method implemented.
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: spDiscard[Tgt|Opp]
by Chris H. » 09 Jul 2010, 17:00
The cards.txt entries that use the spDiscardOpp form of the keyword are causing a null error.
- Code: Select all
An error has occured. You can copy/paste this message or save it to a file.
Please report this, plus what you tried to do, to:
http://www.slightlymagic.net/forum/viewforum.php?f=26
If you don't want to register an account, you can mail it directly to
mtgerror@yahoo.com
null
Version:
Forge -- official beta: $Date: 2010-05-01 03:21:42 -0400 (Sat, 01 May 2010) $, SVN revision: $Revision: 916 $
OS: Mac OS X Version: 10.6.4 Architecture: x86_64
Java Version: 1.6.0_20 Vendor: Apple Inc.
Detailed error trace:
java.lang.NullPointerException
at forge.CardFactory.getCard2(CardFactory.java:580)
at forge.CardFactory.getCard(CardFactory.java:220)
at forge.CardFactory.<init>(CardFactory.java:67)
at forge.AllZone.<clinit>(AllZone.java:22)
at forge.Gui_NewGame.main(Gui_NewGame.java:131)
-
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: spDiscard[Tgt|Opp]
by Rob Cashwalker » 09 Jul 2010, 19:05
Hmm...
When the card's being created it has no controller... duh.
fixed it in r.1393
Plus, I make use of Opp, so no more warning.
When the card's being created it has no controller... duh.
fixed it in r.1393
Plus, I make use of Opp, so no more warning.
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: spDiscard[Tgt|Opp]
by Chris H. » 09 Jul 2010, 21:45
Thank you Rob.
I will merge in the new code and will then run a test to see if I am still having trouble adding Mind Peel. Mind Peel gave me an error in reference to the mana cost of the SVar Buyback:
Mind Peel
B
Sorcery
no text
spDiscardTgt:TgtChoose:1:Target player discards a card.:Mind Peel - target player discards a card
SVar:Buyback:2 B B
I will merge in the new code and will then run a test to see if I am still having trouble adding Mind Peel. Mind Peel gave me an error in reference to the mana cost of the SVar Buyback:
Mind Peel
B
Sorcery
no text
spDiscardTgt:TgtChoose:1:Target player discards a card.:Mind Peel - target player discards a card
SVar:Buyback:2 B B
- Code: Select all
An error has occured. You can copy/paste this message or save it to a file.
Please report this, plus what you tried to do, to:
http://www.slightlymagic.net/forum/viewforum.php?f=26
If you don't want to register an account, you can mail it directly to
mtgerror@yahoo.com
For input string: ""
Version:
Forge -- official beta: $Date: 2010-05-01 03:21:42 -0400 (Sat, 01 May 2010) $, SVN revision: $Revision: 916 $
OS: Mac OS X Version: 10.6.4 Architecture: x86_64
Java Version: 1.6.0_20 Vendor: Apple Inc.
Detailed error trace:
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:470)
at java.lang.Integer.valueOf(Integer.java:554)
at forge.CardUtil.addManaCosts(CardUtil.java:244)
at forge.CardFactory.getCard2(CardFactory.java:592)
at forge.CardFactory.getCard(CardFactory.java:220)
at forge.CardFactory.<init>(CardFactory.java:67)
at forge.AllZone.<clinit>(AllZone.java:22)
at forge.Gui_NewGame.main(Gui_NewGame.java:131)
-
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: spDiscard[Tgt|Opp]
by Chris H. » 10 Jul 2010, 12:01
-
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: spDiscard[Tgt|Opp]
by Rob Cashwalker » 10 Jul 2010, 16:44
I fixed the addManaCosts method to correctly handle adding a mana cost with no numeric component. Mind Peel costs B, so Integer.valueOf("") apparantly is the number format exception.... In VB Val("") is 0.
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
25 posts
• Page 1 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 15 guests