abPump[Tgt] Keyword
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
25 posts
• Page 2 of 2 • 1, 2
Re: abPump[Tgt] Keyword
by Chris H. » 15 Feb 2010, 01:25
I noticed something strange recently with the abPumpTgt keyword. I have not had a chance to examine the code. I added the Granger Guildmage and when I looked at the text description I saw the word "gains" appear twice.
Stun Sniper does not have a text description and instead states "none". Yet the Storm Spirit is very similar and displays the text description. Both of these cards have "no text" in cards.txt and they do not include data in the card description and stack description fields.
`W, tap: Target creature gains gains First Strike until end of turn.
Granger Guildmage deals 1 damage to target creature or player and 1 damage to you.
Stun Sniper does not have a text description and instead states "none". Yet the Storm Spirit is very similar and displays the text description. Both of these cards have "no text" in cards.txt and they do not include data in the card description and stack description fields.
-
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: abPump[Tgt] Keyword
by Rob Cashwalker » 15 Feb 2010, 03:49
Stun Sniper - I just forgot the description, definitely needs it.
Storm Spirit - is a simple damage ability, and the abDamageTgt code will build the description.
Granger Guildmage - I see where the problem is. Missing some braces for the else:
Storm Spirit - is a simple damage ability, and the abDamageTgt code will build the description.
Granger Guildmage - I see where the problem is. Missing some braces for the else:
- Code: Select all
if (Tgt[0] == true)
sbD.append("Target creature gains ");
else
sbD.append(cardName);
sbD.append(" gains ");
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: abPump[Tgt] Keyword
by Rob Cashwalker » 20 Feb 2010, 04:18
Fixed in today's commit of CardFactory.
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: abPump[Tgt] Keyword
by Rob Cashwalker » 08 May 2010, 02:22
abPump now supports multiple keywords.
Cards to be added:
Cards to be added:
- Code: Select all
Power Matrix
4
Artifact
no text
abPumpTgt T:+1/+1/Flying & First Strike & Trample
Scornful AEther-Lich
3 U
Artifact Creature - Zombie Wizard
no text
2/4
abPump W B:Fear & Vigilance
- Code: Select all
while(hasKeyword(card, "abPump") != -1) {
int n = hasKeyword(card, "abPump");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean Tgt[] = {false};
Tgt[0] = k[0].contains("Tgt");
String tmpCost;
if(Tgt[0]) tmpCost = k[0].substring(9);
else tmpCost = k[0].substring(6);
boolean tapCost = false;
boolean tapOnlyCost = false;
if(tmpCost.contains("T")) {
tapCost = true;
tmpCost = tmpCost.replace("T", "");
tmpCost = tmpCost.trim();
if(tmpCost.length() == 0) tapOnlyCost = true;
}
final String manaCost = tmpCost.trim();
final int NumAttack[] = {-1138};
final String AttackX[] = {"none"};
final int NumDefense[] = {-1138};
final String DefenseX[] = {"none"};
final String Keyword[] = {"none"};
String ptk[] = k[1].split("/");
if(ptk.length == 1) // keyword only
Keyword[0] = ptk[0];
if(ptk.length >= 2) // power/toughness
{
if(ptk[0].matches("[\\+\\-][XY]")) {
String xy = card.getSVar(ptk[0].replaceAll("[\\+\\-]", ""));
if(xy.startsWith("Count$")) {
String kk[] = xy.split("\\$");
AttackX[0] = kk[1];
if(ptk[0].contains("-")) // handle "-X" or "-Y"
if(AttackX[0].contains("/")) // already contains math element
AttackX[0] = AttackX[0].replace("/", "/Negative"); // insert into existing math element
else AttackX[0] += "/Negative"; // add math element
}
} else if(ptk[0].matches("[\\+\\-][0-9]"))
NumAttack[0] = Integer.parseInt(ptk[0].replace("+", ""));
if(ptk[1].matches("[\\+\\-][XY]")) {
String xy = card.getSVar(ptk[1].replaceAll("[\\+\\-]", ""));
if(xy.startsWith("Count$")) {
String kk[] = xy.split("\\$");
DefenseX[0] = kk[1];
if(ptk[1].contains("-")) //handle "-X" or "-Y"
if(DefenseX[0].contains("/")) // already contains math element
DefenseX[0] = DefenseX[0].replace("/", "/Negative"); // insert into existing math element
else DefenseX[0] += "/Negative"; // add math element
}
} else if(ptk[1].matches("[\\+\\-][0-9]")) NumDefense[0] = Integer.parseInt(ptk[1].replace(
"+", ""));
}
if(ptk.length == 3) // power/toughness/keyword
Keyword[0] = ptk[2];
String dK = Keyword[0];
if (Keyword[0].contains(" & "))
{
int amp = Keyword[0].lastIndexOf("&");
StringBuffer sbk = new StringBuffer(Keyword[0]);
sbk.replace(amp, amp + 1, "and");
dK = sbk.toString();
dK = dK.replace(" & ", ", ");
}
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
String d = "none";
StringBuilder sbD = new StringBuilder();
if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
&& (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && Keyword[0].equals("none")) {
// pt boost
if(Tgt[0] == true) sbD.append("Target creature gets ");
else {
sbD.append(cardName);
sbD.append(" gets ");
}
if(NumAttack[0] > 0 || (NumAttack[0] == 0 && NumDefense[0] > 0)) // +0/+1
sbD.append("+");
else if(NumAttack[0] < 0 || (NumAttack[0] == 0 && NumDefense[0] < 0)) // -0/-1
sbD.append("-");
sbD.append(Math.abs(NumAttack[0]) + "/");
if(NumDefense[0] > 0 || (NumDefense[0] == 0 && NumAttack[0] > 0)) // +1/+0
sbD.append("+");
else if(NumDefense[0] < 0 || (NumDefense[0] == 0 && NumAttack[0] < 0)) // -1/-0
sbD.append("-");
sbD.append(Math.abs(NumDefense[0]));
sbD.append(" until end of turn.");
}
if((AttackX[0].equals("none") && NumAttack[0] == -1138)
&& (DefenseX[0].equals("none") && NumDefense[0] == -1138) && !Keyword[0].equals("none")) {
// k boost
if(Tgt[0] == true) sbD.append("Target creature gains ");
else {
sbD.append(cardName);
sbD.append(" gains ");
}
sbD.append(dK);
sbD.append(" until end of turn.");
}
if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
&& (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && !Keyword[0].equals("none")) {
// ptk boost
if(Tgt[0] == true) sbD.append("Target creature gets ");
else {
sbD.append(cardName);
sbD.append(" gets ");
}
if(NumAttack[0] > 0 || (NumAttack[0] == 0 && NumDefense[0] > 0)) // +0/+1
sbD.append("+");
else if(NumAttack[0] < 0 || (NumAttack[0] == 0 && NumDefense[0] < 0)) // -0/-1
sbD.append("-");
sbD.append(Math.abs(NumAttack[0]) + "/");
if(NumDefense[0] > 0 || (NumDefense[0] == 0 && NumAttack[0] > 0)) // +1/+0
sbD.append("+");
else if(NumDefense[0] < 0 || (NumDefense[0] == 0 && NumAttack[0] < 0)) // -1/-0
sbD.append("-");
sbD.append(Math.abs(NumDefense[0]));
sbD.append(" and gains ");
sbD.append(dK);
sbD.append(" until end of turn.");
}
//if (!sbD.toString().isEmpty())
if(sbD.toString().trim().length() != 0) d = sbD.toString();
if(k.length > 2) {
if(k[2].contains("Drawback$")) {
String kk[] = k[2].split("\\$");
DrawBack[0] = kk[1];
if(k.length > 3) d = k[3];
} else if(k.length > 2) d = k[2];
}
if(!d.equals("none")) {
if(tapOnlyCost == true) spDesc[0] = "Tap: " + d;
else if(tapCost == true) spDesc[0] = manaCost + ", tap: " + d;
else spDesc[0] = manaCost + ": " + d;
stDesc[0] = d;
}
if(!tapCost) {
final SpellAbility ability = new Ability_Activated(card, manaCost) {
private static final long serialVersionUID = -1118592153328758083L;
private int defense;
private String keyword;
private int getNumAttack() {
if(NumAttack[0] != -1138) return NumAttack[0];
if(!AttackX[0].equals("none")) return CardFactoryUtil.xCount(card, AttackX[0]);
return 0;
}
private int getNumDefense() {
if(NumDefense[0] != -1138) return NumDefense[0];
if(!DefenseX[0].equals("none")) return CardFactoryUtil.xCount(card, DefenseX[0]);
return 0;
}
@Override
public boolean canPlayAI() {
defense = getNumDefense();
keyword = Keyword[0];
if(AllZone.Phase.getPhase().equals(Constant.Phase.Main2)) return false;
if(Tgt[0] == false) {
setTargetCard(card);
if((card.getNetDefense() + defense > 0) && (!card.getKeyword().contains(keyword))) if(card.hasSickness()
&& keyword.contains("Haste")) return true;
else if((card.hasSickness() && (!keyword.contains("Haste")))
|| ((!card.hasSickness()) && keyword.contains("Haste"))) return false;
else {
Random r = new Random();
if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) return CardFactoryUtil.AI_doesCreatureAttack(card);
}
}
CardList list = getCreatures();
if(!list.isEmpty()) {
boolean goodt = false;
Card t = new Card();
while(goodt == false && !list.isEmpty()) // loop until we find a target that is best and won't die when targeted or until no more creatures
{
t = CardFactoryUtil.AI_getBestCreature(list);
if((t.getNetDefense() + defense) > 0) // handle negative defense pumps
goodt = true;
else list.remove(t);
}
if(goodt == true) {
Random r = new Random();
if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) {
setTargetCard(t);
return true;
}
}
}
return false;
}
@Override
public boolean canPlay() {
return (CardFactoryUtil.canUseAbility(card))
&& (AllZone.GameAction.isCardInPlay(card)) && (!card.isFaceDown());
}
private CardList getCreatures() {
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
if(c.isCreature()) {
if(c.hasSickness() && keyword.contains("Haste")) // AI_doesCreatureAttack would have prevented the effect from granting haste, because it assumes the creature would already have it
return CardFactoryUtil.canTarget(card, c);
return (CardFactoryUtil.AI_doesCreatureAttack(c))
&& (CardFactoryUtil.canTarget(card, c))
&& (!keyword.equals("none") && !c.hasAnyKeyword(keyword.split(" & ")))
&& (!(!c.hasSickness()) && keyword.contains("Haste")); // if creature doesn't have sickness, the haste keyword won't help
}
return false;
}
});
// list.remove(card); // if mana-only cost, allow self-target
return list;
}//getCreatures()
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& (CardFactoryUtil.canTarget(card, getTargetCard()) || !Tgt[0] )) {
final Card[] creature = new Card[1];
if(Tgt[0] == true) creature[0] = getTargetCard();
else creature[0] = card;
final int a = getNumAttack();
final int d = getNumDefense();
final Command EOT = new Command() {
private static final long serialVersionUID = -8840812331316327448L;
public void execute() {
if(AllZone.GameAction.isCardInPlay(creature[0])) {
creature[0].addTempAttackBoost(-1 * a);
creature[0].addTempDefenseBoost(-1 * d);
if(!Keyword[0].equals("none"))
{
String[] kws = Keyword[0].split(" & ");
for (int i=0; i<kws.length; i++)
creature[0].removeExtrinsicKeyword(kws[i]);
}
}
}
};
creature[0].addTempAttackBoost(a);
creature[0].addTempDefenseBoost(d);
if(!Keyword[0].equals("none"))
{
String[] kws = Keyword[0].split(" & ");
for (int i=0; i<kws.length; i++)
creature[0].addExtrinsicKeyword(kws[i]);
}
card.setAbilityUsed(card.getAbilityUsed() + 1);
AllZone.EndOfTurn.addUntil(EOT);
if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], 0,
card.getController(),
AllZone.GameAction.getOpponent(card.getController()), null, card,
creature[0]);
}//if (card is in play)
}//resolve()
};//SpellAbility
ability.setDescription(spDesc[0]);
ability.setStackDescription(stDesc[0]);
if(Tgt[0] == true) ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability));
else ability.setTargetCard(card);
card.addSpellAbility(ability);
}
if(tapCost) {
final SpellAbility ability = new Ability_Tap(card) {
private static final long serialVersionUID = 5252594757468128739L;
private int defense;
private String keyword;
private int getNumAttack() {
if(NumAttack[0] != -1138) return NumAttack[0];
if(!AttackX[0].equals("none")) return CardFactoryUtil.xCount(card, AttackX[0]);
return 0;
}
private int getNumDefense() {
if(NumDefense[0] != -1138) return NumDefense[0];
if(!DefenseX[0].equals("none")) return CardFactoryUtil.xCount(card, DefenseX[0]);
return 0;
}
@Override
public boolean canPlayAI() {
defense = getNumDefense();
keyword = Keyword[0];
if(CardFactoryUtil.AI_doesCreatureAttack(card)) return false;
if(AllZone.Phase.getPhase().equals(Constant.Phase.Main2)) return false;
CardList list = getCreatures();
if(!list.isEmpty()) {
boolean goodt = false;
Card t = new Card();
while(goodt == false && !list.isEmpty()) {
t = CardFactoryUtil.AI_getBestCreature(list);
if((t.getNetDefense() + defense) > 0) goodt = true;
else list.remove(t);
}
if(goodt == true) {
setTargetCard(t);
return true;
}
}
return false;
}
@Override
public boolean canPlay() {
boolean sick = true;
if(!card.hasSickness() || !card.isCreature()) sick = false;
if(card.isUntapped() && AllZone.GameAction.isCardInPlay(card) && !sick
&& !card.isFaceDown()) return true;
else return false;
}
private CardList getCreatures() {
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
if(c.isCreature()) {
if(c.hasSickness() && keyword.contains("Haste"))
return CardFactoryUtil.canTarget(card, c);
return (CardFactoryUtil.AI_doesCreatureAttack(c))
&& (CardFactoryUtil.canTarget(card, c))
&& (!keyword.equals("none") && !c.hasAnyKeyword(keyword.split(" & ")))
&& (!(!c.hasSickness()) && keyword.contains("Haste"));
}
return false;
}
});
list.remove(card);
return list;
}//getCreature()
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
final Card[] creature = new Card[1];
if(Tgt[0] == true) creature[0] = getTargetCard();
else creature[0] = card;
final int a = getNumAttack();
final int d = getNumDefense();
final Command EOT = new Command() {
private static final long serialVersionUID = 2134353417588894452L;
public void execute() {
if(AllZone.GameAction.isCardInPlay(creature[0])) {
creature[0].addTempAttackBoost(-1 * a);
creature[0].addTempDefenseBoost(-1 * d);
if(!Keyword[0].equals("none"))
{
String[] kws = Keyword[0].split(" & ");
for (int i=0; i<kws.length; i++)
creature[0].removeExtrinsicKeyword(kws[i]);
}
}
}
};
creature[0].addTempAttackBoost(a);
creature[0].addTempDefenseBoost(d);
if(!Keyword[0].equals("none"))
{
String[] kws = Keyword[0].split(" & ");
for (int i=0; i<kws.length; i++)
creature[0].addExtrinsicKeyword(kws[i]);
}
AllZone.EndOfTurn.addUntil(EOT);
if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], 0,
card.getController(),
AllZone.GameAction.getOpponent(card.getController()), null, card,
creature[0]);
}//if (card is in play)
}//resolve()
};//SpellAbility
ability.setDescription(spDesc[0]);
ability.setStackDescription(stDesc[0]);
if(Tgt[0] == true) ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability));
else ability.setTargetCard(card);
if(!tapOnlyCost) ability.setManaCost(manaCost);
card.addSpellAbility(ability);
}
}
}//while
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
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: abPump[Tgt] Keyword
by Chris H. » 08 May 2010, 09:32
The two new cards that this allows look very interesting. 

-
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: abPump[Tgt] Keyword
by Rob Cashwalker » 09 May 2010, 06:09
Mind you that's ALL the cards that are added... there are very few abilities and spells that do multiple keywords. Plenty of Auras, global enchantments and some global pump spells that do.
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: abPump[Tgt] Keyword
by Chris H. » 10 May 2010, 13:29
`Rob Cashwalker wrote:Mind you that's ALL the cards that are added... there are very few abilities and spells that do multiple keywords. Plenty of Auras, global enchantments and some global pump spells that do.
Understood.

I would like to include the Power Matrix in a new AI deck for quest mode. The Scornful AEther-Lich is another zombie and at some point it might be nice to also add a zombie deck.
-
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: abPump[Tgt] Keyword
by DennisBergkamp » 10 May 2010, 15:07
Hm, quest10.dck is some zombie deck I put together (it's really not that strong though - just has a bunch of random zombies and a couple Lord of the Undead + Cemetery Reaper).
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: abPump[Tgt] Keyword
by Chris H. » 10 May 2010, 16:11
`DennisBergkamp wrote:Hm, quest10.dck is some zombie deck I put together (it's really not that strong though - just has a bunch of random zombies and a couple Lord of the Undead + Cemetery Reaper).
I suspected that one of the quest{num} decks might contain zombies or that you were working to accomplish this goal ... I was going to mention this but I did not want to twist your arm behind your back.

-
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
25 posts
• Page 2 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 32 guests