spDrawCards
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
21 posts
• Page 1 of 2 • 1, 2
spDrawCards
by Rob Cashwalker » 16 Aug 2009, 04:04
This is by far my most involved keyword development ever. It is also the most modular keyword - it has to support a wide variety of slight differences in the "Draw n cards" mechanic.
syntax:
spDrawCards[Tgt]:num:drawback
where num is:
a number.. like 1, 2, 3
Domain
NumCardsType/type/zone
where type is any single card type (artifact, creature, elf)
where zone is:
YouCtrl, InPlay, InYourYard or InAllYards
where drawback is:
Discard/{num | X}[/[AtRandom | UnlessDiscardType/type]]
LoseLife/{num | X}
NumToLibrary/{num | X}/{Top | Bottom | TopOrBottom}
NumOppDraw/{num | X}
where X really means "X" and will take on the number of cards calculated.
If you include "Tgt" to form "spDrawCardsTgt:" then it will request player targeting prior to resolution.
These are all the draw spells already included:
CardFactory:
The hand to library "TopOrBottom" function puts BOTH cards either on the top or the bottom. The usual wording of the general mechanic allows the top or bottom decision for each card. But the version of it that's used on a draw spell does specify BOTH. So until the basic code is hacked for the other form, to be used in other spells (scry anyone?) just be aware that it asks once for top or bottom, and then the second (or third, or last) card you select will be the very top card, followed by the prior cards.
The spells are playable by the AI. It will only play them to refill the hand as long as after the discard drawback, its hand will be less than 7. So if it has 5 cards, it won't play Ancestral Recall, but it would play Brainstorm or Sift, when it's added.
Also, I chose 8 as the cut-off for losing life drawbacks. I don't recall any gain life (self or opponent) "drawbacks" on drawspells, but I could easily add it just in case it does show up at some point, or to help support possible fan-made cards.
For targeted spells, the AI will always choose itself... unless and until milling is a viable strategy. (hint hint add the check in SBE, it's so easy)
syntax:
spDrawCards[Tgt]:num:drawback
where num is:
a number.. like 1, 2, 3
Domain
NumCardsType/type/zone
where type is any single card type (artifact, creature, elf)
where zone is:
YouCtrl, InPlay, InYourYard or InAllYards
where drawback is:
Discard/{num | X}[/[AtRandom | UnlessDiscardType/type]]
LoseLife/{num | X}
NumToLibrary/{num | X}/{Top | Bottom | TopOrBottom}
NumOppDraw/{num | X}
where X really means "X" and will take on the number of cards calculated.
If you include "Tgt" to form "spDrawCardsTgt:" then it will request player targeting prior to resolution.
These are all the draw spells already included:
- Code: Select all
Brainstorm
U
Instant
Draw three cards, then put two cards from your hand on top of your library in any order.
spDrawCards:3:NumToLibrary/2/Top
Minions' Murmurs
2 B B
Sorcery
You draw X cards and you lose X life, where X is the number of creatures you control.
spDrawCards:NumCardsType/Creature/YouCtrl:LoseLife/X
Harmonize
2 G G
Sorcery
Draw three cards.
spDrawCards:3
Concentrate
2 U U
Sorcery
Draw three cards.
spDrawCards:3
Night's Whisper
1 B
Sorcery
You draw two cards and you lose 2 life.
spDrawCards:2:LoseLife/2
Counsel of the Soratami
2 U
Sorcery
Draw two cards.
spDrawCards:2
Words of Wisdom
1 U
Instant
You draw two cards, then each other player draws a card.
spDrawCards:2:NumOppDraw/1
Ancestral Recall
U
Instant
Target player draws three cards.
spDrawCardsTgt:3
CardFactory:
- Code: Select all
private final int shouldSpDrawCards(Card c){
ArrayList<String> a = c.getKeyword();
for (int i = 0; i < a.size(); i++)
if (a.get(i).toString().startsWith("spDrawCards"))
return i;
return -1;
}
- Code: Select all
if (shouldSpDrawCards(card) != -1)
{
int n = shouldSpDrawCards(card);
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean Tgt[] = {false};
Tgt[0] = k[0].contains("Tgt");
final int NumCards[] = {-1};
final String NumCardsType[] = {"none"};
final boolean NumCardsTypeYouCtrl[] = {false};
final boolean NumCardsTypeInPlay[] = {false};
final boolean NumCardsTypeInYourYard[] = {false};
final boolean NumCardsTypeInAllYards[] = {false};
final boolean NumCardsDomain[] = {false};
if (k[1].length() == 1)
NumCards[0] = Integer.parseInt(k[1]);
else
{
if (k[1].startsWith("NumCardsType"))
{
String kk[] = k[1].split("/");
NumCardsType[0] = kk[1];
NumCardsTypeYouCtrl[0] = kk[2].equals("YouCtrl");
NumCardsTypeInPlay[0] = kk[2].equals("InPlay");
NumCardsTypeInYourYard[0] = kk[2].equals("InYourYard");
NumCardsTypeInAllYards[0] = kk[2].equals("InAllYards");
}
NumCardsDomain[0] = k[1].equals("Domain");
}
final int NumDiscard[] = {0};
final String UnlessDiscardType[] = {"none"};
final boolean AtRandom[] = {false};
final int NumLoseLife[] = {0};
final int NumToLibrary[] = {0};
final String LibraryPosition[] = {"none"};
final int NumOppDraw[] = {0};
if (k.length > 2)
{
if (k[2].contains("Discard"))
{
String kk[] = k[2].split("/");
if (kk[1].equals("X"))
NumDiscard[0] = -1;
else
NumDiscard[0] = Integer.parseInt(kk[1]);
if (kk.length > 2)
{
if (kk[2].equals("UnlessDiscardType"))
UnlessDiscardType[0] = kk[3];
AtRandom[0] = kk[2].equals("AtRandom");
}
}
if (k[2].contains("LoseLife"))
{
String kk[] = k[2].split("/");
if (kk[1].equals("X"))
NumLoseLife[0] = -1;
else
NumLoseLife[0] = Integer.parseInt(kk[1]);
}
if (k[2].contains("NumToLibrary"))
{
String kk[] = k[2].split("/");
if (kk[1].equals("X"))
NumToLibrary[0] = -1;
else
NumToLibrary[0] = Integer.parseInt(kk[1]);
LibraryPosition[0] = kk[2];
}
if (k[2].contains("NumOppDraw"))
{
String kk[] = k[2].split("/");
if (kk[1].equals("X"))
NumOppDraw[0] = -1;
else
NumOppDraw[0] = Integer.parseInt(kk[1]);
}
}
final SpellAbility spDraw = new Spell(card)
{
private static final long serialVersionUID = -7049779241008089696L;
public int getNumCards()
{
if (NumCards[0] != -1)
return NumCards[0];
int n = 0;
String cardController = card.getController();
PlayerZone myPlay = AllZone.getZone(Constant.Zone.Play, cardController);
PlayerZone opPlay = AllZone.getZone(Constant.Zone.Play, AllZone.GameAction.getOpponent(cardController));
PlayerZone myYard = AllZone.getZone(Constant.Zone.Graveyard, cardController);
PlayerZone opYard = AllZone.getZone(Constant.Zone.Graveyard, AllZone.GameAction.getOpponent(cardController));
CardList AllCards = new CardList();
if (! NumCardsType[0].equals("none"))
{
if (NumCardsTypeInYourYard[0] == false)
AllCards.addAll(myYard.getCards());
if (NumCardsTypeInAllYards[0] == false)
{
AllCards.addAll(myYard.getCards());
AllCards.addAll(opYard.getCards());
}
if (NumCardsTypeYouCtrl[0] == true)
AllCards.addAll(myPlay.getCards());
if (NumCardsTypeInPlay[0] == true)
{
AllCards.addAll(myPlay.getCards());
AllCards.addAll(opPlay.getCards());
}
AllCards = AllCards.filter(new CardListFilter()
{
public boolean addCard(Card c)
{
if (c.getType().contains(NumCardsType[0]))
return true;
return false;
}
});
n = AllCards.size();
}
if (NumCardsDomain[0] == true)
{
AllCards.addAll(myPlay.getCards());
String basic[] = {"Forest", "Plains", "Mountain", "Island", "Swamp"};
for(int i = 0; i < basic.length; i++)
if (! AllCards.getType(basic[i]).isEmpty())
n++;
}
if (NumDiscard[0] == -1)
NumDiscard[0] = n;
if (NumLoseLife[0] == -1)
NumLoseLife[0] = n;
if (NumToLibrary[0] == -1)
NumToLibrary[0] = n;
if (NumOppDraw[0] == -1)
NumOppDraw[0] = n;
return n;
}
public boolean canPlayAI()
{
int n = getNumCards();
int h = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).size();
Random r = new Random();
if (((h + n) - (NumDiscard[0] + NumToLibrary[0]) <= 7)
&& (AllZone.GameAction.getPlayerLife(Constant.Player.Computer).getLife() - NumLoseLife[0]) >= 8
&& (r.nextInt(10) > 4))
{
setTargetPlayer(Constant.Player.Computer);
return true;
}
return false;
}
public void resolve()
{
int n = getNumCards();
String TgtPlayer = card.getController();
if (Tgt[0])
TgtPlayer = getTargetPlayer();
for (int i=0; i < n; i++)
AllZone.GameAction.drawCard(TgtPlayer);
if (NumDiscard[0] > 0)
{
if (!UnlessDiscardType[0].equals("none"))
AllZone.GameAction.discardUnless(TgtPlayer, NumDiscard[0], UnlessDiscardType[0]);
else if (AtRandom[0] == true)
AllZone.GameAction.discardRandom(TgtPlayer, NumDiscard[0]);
else
AllZone.GameAction.discard(TgtPlayer, NumDiscard[0]);
}
if (NumLoseLife[0] > 0)
AllZone.GameAction.getPlayerLife(TgtPlayer).subtractLife(NumLoseLife[0]);
if (NumToLibrary[0] > 0)
AllZone.GameAction.handToLibrary(TgtPlayer, NumToLibrary[0], LibraryPosition[0]);
if (NumOppDraw[0] > 0)
for (int i = 0; i < NumOppDraw[0]; i++)
AllZone.GameAction.drawCard(AllZone.GameAction.getOpponent(TgtPlayer));
}
};
if (Tgt[0])
spDraw.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spDraw));
spDraw.setDescription(card.getText());
card.setText("");
card.clearSpellAbility();
card.addSpellAbility(spDraw);
}
- Code: Select all
public void discardRandom(String player, int numDiscard)
{
for (int i=0; i < numDiscard; i++)
{
Card[] c = AllZone.getZone(Constant.Zone.Hand, player).getCards();
if (c.length != 0)
discard(CardUtil.getRandom(c));
}
}
public void discard(String player, int numDiscard)
{
for (int i=0; i < numDiscard; i++)
if (player.equals(Constant.Player.Human))
AllZone.InputControl.setInput(CardFactoryUtil.input_discard());
else
AI_discard();
}
public void discardUnless(String player, int numDiscard, String uType)
{
if (player.equals(Constant.Player.Human))
AllZone.InputControl.setInput(CardFactoryUtil.input_discardNumUnless(numDiscard, uType));
else
AI_discardNumUnless(numDiscard, uType);
}
public void AI_discardNumUnless(int numDiscard, String uType)
{
CardList hand = new CardList();
hand.addAll(AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).getCards());
CardList tHand = hand.getType(uType);
if (tHand.size() > 0)
{
CardListUtil.sortCMC(tHand);
tHand.reverse();
discard(tHand.get(0));
return;
}
for (int i=0; i < numDiscard; i++)
AI_discard();
}
public void AI_discard()
{
CardList hand = new CardList();
hand.addAll(AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).getCards());
CardList blIP = new CardList();
blIP.addAll(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards());
blIP = blIP.getType("Basic");
if (blIP.size() > 5)
{
CardList blIH = hand.getType("Basic");
if (blIH.size() > 0)
{
discard(blIH.get(CardUtil.getRandomIndex(blIH)));
return;
}
CardListUtil.sortAttackLowFirst(hand);
CardListUtil.sortNonFlyingFirst(hand);
discard(hand.get(0));
return;
}
else
{
CardListUtil.sortCMC(hand);
discard(hand.get(0));
return;
}
}
public void handToLibrary(String player, int numToLibrary, String libPos)
{
if (player.equals(Constant.Player.Human))
{
if (libPos.equals("Top") || libPos.equals("Bottom"))
libPos = libPos.toLowerCase();
else
{
Object o = new Object();
String s = "card";
if (numToLibrary > 1)
s = "cards";
o = AllZone.Display.getChoice("Do you want to put the " + s + " on the top or bottom of your library?", new Object[] {"top", "bottom"});
libPos = o.toString();
}
AllZone.InputControl.setInput(CardFactoryUtil.input_putFromHandToLibrary(libPos, numToLibrary));
}
else
{
for (int i=0; i < numToLibrary; i++)
{
if (libPos.equals("Top") || libPos.equals("Bottom"))
libPos = libPos.toLowerCase();
else
{
Random r = new Random();
if (r.nextBoolean())
libPos = "top";
else
libPos = "bottom";
}
AI_handToLibrary(libPos);
}
}
}
public void AI_handToLibrary(String libPos)
{
CardList hand = new CardList();
hand.addAll(AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).getCards());
CardList blIP = new CardList();
blIP.addAll(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards());
blIP = blIP.getType("Basic");
if (blIP.size() > 5)
{
CardList blIH = hand.getType("Basic");
if (blIH.size() > 0)
{
Card card = blIH.get(CardUtil.getRandomIndex(blIH));
AllZone.Computer_Hand.remove(card);
if (libPos.equals("top"))
AllZone.Computer_Library.add(card, 0);
else
AllZone.Computer_Library.add(card);
return;
}
CardListUtil.sortAttackLowFirst(hand);
CardListUtil.sortNonFlyingFirst(hand);
discard(hand.get(0));
return;
}
else
{
CardListUtil.sortCMC(hand);
discard(hand.get(0));
return;
}
}
- Code: Select all
public static Input input_putFromHandToLibrary(final String TopOrBottom, final int num)
{
Input target = new Input()
{
private static final long serialVersionUID = 5178077952030689103L;
public int n = 0;
public void showMessage()
{
AllZone.Display.showMessage("Select a card to put on the " + TopOrBottom + " of your library.");
ButtonUtil.disableAll();
if (n == num || AllZone.Human_Hand.getCards().length == 0)
stop();
}
public void selectButtonCancel() {stop();}
public void selectCard(Card card, PlayerZone zone)
{
if (zone.is(Constant.Zone.Hand))
{
AllZone.Human_Hand.remove(card);
if (TopOrBottom.equals("top"))
AllZone.Human_Library.add(card, 0);
else if (TopOrBottom.equals("bottom"))
AllZone.Human_Library.add(card);
n++;
if (n == num)
stop();
showMessage();
}
}
};
return target;
}
public static Input input_discardNumUnless(final int nCards, final String uType)
{
Input target = new Input()
{
private static final long serialVersionUID = 8822292413831640944L;
int n = 0;
public void showMessage()
{
AllZone.Display.showMessage("Select " + (nCards - n) + " cards to discard, unless you discard a " + uType + ".");
ButtonUtil.disableAll();
if (n == nCards || AllZone.Human_Hand.getCards().length == 0)
stop();
}
public void selectButtonCancel() {stop();}
public void selectCard(Card card, PlayerZone zone)
{
if (zone.is(Constant.Zone.Hand))
{
AllZone.GameAction.discard(card);
n++;
if (card.getType().contains(uType))
stop();
showMessage();
}
}
};
return target;
}
The hand to library "TopOrBottom" function puts BOTH cards either on the top or the bottom. The usual wording of the general mechanic allows the top or bottom decision for each card. But the version of it that's used on a draw spell does specify BOTH. So until the basic code is hacked for the other form, to be used in other spells (scry anyone?) just be aware that it asks once for top or bottom, and then the second (or third, or last) card you select will be the very top card, followed by the prior cards.
The spells are playable by the AI. It will only play them to refill the hand as long as after the discard drawback, its hand will be less than 7. So if it has 5 cards, it won't play Ancestral Recall, but it would play Brainstorm or Sift, when it's added.
Also, I chose 8 as the cut-off for losing life drawbacks. I don't recall any gain life (self or opponent) "drawbacks" on drawspells, but I could easily add it just in case it does show up at some point, or to help support possible fan-made cards.
For targeted spells, the AI will always choose itself... unless and until milling is a viable strategy. (hint hint add the check in SBE, it's so easy)
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: spDrawCards
by Marek14 » 16 Aug 2009, 06:17
Kiss of the AmeshaRob Cashwalker wrote:Also, I chose 8 as the cut-off for losing life drawbacks. I don't recall any gain life (self or opponent) "drawbacks" on drawspells, but I could easily add it just in case it does show up at some point, or to help support possible fan-made cards.
Bargain
Armistice
Other effects which do something in addition to draw:
Arcane Spyglass
Fa'adiyah Seer and Sindbad
Fungal Shambler
Re: spDrawCards
by Rob Cashwalker » 16 Aug 2009, 14:45
I'd rather do those with dedicated life gain spells, since the primary AI on them would be related to gaining life, not drawing cards. BTW, if you specify any negative number other than -1 (used in handling "X") you could effectively make the gain life work as is....Marek14 wrote:Kiss of the Amesha
Bargain
Armistice
Other effects which do something in addition to draw:
Arcane Spyglass
Fa'adiyah Seer and Sindbad
Fungal Shambler
And this keyword doesn't cover permanent abilities.
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: spDrawCards
by DennisBergkamp » 16 Aug 2009, 17:02
Wow, as always, great stuff Rob! This one seems to cover a lot... and must've taken a long time to implement.
I'll merge this asap, and release a new version in the next few days.
I'll merge this asap, and release a new version in the next few days.
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: spDrawCards
by DennisBergkamp » 16 Aug 2009, 20:14
One problem with merging: you created a function sortCMC in CardListUtil:
?
- Code: Select all
CardListUtil.sortCMC(tHand);

-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: spDrawCards
by Rob Cashwalker » 17 Aug 2009, 11:31
- Code: Select all
@SuppressWarnings("unchecked") // Comparator needs <type>
public static void sortCMC(CardList list)
{
Comparator com = new Comparator()
{
public int compare(Object a1, Object b1)
{
Card a = (Card)a1;
Card b = (Card)b1;
int cmcA = CardUtil.getConvertedManaCost(a.getManaCost());
int cmcB = CardUtil.getConvertedManaCost(b.getManaCost());
if (cmcA == cmcB)
return 0;
if (cmcA > cmcB)
return -1;
if (cmcB > cmcA)
return 1;
return 0;
}
};
list.sort(com);
}
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: spDrawCards
by mtgrares » 17 Aug 2009, 15:57
Great work Rob, hopefully you didn't pull out any hair. 

- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
Re: spDrawCards
by Rob Cashwalker » 17 Aug 2009, 17:45
No.. no hair loss that I'm aware of. But I did lose a little sleep.
Funny enough, while I complain about my wife's facebook habits in marriage counseling, she's equally complained of my coding habits for MTGForge. While she has virtual farms and virtual mafias to her credit, I've gotten hundreds of cards added to the game.
Funny enough, while I complain about my wife's facebook habits in marriage counseling, she's equally complained of my coding habits for MTGForge. While she has virtual farms and virtual mafias to her credit, I've gotten hundreds of cards added to the game.
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: spDrawCards
by Chris H. » 19 Aug 2009, 12:51
I have been fairly busy in recent days. I'm sure that Dennis would like to release the next version in the near future. Rob has done a wonderful job with this keyword, and I have to agree that the syntax is complicated.
I did a search on the word "Draw" and was surprised to see so many hits. I grabbed eight cards that can be implemented for the next version. These cards are fairly simple in syntax. There are still many candidates that are not yet implemented/submitted. Some of these will require a more complicated form of the syntax.
The cards that I am submitting are:
@ Dennis:
I will pm the card data and the jpg urls to you.
I did a search on the word "Draw" and was surprised to see so many hits. I grabbed eight cards that can be implemented for the next version. These cards are fairly simple in syntax. There are still many candidates that are not yet implemented/submitted. Some of these will require a more complicated form of the syntax.
The cards that I am submitting are:
- Code: Select all
Ambition's Cost
3 B
Sorcery
You draw three cards and you lose 3 life.
spDrawCards:3:LoseLife/3
Ancient Craving
3 B
Sorcery
You draw three cards and you lose 3 life.
spDrawCards:3:LoseLife/3
Brilliant Plan
4 U
Sorcery
Draw three cards.
spDrawCards:3
Careful Study
U
Sorcery
Draw two cards, then discard two cards.
spDrawCards:2:Discard/2
Catalog
2 U
Instant
Draw two cards, then discard a card.
spDrawCards:2:Discard/1
Control of the Court
1 R
Sorcery
Draw four cards, then discard three cards at random.
spDrawCards:4:Discard/3/AtRandom
Divination
2 U
Sorcery
Draw two cards.
spDrawCards:2
Goblin Lore
1 R
Sorcery
Draw four cards, then discard three cards at random.
spDrawCards:4:Discard/3/AtRandom
@ Dennis:
I will pm the card data and the jpg urls to you.
-
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: spDrawCards
by Rob Cashwalker » 19 Aug 2009, 14:39
Those look good. Yeah, there are a lot of hits if you're just searching for "Draw"....
When I was doing the research for the different forms, I found it best to filter the phrase "Draw a card", since it's a tack-on effect, and present in "cycling", another tack-on. I didn't think of it at the time, but also filter "whenever" or "next", as there were some spells that created triggers. Also limit the search to just instants and sorceries.
If you come across any additional variations that seem simple, logical or popular enough, then let me know and I'll add it.
When I was doing the research for the different forms, I found it best to filter the phrase "Draw a card", since it's a tack-on effect, and present in "cycling", another tack-on. I didn't think of it at the time, but also filter "whenever" or "next", as there were some spells that created triggers. Also limit the search to just instants and sorceries.
If you come across any additional variations that seem simple, logical or popular enough, then let me know and I'll add it.
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: spDrawCards
by Chris H. » 19 Aug 2009, 14:59
Once I filtered out the cantrip and cycling cards the list became a wee bit easier to handle. There was still a third type which states:
Draw a card at the beginning of the next turn's upkeep.
This one looks like it should be a separate keyword and might be somewhat similar to the cantrips.
Draw a card at the beginning of the next turn's upkeep.
This one looks like it should be a separate keyword and might be somewhat similar to the cantrips.
-
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: spDrawCards
by Rob Cashwalker » 20 Aug 2009, 02:33
Yeah.. those were the ones I was talking about... I'm not about to try to figure out a delayed trigger of that magnitude....
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: spDrawCards
by mtgrares » 21 Aug 2009, 17:30
Don't get me started on therapists.Rob Cashwalker wrote:No.. no hair loss that I'm aware of. But I did lose a little sleep.
Funny enough, while I complain about my wife's facebook habits in marriage counseling, she's equally complained of my coding habits for MTGForge. While she has virtual farms and virtual mafias to her credit, I've gotten hundreds of cards added to the game.
- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
Re: spDrawCards
by Chris H. » 22 Aug 2009, 14:34
I think that I have figured out how to add an additional 15 cards. Many of these 15 cards require a fairly complicated form of the syntax, but I think that I have the following cards figured out.Chris H. wrote:Rob has done a wonderful job with this keyword, and I have to agree that the syntax is complicated.
There are still many candidates that are not yet implemented/submitted. Some of these will require a more complicated form of the syntax.

I may have missed a number of cards that can be included, if anyone else figures out a few more of these cards, that would be great.

The cards that I am submitting are:
- Code: Select all
Airborne Aid
3 U
Sorcery
Draw a card for each Bird on the battlefield.
spDrawCards:NumCardsType/Bird/InPlay
Collective Unconscious
4 G G
Sorcery
Draw a card for each creature you control.
spDrawCards:NumCardsType/Creature/YouCtrl
Compulsive Research
2 U
Sorcery
Target player draws three cards. Then that player discards two cards unless he or she discards a land card.
spDrawCardsTgt:3:Discard/2/UnlessDiscardType/Land
Dream Cache
2 U
Sorcery
Draw three cards, then put two cards from your hand both on top of your library or both on the bottom of your library.
spDrawCards:3:NumToLibrary/2/TopOrBottom
Flow of Ideas
5 U
Sorcery
Draw a card for each Island you control.
spDrawCards:NumCardsType/Island/YouCtrl
Inspiration
3 U
Instant
Target player draws two cards.
spDrawCardsTgt:2
Opportunity
4 U U
Instant
Target player draws four cards.
spDrawCardsTgt:4
Ribbons of the Reikai
4 U
Sorcery Arcane
Draw a card for each Spirit you control.
spDrawCards:NumCardsType/Spirit/YouCtrl
Sift
3 U
Sorcery
Draw three cards, then discard a card.
spDrawCards:3:Discard/1
Sign in Blood
B B
Sorcery
Target player draws two cards and loses 2 life.
spDrawCardsTgt:2:LoseLife/2
Thirst for Knowledge
2 U
Instant
Draw three cards. Then discard two cards unless you discard an artifact card.
spDrawCards:3:Discard/2/UnlessDiscardType/Artifact
Tidings
3 U U
Sorcery
Draw four cards.
spDrawCards:4
Touch of Brilliance
3 U
Sorcery
Draw two cards.
spDrawCards:2
Vision Skeins
1 U
Instant
Each player draws two cards.
spDrawCards:2:NumOppDraw/2
Wistful Thinking
2 U
Sorcery
Target player draws two cards, then discards four cards.
spDrawCardsTgt:2:Discard/4
@ Dennis:
I will pm the card data and the jpg urls to you.
-
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: spDrawCards
by Huggybaby » 22 Aug 2009, 15:25
My fiancee just got started on Facebook, and she has a farm now too. It's quite pointless IMO but so are my games I suppose. I think her time is better spent cooking me food and rubbing my feet.Rob Cashwalker wrote:While she has virtual farms and virtual mafias to her credit, I've gotten hundreds of cards added to the game.
-
Huggybaby - Administrator
- Posts: 3227
- Joined: 15 Jan 2006, 19:44
- Location: Finally out of Atlanta
- Has thanked: 749 times
- Been thanked: 601 times
21 posts
• Page 1 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 29 guests