mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
Issue 92: Reorganization of Costs
- Fix a few cards to adhere to new Cost requirements
This commit is contained in:
19
.gitattributes
vendored
19
.gitattributes
vendored
@@ -9584,6 +9584,23 @@ src/main/java/forge/card/cardFactory/CardFactory_Sorceries.java svneol=native#te
|
||||
src/main/java/forge/card/cardFactory/LazyCardFactory.java svneol=native#text/plain
|
||||
src/main/java/forge/card/cardFactory/PreloadingCardFactory.java svneol=native#text/plain
|
||||
src/main/java/forge/card/cardFactory/package-info.java svneol=native#text/plain
|
||||
src/main/java/forge/card/cost/Cost.java svneol=native#text/plain
|
||||
src/main/java/forge/card/cost/CostDiscard.java -text
|
||||
src/main/java/forge/card/cost/CostExile.java -text
|
||||
src/main/java/forge/card/cost/CostMana.java -text
|
||||
src/main/java/forge/card/cost/CostPart.java -text
|
||||
src/main/java/forge/card/cost/CostPartWithList.java -text
|
||||
src/main/java/forge/card/cost/CostPayLife.java -text
|
||||
src/main/java/forge/card/cost/CostPutCounter.java -text
|
||||
src/main/java/forge/card/cost/CostRemoveCounter.java -text
|
||||
src/main/java/forge/card/cost/CostReturn.java -text
|
||||
src/main/java/forge/card/cost/CostSacrifice.java -text
|
||||
src/main/java/forge/card/cost/CostTap.java -text
|
||||
src/main/java/forge/card/cost/CostTapType.java -text
|
||||
src/main/java/forge/card/cost/CostUntap.java -text
|
||||
src/main/java/forge/card/cost/CostUtil.java -text
|
||||
src/main/java/forge/card/cost/Cost_Input.java -text
|
||||
src/main/java/forge/card/cost/Cost_Payment.java svneol=native#text/plain
|
||||
src/main/java/forge/card/mana/Mana.java svneol=native#text/plain
|
||||
src/main/java/forge/card/mana/ManaCost.java svneol=native#text/plain
|
||||
src/main/java/forge/card/mana/ManaPool.java svneol=native#text/plain
|
||||
@@ -9601,8 +9618,6 @@ src/main/java/forge/card/spellability/Ability_Mana.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/Ability_Static.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/Ability_Sub.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/Ability_Triggered.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/Cost.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/Cost_Payment.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/Spell.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/SpellAbility.java svneol=native#text/plain
|
||||
src/main/java/forge/card/spellability/SpellAbilityList.java svneol=native#text/plain
|
||||
|
||||
@@ -4,8 +4,9 @@ Types:Artifact Creature Angel
|
||||
Text:no text
|
||||
PT:2/2
|
||||
K:Flying
|
||||
A:AB$PutCounter | Cost$ T Sac<X/Land> | Defined$ Self | CounterType$ P1P1 | CounterNum$ X | SpellDescription$ Put X +1/+1 counters on CARDNAME.
|
||||
SVar:X:Sacrificed$Amount
|
||||
A:AB$PutCounter | Cost$ T Sac<X/Land> | Defined$ Self | CounterType$ P1P1 | CounterNum$ ChosenX | SpellDescription$ Put X +1/+1 counters on CARDNAME.
|
||||
SVar:X:XChoice
|
||||
#ChosenX SVar created by Cost payment
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Rare
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/copper_leaf_angel.jpg
|
||||
|
||||
@@ -2,8 +2,9 @@ Name:Devastating Summons
|
||||
ManaCost:R
|
||||
Types:Sorcery
|
||||
Text:no text
|
||||
A:SP$ Token | Cost$ R Sac<X/Land> | TokenAmount$ 2 | TokenName$ Elemental | TokenTypes$ Creature,Elemental | TokenOwner$ You | TokenColors$ Red | TokenPower$ X | TokenToughness$ X | SpellDescription$ Put two X/X red Elemental creature tokens onto the battlefield.
|
||||
SVar:X:Sacrificed$Amount
|
||||
A:SP$ Token | Cost$ R Sac<X/Land> | TokenAmount$ 2 | TokenName$ Elemental | TokenTypes$ Creature,Elemental | TokenOwner$ You | TokenColors$ Red | TokenPower$ ChosenX | TokenToughness$ ChosenX | SpellDescription$ Put two X/X red Elemental creature tokens onto the battlefield.
|
||||
SVar:X:XChoice
|
||||
#ChosenX SVar created by Cost payment
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Rare
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/devastating_summons.jpg
|
||||
|
||||
@@ -3,9 +3,11 @@ ManaCost:X R R
|
||||
Types:Sorcery
|
||||
Text:no text
|
||||
A:SP$ Token | Cost$ X R R | TokenAmount$ X | TokenName$ Elemental Cat | TokenTypes$ Creature,Elemental,Cat | TokenOwner$ You | TokenColors$ Red | TokenPower$ 1 | TokenToughness$ 1 | TokenKeywords$ Haste<>At the beginning of the end step, exile CARDNAME. | SpellDescription$ Put X 1/1 red Elemental Cat creature tokens with haste onto the battlefield. Exile them at the beginning of the next end step.
|
||||
A:SP$ Token | Cost$ R R Sac<X/Mountain> | TokenAmount$ Y | TokenName$ Elemental Cat | TokenTypes$ Creature,Elemental,Cat | TokenOwner$ You | TokenColors$ Red | TokenPower$ 1 | TokenToughness$ 1 | TokenKeywords$ Haste<>At the beginning of the end step, exile CARDNAME. | Flashback$ True | CostDesc$ Flashback - R R, Sacrifice X Mountains. | SpellDescription$ (You may cast this card from your graveyard for its flashback cost. Then exile it.)
|
||||
A:SP$ Token | Cost$ R R Sac<Y/Mountain> | TokenAmount$ ChosenX | TokenName$ Elemental Cat | TokenTypes$ Creature,Elemental,Cat | TokenOwner$ You | TokenColors$ Red | TokenPower$ 1 | TokenToughness$ 1 | TokenKeywords$ Haste<>At the beginning of the end step, exile CARDNAME. | Flashback$ True | CostDesc$ Flashback - R R, Sacrifice X Mountains. | SpellDescription$ (You may cast this card from your graveyard for its flashback cost. Then exile it.)
|
||||
SVar:X:Count$xPaid
|
||||
SVar:Y:Sacrificed$Amount
|
||||
SVar:Y:XChoice
|
||||
#Flashback uses Y because SVars can't overlap
|
||||
#ChosenX SVar created by Cost payment
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Uncommon
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/firecat_blitz.jpg
|
||||
|
||||
@@ -175,6 +175,8 @@ public class Card extends MyObservable implements Comparable<Card> {
|
||||
|
||||
private Map<Counters, Integer> counters = new TreeMap<Counters, Integer>();
|
||||
private Map<String, String> SVars = new TreeMap<String, String>();
|
||||
private static String[] storableSVars = { "ChosenX" };
|
||||
public static String[] getStorableSVars() { return storableSVars; }
|
||||
|
||||
//hacky code below, used to limit the number of times an ability
|
||||
//can be used per turn like Vampire Bats
|
||||
|
||||
@@ -451,4 +451,17 @@ public class CardListUtil {
|
||||
return cmc;
|
||||
|
||||
}//sumCMC
|
||||
|
||||
public static CardList getRandomSubList(CardList c, int amount){
|
||||
if (c.size() < amount)
|
||||
return null;
|
||||
|
||||
CardList subList = new CardList();
|
||||
while(subList.size() < amount){
|
||||
c.shuffle();
|
||||
subList.add(c.get(0));
|
||||
c.remove(0);
|
||||
}
|
||||
return subList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ package forge;
|
||||
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.cost.Cost_Payment;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.mana.ManaPool;
|
||||
import forge.card.spellability.*;
|
||||
@@ -128,7 +131,7 @@ public class ComputerUtil {
|
||||
//String totalMana = source.getSVar("PayX"); // + cost.getCMC()
|
||||
|
||||
// Consider the costs here for relative "scoring"
|
||||
if (cost.getDiscardType().equals("Hand")) {
|
||||
if (CostUtil.hasDiscardHandCost(cost)) {
|
||||
// Null Brooch aid
|
||||
restrict -= (AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer()).size() * 20);
|
||||
}
|
||||
@@ -418,160 +421,11 @@ public class ComputerUtil {
|
||||
* @return a boolean.
|
||||
*/
|
||||
static public boolean canPayAdditionalCosts(SpellAbility sa, Player player) {
|
||||
// Add additional cost checks here before attempting to activate abilities
|
||||
Cost cost = sa.getPayCosts();
|
||||
if (cost == null)
|
||||
return true;
|
||||
Card card = sa.getSourceCard();
|
||||
|
||||
if (cost.getTap() && (card.isTapped() || card.isSick()))
|
||||
return false;
|
||||
|
||||
if (cost.getUntap() && (card.isUntapped() || card.isSick()))
|
||||
return false;
|
||||
|
||||
if (cost.getTapXTypeCost()) {
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(player);
|
||||
typeList = typeList.getValidCards(cost.getTapXType().split(","), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
|
||||
if (cost.getTap())
|
||||
typeList.remove(sa.getSourceCard());
|
||||
typeList = typeList.filter(AllZoneUtil.untapped);
|
||||
|
||||
if (cost.getTapXTypeAmount() > typeList.size())
|
||||
return false;
|
||||
if (sa.getActivatingPlayer() == null){
|
||||
System.out.println(sa.getSourceCard() + " in ComputerUtil.canPayAdditionalCosts() without an activating player");
|
||||
sa.setActivatingPlayer(player);
|
||||
}
|
||||
|
||||
if (cost.getSubCounter()) {
|
||||
Counters c = cost.getCounterType();
|
||||
if (card.getCounters(c) - cost.getCounterNum() < 0 || !AllZoneUtil.isCardInPlay(card)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cost.getAddCounter()) {
|
||||
// this should always be true
|
||||
}
|
||||
|
||||
if (cost.getLifeCost()) {
|
||||
if (player.getLife() <= cost.getLifeAmount())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cost.getDiscardCost()) {
|
||||
CardList handList = AllZoneUtil.getPlayerHand(player);
|
||||
String discType = cost.getDiscardType();
|
||||
int discAmount = cost.getDiscardAmount();
|
||||
|
||||
if (cost.getDiscardThis()) {
|
||||
if (!AllZone.getZone(card).getZoneName().equals(Constant.Zone.Hand))
|
||||
return false;
|
||||
} else if (discType.equals("LastDrawn")) {
|
||||
//compy can't yet use this effectively
|
||||
return false;
|
||||
} else if (discType.equals("Hand")) {
|
||||
// this will always work
|
||||
} else {
|
||||
if (!discType.equals("Any") && !discType.equals("Random")) {
|
||||
String validType[] = discType.split(",");
|
||||
handList = handList.getValidCards(validType, sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
}
|
||||
if (discAmount > handList.size()) {
|
||||
// not enough cards in hand to pay
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cost.getSacCost()) {
|
||||
// if there's a sacrifice in the cost, just because we can Pay it doesn't mean we want to.
|
||||
if (!cost.getSacThis()) {
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(player);
|
||||
typeList = typeList.getValidCards(cost.getSacType().split(","), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
Card target = sa.getTargetCard();
|
||||
if (target != null && target.getController().isPlayer(player)) // don't sacrifice the card we're pumping
|
||||
typeList.remove(target);
|
||||
|
||||
if (cost.getSacAmount() > typeList.size())
|
||||
return false;
|
||||
} else if (cost.getSacThis() && !AllZoneUtil.isCardInPlay(card))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cost.getExileCost()) {
|
||||
// if there's an exile in the cost, just because we can Pay it doesn't mean we want to.
|
||||
if (!cost.getExileThis()) {
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(player);
|
||||
typeList = typeList.getValidCards(cost.getExileType().split(","), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
Card target = sa.getTargetCard();
|
||||
if (target != null && target.getController().isPlayer(player)) // don't exile the card we're pumping
|
||||
typeList.remove(target);
|
||||
|
||||
if (cost.getExileAmount() > typeList.size())
|
||||
return false;
|
||||
} else if (cost.getExileThis() && !AllZoneUtil.isCardInPlay(card))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cost.getExileFromHandCost()) {
|
||||
// if there's an exile in the cost, just because we can Pay it doesn't mean we want to.
|
||||
if (!cost.getExileFromHandThis()) {
|
||||
CardList typeList = AllZoneUtil.getPlayerHand(player);
|
||||
typeList = typeList.getValidCards(cost.getExileFromHandType().split(","), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
Card target = sa.getTargetCard();
|
||||
if (target != null && target.getController().isPlayer(player)) // don't exile the card we're pumping
|
||||
typeList.remove(target);
|
||||
|
||||
if (cost.getExileFromHandAmount() > typeList.size())
|
||||
return false;
|
||||
} else if (cost.getExileFromHandThis() && !AllZoneUtil.isCardInPlayerHand(player, card))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cost.getExileFromGraveCost()) {
|
||||
if (!cost.getExileFromGraveThis()) {
|
||||
CardList typeList = AllZoneUtil.getPlayerGraveyard(player);
|
||||
typeList = typeList.getValidCards(cost.getExileFromGraveType().split(","), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
Card target = sa.getTargetCard();
|
||||
if (target != null && target.getController().isPlayer(player)) // don't exile the card we're pumping
|
||||
typeList.remove(target);
|
||||
|
||||
if (cost.getExileFromGraveAmount() > typeList.size())
|
||||
return false;
|
||||
} else if (cost.getExileFromGraveThis() && !AllZoneUtil.isCardInPlayerGraveyard(player, card))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cost.getExileFromTopCost()) {
|
||||
if (!cost.getExileFromTopThis()) {
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInLibrary(player);
|
||||
typeList = typeList.getValidCards(cost.getExileFromTopType().split(","), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
Card target = sa.getTargetCard();
|
||||
if (target != null && target.getController().isPlayer(player)) // don't exile the card we're pumping
|
||||
typeList.remove(target);
|
||||
|
||||
if (cost.getExileFromTopAmount() > typeList.size())
|
||||
return false;
|
||||
} else if (cost.getExileFromTopThis() && !AllZoneUtil.isCardInPlayerLibrary(player, card))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cost.getReturnCost()) {
|
||||
// if there's a return in the cost, just because we can Pay it doesn't mean we want to.
|
||||
if (!cost.getReturnThis()) {
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(player);
|
||||
typeList = typeList.getValidCards(cost.getReturnType().split(","), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
Card target = sa.getTargetCard();
|
||||
if (target != null && target.getController().isPlayer(player)) // don't bounce the card we're pumping
|
||||
typeList.remove(target);
|
||||
|
||||
if (cost.getReturnAmount() > typeList.size())
|
||||
return false;
|
||||
} else if (!AllZoneUtil.isCardInPlay(card))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return Cost_Payment.canPayAdditionalCosts(sa.getPayCosts(), sa);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -651,7 +505,7 @@ public class ComputerUtil {
|
||||
for (Ability_Mana m : manaAbilities) {
|
||||
|
||||
if (used) break; //mana source already used in the test
|
||||
|
||||
m.setActivatingPlayer(player);
|
||||
//if the AI can't pay the additional costs skip the mana ability
|
||||
if (m.getPayCosts() != null) {
|
||||
if (!canPayAdditionalCosts(m, player))
|
||||
@@ -799,15 +653,14 @@ public class ComputerUtil {
|
||||
for (Ability_Mana m : manaAbilities) {
|
||||
|
||||
Cost cost = m.getPayCosts();
|
||||
needsLimitedResources |= !cost.isReusuableResource();
|
||||
|
||||
//if the AI can't pay the additional costs skip the mana ability
|
||||
m.setActivatingPlayer(AllZone.getComputerPlayer());
|
||||
if (cost != null) {
|
||||
if (!canPayAdditionalCosts(m, player))
|
||||
continue;
|
||||
if (cost.getSubCounter() || cost.getLifeCost())
|
||||
needsLimitedResources = true;
|
||||
} else if (card.isTapped())
|
||||
continue;
|
||||
}
|
||||
|
||||
//don't use abilities with dangerous drawbacks
|
||||
if (m.getSubAbility() != null) {
|
||||
@@ -837,15 +690,12 @@ public class ComputerUtil {
|
||||
for (Ability_Mana m : manaAbilities) {
|
||||
|
||||
Cost cost = m.getPayCosts();
|
||||
|
||||
needsLimitedResources |= !cost.isReusuableResource();
|
||||
//if the AI can't pay the additional costs skip the mana ability
|
||||
if (cost != null) {
|
||||
if (!canPayAdditionalCosts(m, player))
|
||||
continue;
|
||||
if (cost.getSubCounter() || cost.getLifeCost())
|
||||
needsLimitedResources = true;
|
||||
} else if (card.isTapped())
|
||||
continue;
|
||||
}
|
||||
|
||||
//don't use abilities with dangerous drawbacks
|
||||
if (m.getSubAbility() != null) {
|
||||
@@ -1035,7 +885,7 @@ public class ComputerUtil {
|
||||
if (target != null && target.getController().isComputer() && typeList.contains(target))
|
||||
typeList.remove(target); // don't sacrifice the card we're pumping
|
||||
|
||||
if (typeList.size() == 0)
|
||||
if (typeList.size() < amount)
|
||||
return null;
|
||||
|
||||
CardList sacList = new CardList();
|
||||
@@ -1112,7 +962,7 @@ public class ComputerUtil {
|
||||
if (target != null && target.getController().isComputer() && typeList.contains(target))
|
||||
typeList.remove(target); // don't exile the card we're pumping
|
||||
|
||||
if (typeList.size() == 0)
|
||||
if (typeList.size() < amount)
|
||||
return null;
|
||||
|
||||
CardListUtil.sortAttackLowFirst(typeList);
|
||||
@@ -1141,7 +991,7 @@ public class ComputerUtil {
|
||||
if (tap)
|
||||
typeList.remove(activate);
|
||||
|
||||
if (typeList.size() == 0 || amount >= typeList.size())
|
||||
if (typeList.size() < amount)
|
||||
return null;
|
||||
|
||||
CardListUtil.sortAttackLowFirst(typeList);
|
||||
@@ -1167,7 +1017,7 @@ public class ComputerUtil {
|
||||
if (target != null && target.getController().isComputer() && typeList.contains(target)) // don't bounce the card we're pumping
|
||||
typeList.remove(target);
|
||||
|
||||
if (typeList.size() == 0)
|
||||
if (typeList.size() < amount)
|
||||
return null;
|
||||
|
||||
CardListUtil.sortAttackLowFirst(typeList);
|
||||
|
||||
@@ -5,6 +5,8 @@ import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.abilityFactory.AbilityFactory_Attach;
|
||||
import forge.card.cardFactory.CardFactoryInterface;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.Cost_Payment;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.mana.ManaPool;
|
||||
import forge.card.spellability.*;
|
||||
@@ -475,26 +477,30 @@ public class GameAction {
|
||||
return moveToStack(c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>AI_discardNumType.</p>
|
||||
*
|
||||
* @param numDiscard a int.
|
||||
* @param uTypes an array of {@link java.lang.String} objects.
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a boolean.
|
||||
* @return a CardList of discarded cards.
|
||||
*/
|
||||
public boolean AI_discardNumType(int numDiscard, String[] uTypes, SpellAbility sa) {
|
||||
public CardList AI_discardNumType(int numDiscard, String[] uTypes, SpellAbility sa) {
|
||||
CardList hand = AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer());
|
||||
CardList tHand = hand.getValidCards(uTypes, sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
hand = hand.getValidCards(uTypes, sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
|
||||
if (tHand.size() >= numDiscard) {
|
||||
CardListUtil.sortCMC(tHand);
|
||||
tHand.reverse();
|
||||
if (hand.size() < numDiscard)
|
||||
return null;
|
||||
|
||||
CardList discard = new CardList();
|
||||
|
||||
CardListUtil.sortCMC(hand);
|
||||
hand.reverse();
|
||||
for (int i = 0; i < numDiscard; i++)
|
||||
tHand.get(i).getController().discard(tHand.get(i), sa);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
discard.add(hand.get(i));
|
||||
|
||||
return discard;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge;
|
||||
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.game.GameLossReason;
|
||||
import forge.gui.GuiUtils;
|
||||
|
||||
@@ -2,6 +2,7 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -73,7 +74,7 @@ public class AbilityFactory {
|
||||
/**
|
||||
* <p>Getter for the field <code>abCost</code>.</p>
|
||||
*
|
||||
* @return a {@link forge.card.spellability.Cost} object.
|
||||
* @return a {@link forge.card.cost.Cost} object.
|
||||
*/
|
||||
public Cost getAbCost() {
|
||||
return abCost;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -200,33 +202,20 @@ public class AbilityFactory_AlterLife {
|
||||
//don't use it if no life to gain
|
||||
if (lifeAmount <= 0) return false;
|
||||
|
||||
if (abCost != null) {
|
||||
if (abCost.getSacCost() && life > 4) {
|
||||
if (abCost.getSacThis() && life > 6)
|
||||
if (abCost != null) {
|
||||
if (life > 5){
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
else {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String type = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(type.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (abCost.getLifeCost() && life > 5) return false;
|
||||
if (abCost.getDiscardCost() && life > 5) return false;
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
//non +1/+1 counters should be used
|
||||
if (abCost.getCounterType().equals(Counters.P1P1)) {
|
||||
// A card has a 25% chance per counter to be able to pass through here
|
||||
// 4+ counters will always pass. 0 counters will never
|
||||
int currentNum = source.getCounters(abCost.getCounterType());
|
||||
double percent = .25 * (currentNum / abCost.getCounterNum());
|
||||
if (percent <= r.nextFloat())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(abCost, source))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!AllZone.getComputerPlayer().canGainLife())
|
||||
@@ -507,8 +496,6 @@ public class AbilityFactory_AlterLife {
|
||||
Cost abCost = sa.getPayCosts();
|
||||
final Card source = sa.getSourceCard();
|
||||
HashMap<String, String> params = af.getMapParams();
|
||||
int humanLife = AllZone.getHumanPlayer().getLife();
|
||||
int aiLife = AllZone.getComputerPlayer().getLife();
|
||||
|
||||
String amountStr = params.get("LifeAmount");
|
||||
|
||||
@@ -517,29 +504,17 @@ public class AbilityFactory_AlterLife {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost()) {
|
||||
if (amountStr.contains("X"))
|
||||
return false;
|
||||
if (!abCost.getSacThis()) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String type = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(type.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (abCost.getLifeCost() && aiLife - abCost.getLifeAmount() < humanLife - amount) return false;
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
if (!CostUtil.checkLifeCost(abCost, source, amount))
|
||||
return false;
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
// A card has a 25% chance per counter to be able to pass through here
|
||||
// 4+ counters will always pass. 0 counters will never
|
||||
int currentNum = source.getCounters(abCost.getCounterType());
|
||||
double percent = .25 * (currentNum / abCost.getCounterNum());
|
||||
if (percent <= r.nextFloat())
|
||||
return false;
|
||||
}
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(abCost, source))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!AllZone.getHumanPlayer().canLoseLife())
|
||||
@@ -892,27 +867,17 @@ public class AbilityFactory_AlterLife {
|
||||
//int humanPoison = AllZone.getHumanPlayer().getPoisonCounters();
|
||||
//int humanLife = AllZone.getHumanPlayer().getLife();
|
||||
//int aiPoison = AllZone.getComputerPlayer().getPoisonCounters();
|
||||
int aiLife = AllZone.getComputerPlayer().getLife();
|
||||
String amountStr = params.get("Num");
|
||||
|
||||
// TODO handle proper calculation of X values based on Cost and what would be paid
|
||||
//final int amount = AbilityFactory.calculateAmount(af.getHostCard(), amountStr, sa);
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost()) {
|
||||
if (amountStr.contains("X"))
|
||||
return false;
|
||||
if (!abCost.getSacThis()) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String type = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(type.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (abCost.getLifeCost() && aiLife - abCost.getLifeAmount() <= 0) return false;
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 1))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
}
|
||||
|
||||
//Don't use poison before main 2 if possible
|
||||
|
||||
@@ -15,13 +15,12 @@ import forge.CombatUtil;
|
||||
import forge.Command;
|
||||
import forge.ComputerUtil;
|
||||
import forge.Constant;
|
||||
import forge.Counters;
|
||||
import forge.MyRandom;
|
||||
import forge.Player;
|
||||
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.Ability_Sub;
|
||||
import forge.card.spellability.Cost;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Spell_Permanent;
|
||||
@@ -520,25 +519,7 @@ public class AbilityFactory_Attach {
|
||||
|
||||
if (abCost != null){
|
||||
// No Aura spells have Additional Costs
|
||||
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost()){
|
||||
|
||||
}
|
||||
if (abCost.getLifeCost()) return false;
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
|
||||
if (abCost.getSubCounter()){
|
||||
//non +1/+1 counters should be used
|
||||
if (abCost.getCounterType().equals(Counters.P1P1)){
|
||||
// A card has a 25% chance per counter to be able to pass through here
|
||||
// 4+ counters will always pass. 0 counters will never
|
||||
int currentNum = source.getCounters(abCost.getCounterType());
|
||||
double percent = .25 * (currentNum / abCost.getCounterNum());
|
||||
if (percent <= r.nextFloat())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
@@ -552,7 +533,7 @@ public class AbilityFactory_Attach {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (abCost.getMana().contains("X") && source.getSVar("X").equals("Count$xPaid")){
|
||||
if (abCost.getTotalMana().contains("X") && source.getSVar("X").equals("Count$xPaid")){
|
||||
// Set PayX here to maximum value. (Endless Scream and Venarian Gold)
|
||||
int xPay = ComputerUtil.determineLeftoverMana(sa);
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
|
||||
@@ -283,22 +285,14 @@ public class AbilityFactory_ChangeZone {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost() && !abCost.getSacThis()) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String type = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(type.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
|
||||
if (abCost.getSubCounter()) ; // SubCounter is fine
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
}
|
||||
|
||||
Random r = MyRandom.random;
|
||||
@@ -897,28 +891,17 @@ public class AbilityFactory_ChangeZone {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost() && !abCost.getSacThis()) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String type = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(type.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
// A card has a 25% chance per counter to be able to pass through here
|
||||
// 4+ counters will always pass. 0 counters will never
|
||||
int currentNum = source.getCounters(abCost.getCounterType());
|
||||
double percent = .25 * (currentNum / abCost.getCounterNum());
|
||||
if (percent <= r.nextFloat())
|
||||
return false;
|
||||
}
|
||||
if (!CostUtil.checkRemoveCounterCost(abCost, source))
|
||||
return false;
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
@@ -1565,24 +1548,19 @@ public class AbilityFactory_ChangeZone {
|
||||
private static boolean changeZoneAllCanPlayAI(AbilityFactory af, SpellAbility sa) {
|
||||
// Change Zone All, can be any type moving from one zone to another
|
||||
Cost abCost = af.getAbCost();
|
||||
//Card source = af.getHostCard();
|
||||
Card source = sa.getSourceCard();
|
||||
HashMap<String, String> params = af.getMapParams();
|
||||
String destination = params.get("Destination");
|
||||
String origin = params.get("Origin");
|
||||
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost()) {
|
||||
// Sac is ok in general, but should add some decision making based off what we Sacrifice and what we might get
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
|
||||
if (abCost.getSubCounter())
|
||||
; // subcounter is fine
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -171,18 +173,10 @@ public class AbilityFactory_CounterMagic {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost() && !abCost.getSacThis()) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String type = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(type.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
}
|
||||
|
||||
Target tgt = sa.getTarget();
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
import forge.gui.input.Input;
|
||||
@@ -221,25 +223,20 @@ public class AbilityFactory_Counters {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost() && (!abCost.getSacThis() || source.isCreature())) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String sacType = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(sacType.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) return false;
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
// A card has a 25% chance per counter to be able to pass through here
|
||||
// 4+ counters will always pass. 0 counters will never
|
||||
int currentNum = source.getCounters(abCost.getCounterType());
|
||||
double percent = .25 * (currentNum / abCost.getCounterNum());
|
||||
if (percent <= r.nextFloat())
|
||||
return false;
|
||||
}
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (CostUtil.checkCreatureSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(abCost, source))
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO handle proper calculation of X values based on Cost
|
||||
@@ -743,25 +740,17 @@ public class AbilityFactory_Counters {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost() && !abCost.getSacThis()) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String sacType = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(sacType.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) return false;
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
// A card has a 25% chance per counter to be able to pass through here
|
||||
// 4+ counters will always pass. 0 counters will never
|
||||
int currentNum = source.getCounters(abCost.getCounterType());
|
||||
double percent = .25 * (currentNum / abCost.getCounterNum());
|
||||
if (percent <= r.nextFloat())
|
||||
return false;
|
||||
}
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(abCost, source))
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO handle proper calculation of X values based on Cost
|
||||
@@ -1363,11 +1352,14 @@ public class AbilityFactory_Counters {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost()) {
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 8))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) return false;
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
}
|
||||
|
||||
if (tgt != null) {
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -238,23 +240,14 @@ public class AbilityFactory_DealDamage {
|
||||
boolean rr = AF.isSpell();
|
||||
|
||||
// temporarily disabled until better AI
|
||||
if (abCost.getSacCost() && !abCost.getSacThis() && AllZone.getHumanPlayer().getLife() - dmg > 0) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String sacType = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(sacType.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
if (AF.getAbCost().getSubCounter()) {
|
||||
// +1/+1 counters only if damage from this ability would kill the human, otherwise ok
|
||||
if (AllZone.getHumanPlayer().getLife() - dmg > 0 && AF.getAbCost().getCounterType().equals(Counters.P1P1))
|
||||
return false;
|
||||
}
|
||||
if (AF.getAbCost().getLifeCost()) {
|
||||
if (AllZone.getHumanPlayer().getLife() - dmg > 0) // only if damage from this ability would kill the human
|
||||
return false;
|
||||
}
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (source.getName().equals("Stuffy Doll")) {
|
||||
// Now stuffy sits around for blocking
|
||||
@@ -805,18 +798,8 @@ public class AbilityFactory_DealDamage {
|
||||
//abCost stuff that should probably be centralized...
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for some costs
|
||||
if (abCost.getSacCost()) {
|
||||
//OK
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) ; //OK
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
// OK
|
||||
}
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: if damage is dependant on mana paid, maybe have X be human's max life
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
|
||||
import java.util.*;
|
||||
@@ -194,28 +196,21 @@ public class AbilityFactory_Debuff {
|
||||
*/
|
||||
private static boolean debuffCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
|
||||
// if there is no target and host card isn't in play, don't activate
|
||||
if (af.getAbTgt() == null && !AllZoneUtil.isCardInPlay(af.getHostCard()))
|
||||
Card source = sa.getSourceCard();
|
||||
if (sa.getTarget() == null && !AllZoneUtil.isCardInPlay(source))
|
||||
return false;
|
||||
|
||||
Cost cost = sa.getPayCosts();
|
||||
|
||||
// temporarily disabled until AI is improved
|
||||
if (af.getAbCost().getSacCost() && sa.getSourceCard().isCreature()) return false;
|
||||
if (af.getAbCost().getLifeCost()) {
|
||||
if (!CostUtil.checkCreatureSacrificeCost(cost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkLifeCost(cost, source, 40))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(cost, source))
|
||||
return false;
|
||||
}
|
||||
if (af.getAbCost().getSubCounter()) {
|
||||
// instead of never removing counters, we will have a random possibility of failure.
|
||||
// all the other tests still need to pass if a counter will be removed
|
||||
Counters count = af.getAbCost().getCounterType();
|
||||
double chance = .66;
|
||||
if (count.equals(Counters.P1P1)) { // 10% chance to remove +1/+1 to pump
|
||||
chance = .1;
|
||||
} else if (count.equals(Counters.CHARGE)) { // 50% chance to remove charge to pump
|
||||
chance = .5;
|
||||
}
|
||||
Random r = MyRandom.random;
|
||||
if (r.nextFloat() > chance)
|
||||
return false;
|
||||
}
|
||||
|
||||
HashMap<String, String> params = af.getMapParams();
|
||||
SpellAbility_Restriction restrict = sa.getRestrictions();
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -156,23 +158,14 @@ public class AbilityFactory_Destroy {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for some costs
|
||||
if (abCost.getSacCost() && !abCost.getSacThis()) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String sacType = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(sacType.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
// OK
|
||||
}
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
@@ -607,18 +600,9 @@ public class AbilityFactory_Destroy {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for some costs
|
||||
if (abCost.getSacCost()) {
|
||||
//OK
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) ;//OK
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
// OK
|
||||
}
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
import forge.gui.input.Input_PayManaCostUtil;
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
|
||||
@@ -176,13 +178,13 @@ public class AbilityFactory_PermanentState {
|
||||
*/
|
||||
private static boolean untapCanPlayAI(final AbilityFactory af, SpellAbility sa) {
|
||||
// AI cannot use this properly until he can use SAs during Humans turn
|
||||
|
||||
if (af.getAbCost().getAddCounter())
|
||||
if (af.getAbCost().getCounterType().equals(Counters.M1M1))
|
||||
return false;
|
||||
|
||||
Target tgt = af.getAbTgt();
|
||||
//Card source = sa.getSourceCard();
|
||||
Target tgt = sa.getTarget();
|
||||
Card source = sa.getSourceCard();
|
||||
Cost cost = sa.getPayCosts();
|
||||
|
||||
|
||||
if (!CostUtil.checkAddM1M1CounterCost(cost, source))
|
||||
return false;
|
||||
|
||||
Random r = MyRandom.random;
|
||||
boolean randomReturn = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn() + 1);
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -178,12 +180,20 @@ public class AbilityFactory_PreventDamage {
|
||||
final Card hostCard = af.getHostCard();
|
||||
boolean chance = false;
|
||||
|
||||
Cost cost = sa.getPayCosts();
|
||||
|
||||
// temporarily disabled until better AI
|
||||
if (af.getAbCost().getSacCost()) return false;
|
||||
if (af.getAbCost().getSubCounter())
|
||||
if (af.getAbCost().getCounterType().equals(Counters.P1P1))
|
||||
return false;
|
||||
if (af.getAbCost().getLifeCost()) return false;
|
||||
if (!CostUtil.checkLifeCost(cost, hostCard, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
Target tgt = af.getAbTgt();
|
||||
if (tgt == null) {
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
|
||||
@@ -209,28 +211,20 @@ public class AbilityFactory_Protection {
|
||||
if(af.getAbTgt() == null && !AllZoneUtil.isCardInPlay(hostCard))
|
||||
return false;
|
||||
|
||||
// temporarily disabled until AI is improved
|
||||
if(af.getAbCost().getSacCost() && sa.getSourceCard().isCreature()) return false;
|
||||
if(af.getAbCost().getLifeCost()) {
|
||||
if(!af.isCurse()) return false; //Use life only to kill creatures
|
||||
if(AllZone.getComputerPlayer().getLife() - af.getAbCost().getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if(af.getAbCost().getSubCounter()) {
|
||||
// instead of never removing counters, we will have a random possibility of failure.
|
||||
// all the other tests still need to pass if a counter will be removed
|
||||
Counters count = af.getAbCost().getCounterType();
|
||||
double chance = .66;
|
||||
if(count.equals(Counters.P1P1)) { // 10% chance to remove +1/+1 to protect
|
||||
chance = .1;
|
||||
}
|
||||
else if(count.equals(Counters.CHARGE)) { // 50% chance to remove charge to protect
|
||||
chance = .5;
|
||||
}
|
||||
Random r = MyRandom.random;
|
||||
if(r.nextFloat() > chance)
|
||||
return false;
|
||||
}
|
||||
Cost cost = sa.getPayCosts();
|
||||
|
||||
// temporarily disabled until better AI
|
||||
if (!CostUtil.checkLifeCost(cost, hostCard, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkCreatureSacrificeCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
// Phase Restrictions
|
||||
if(AllZone.getStack().size() == 0 && AllZone.getPhase().isBefore(Constant.Phase.Combat_FirstStrikeDamage)) {
|
||||
@@ -768,14 +762,20 @@ public class AbilityFactory_Protection {
|
||||
if(af.getAbTgt() == null && !AllZoneUtil.isCardInPlay(hostCard))
|
||||
return false;
|
||||
|
||||
// temporarily disabled until AI is improved
|
||||
if(af.getAbCost().getSacCost()) return false;
|
||||
if(af.getAbCost().getLifeCost()) {
|
||||
return false;
|
||||
}
|
||||
if(af.getAbCost().getSubCounter()) {
|
||||
return false;
|
||||
}
|
||||
Cost cost = sa.getPayCosts();
|
||||
|
||||
// temporarily disabled until better AI
|
||||
if (!CostUtil.checkLifeCost(cost, hostCard, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}//protectAllCanPlayAI()
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -303,30 +305,20 @@ public class AbilityFactory_Pump {
|
||||
if (AF.getAbTgt() == null && !AllZoneUtil.isCardInPlay(hostCard))
|
||||
return false;
|
||||
|
||||
Cost cost = sa.getPayCosts();
|
||||
|
||||
// temporarily disabled until AI is improved
|
||||
if (AF.getAbCost().getSacCost() && sa.getSourceCard().isCreature()) return false;
|
||||
if (AF.getAbCost().getLifeCost()) {
|
||||
if (!AF.isCurse()) return false; //Use life only to kill creatures
|
||||
if (AllZone.getComputerPlayer().getLife() - AF.getAbCost().getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (AF.getAbCost().getDiscardCost() && !AF.isCurse()) {
|
||||
return false;
|
||||
}
|
||||
if (AF.getAbCost().getSubCounter()) {
|
||||
// instead of never removing counters, we will have a random possibility of failure.
|
||||
// all the other tests still need to pass if a counter will be removed
|
||||
Counters count = AF.getAbCost().getCounterType();
|
||||
double chance = .66;
|
||||
if (count.equals(Counters.P1P1)) { // 10% chance to remove +1/+1 to pump
|
||||
chance = .1;
|
||||
} else if (count.equals(Counters.CHARGE)) { // 50% chance to remove charge to pump
|
||||
chance = .5;
|
||||
}
|
||||
Random r = MyRandom.random;
|
||||
if (r.nextFloat() > chance)
|
||||
return false;
|
||||
}
|
||||
if (!CostUtil.checkLifeCost(cost, hostCard, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkCreatureSacrificeCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(cost, hostCard))
|
||||
return false;
|
||||
|
||||
SpellAbility_Restriction restrict = sa.getRestrictions();
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -183,18 +185,14 @@ public class AbilityFactory_Regenerate {
|
||||
Cost abCost = af.getAbCost();
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost() && !abCost.getSacThis()) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String type = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(type.split(","), hostCard.getController(), hostCard);
|
||||
if (ComputerUtil.getCardPreference(hostCard, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (!CostUtil.checkLifeCost(abCost, hostCard, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(abCost, hostCard))
|
||||
return false;
|
||||
|
||||
if (CostUtil.checkCreatureSacrificeCost(abCost, hostCard))
|
||||
return false;
|
||||
}
|
||||
|
||||
Target tgt = sa.getTarget();
|
||||
@@ -550,18 +548,14 @@ public class AbilityFactory_Regenerate {
|
||||
Cost abCost = af.getAbCost();
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost() && !abCost.getSacThis()) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String type = abCost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(type.split(","), hostCard.getController(), hostCard);
|
||||
if (ComputerUtil.getCardPreference(hostCard, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (!CostUtil.checkSacrificeCost(abCost, hostCard))
|
||||
return false;
|
||||
|
||||
if (CostUtil.checkCreatureSacrificeCost(abCost, hostCard))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkLifeCost(abCost, hostCard, 4))
|
||||
return false;
|
||||
}
|
||||
|
||||
// filter AIs battlefield by what I can target
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
|
||||
@@ -595,22 +597,22 @@ public class AbilityFactory_Reveal {
|
||||
*/
|
||||
private static boolean revealHandCanPlayAI(final AbilityFactory af, SpellAbility sa) {
|
||||
// AI cannot use this properly until he can use SAs during Humans turn
|
||||
Cost abCost = af.getAbCost();
|
||||
Cost abCost = sa.getPayCosts();
|
||||
Card source = sa.getSourceCard();
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost()) {
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
if (abCost.getCounterType().equals(Counters.P1P1)) return false; // Other counters should be used
|
||||
}
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(abCost, source))
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -347,15 +349,10 @@ public class AbilityFactory_Sacrifice {
|
||||
msg = valid;
|
||||
|
||||
msg = "Sacrifice a " + msg;
|
||||
|
||||
boolean remSacrificed = params.containsKey("RememberSacrificed");
|
||||
if (remSacrificed)
|
||||
card.clearRemembered();
|
||||
|
||||
if (valid.equals("Self")) {
|
||||
if (AllZone.getZone(sa.getSourceCard()).is(Constant.Zone.Battlefield))
|
||||
if (AllZone.getGameAction().sacrifice(sa.getSourceCard()) && remSacrificed)
|
||||
card.addRemembered(sa.getSourceCard());
|
||||
AllZone.getGameAction().sacrifice(sa.getSourceCard());
|
||||
}
|
||||
//TODO - maybe this can be done smarter...
|
||||
else if (valid.equals("Card.AttachedBy")) {
|
||||
@@ -592,18 +589,8 @@ public class AbilityFactory_Sacrifice {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for some costs
|
||||
if (abCost.getSacCost()) {
|
||||
//OK
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) ;//OK
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
// OK
|
||||
}
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
|
||||
@@ -10,16 +10,16 @@ import forge.CardList;
|
||||
import forge.Command;
|
||||
import forge.ComputerUtil;
|
||||
import forge.Constant;
|
||||
import forge.Counters;
|
||||
import forge.MyRandom;
|
||||
import forge.Player;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.spellability.Ability_Activated;
|
||||
import forge.card.spellability.Ability_Sub;
|
||||
import forge.card.spellability.Cost;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.trigger.Trigger;
|
||||
import forge.card.trigger.TriggerHandler;
|
||||
|
||||
@@ -266,28 +266,17 @@ public class AbilityFactory_Token extends AbilityFactory {
|
||||
}
|
||||
|
||||
if (cost != null) {
|
||||
if (cost.getSacCost() && !cost.getSacThis()) {
|
||||
//only sacrifice something that's supposed to be sacrificed
|
||||
String type = cost.getSacType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(type.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
if (cost.getSubCounter()) {
|
||||
if (cost.getCounterType().equals(Counters.P1P1)) {
|
||||
// A card has a 25% chance per counter to be able to pass through here
|
||||
// 4+ counters will always pass. 0 counters will never
|
||||
int currentNum = source.getCounters(cost.getCounterType());
|
||||
double percent = .25 * (currentNum / cost.getCounterNum());
|
||||
if (percent <= r.nextFloat())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (cost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - cost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (!CostUtil.checkLifeCost(cost, source, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(cost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(cost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(cost, source))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tokenAmount.equals("X")) {
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.card.abilityFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
|
||||
@@ -186,24 +188,23 @@ public class AbilityFactory_ZoneAffecting {
|
||||
private static boolean drawCanPlayAI(final AbilityFactory af, SpellAbility sa) {
|
||||
HashMap<String, String> params = af.getMapParams();
|
||||
|
||||
Target tgt = af.getAbTgt();
|
||||
Target tgt = sa.getTarget();
|
||||
Card source = sa.getSourceCard();
|
||||
Cost abCost = af.getAbCost();
|
||||
Cost abCost = sa.getPayCosts();
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost() && source.isCreature()) {
|
||||
if (CostUtil.checkCreatureSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
if (abCost.getCounterType().equals(Counters.P1P1)) return false; // Other counters should be used
|
||||
}
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(abCost, source))
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@@ -595,18 +596,17 @@ public class AbilityFactory_ZoneAffecting {
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost()) {
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
if (abCost.getCounterType().equals(Counters.P1P1)) return false; // Other counters should be used
|
||||
}
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(abCost, source))
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@@ -1105,24 +1105,23 @@ public class AbilityFactory_ZoneAffecting {
|
||||
private static boolean discardCanPlayAI(final AbilityFactory af, SpellAbility sa) {
|
||||
HashMap<String, String> params = af.getMapParams();
|
||||
|
||||
Target tgt = af.getAbTgt();
|
||||
Target tgt = sa.getTarget();
|
||||
Card source = sa.getSourceCard();
|
||||
Cost abCost = af.getAbCost();
|
||||
Cost abCost = sa.getPayCosts();
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (abCost.getSacCost()) {
|
||||
if (!CostUtil.checkSacrificeCost(abCost, source))
|
||||
return false;
|
||||
}
|
||||
if (abCost.getLifeCost()) {
|
||||
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
|
||||
return false;
|
||||
}
|
||||
if (abCost.getDiscardCost()) return false;
|
||||
|
||||
if (abCost.getSubCounter()) {
|
||||
if (abCost.getCounterType().equals(Counters.P1P1)) return false; // Other counters should be used
|
||||
}
|
||||
if (!CostUtil.checkLifeCost(abCost, source, 4))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkDiscardCost(abCost, source))
|
||||
return false;
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(abCost, source))
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import forge.FileUtil;
|
||||
import forge.Player;
|
||||
import forge.PlayerZone;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.card.trigger.Trigger;
|
||||
import forge.game.GameLossReason;
|
||||
|
||||
@@ -2,6 +2,7 @@ package forge.card.cardFactory;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.card.trigger.Trigger;
|
||||
@@ -907,7 +908,7 @@ public class CardFactoryUtil {
|
||||
* @param sourceCard
|
||||
* a {@link forge.Card} object.
|
||||
* @param cost
|
||||
* a {@link forge.card.spellability.Cost} object.
|
||||
* a {@link forge.card.cost.Cost} object.
|
||||
* @param orgManaCost
|
||||
* a {@link java.lang.String} object.
|
||||
* @param a
|
||||
@@ -1258,7 +1259,7 @@ public class CardFactoryUtil {
|
||||
* @param extrinsicKeywords
|
||||
* an array of {@link java.lang.String} objects.
|
||||
* @param abCost
|
||||
* a {@link forge.card.spellability.Cost} object.
|
||||
* a {@link forge.card.cost.Cost} object.
|
||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public static SpellAbility eqPump_Equip(final Card sourceCard, final int Power, final int Tough,
|
||||
@@ -1370,7 +1371,7 @@ public class CardFactoryUtil {
|
||||
* @param extrinsicKeywords
|
||||
* an array of {@link java.lang.String} objects.
|
||||
* @param abCost
|
||||
* a {@link forge.card.spellability.Cost} object.
|
||||
* a {@link forge.card.cost.Cost} object.
|
||||
* @return a {@link forge.Command} object.
|
||||
*/
|
||||
public static Command eqPump_onEquip(final Card sourceCard, final int Power, final int Tough,
|
||||
@@ -1414,7 +1415,7 @@ public class CardFactoryUtil {
|
||||
* @param extrinsicKeywords
|
||||
* an array of {@link java.lang.String} objects.
|
||||
* @param abCost
|
||||
* a {@link forge.card.spellability.Cost} object.
|
||||
* a {@link forge.card.cost.Cost} object.
|
||||
* @return a {@link forge.Command} object.
|
||||
*/
|
||||
public static Command eqPump_unEquip(final Card sourceCard, final int Power, final int Tough,
|
||||
|
||||
@@ -13,8 +13,8 @@ import forge.Command;
|
||||
import forge.Constant;
|
||||
import forge.Player;
|
||||
import forge.PlayerZone;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.Cost;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Spell_Permanent;
|
||||
|
||||
@@ -4,6 +4,7 @@ package forge.card.cardFactory;
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import forge.*;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.card.trigger.Trigger;
|
||||
import forge.card.trigger.TriggerHandler;
|
||||
|
||||
@@ -2,6 +2,7 @@ package forge.card.cardFactory;
|
||||
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.card.trigger.Trigger;
|
||||
import forge.card.trigger.TriggerHandler;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.card.cardFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
import forge.gui.input.Input;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.card.cardFactory;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
import forge.gui.input.Input;
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.card.cardFactory;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
import forge.gui.input.Input;
|
||||
|
||||
@@ -2,6 +2,7 @@ package forge.card.cardFactory;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.GuiUtils;
|
||||
import forge.gui.input.Input;
|
||||
|
||||
471
src/main/java/forge/card/cost/Cost.java
Normal file
471
src/main/java/forge/card/cost/Cost.java
Normal file
@@ -0,0 +1,471 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import forge.AllZone;
|
||||
import forge.Card;
|
||||
import forge.Constant;
|
||||
import forge.Counters;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
/**
|
||||
* <p>Cost class.</p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Cost {
|
||||
private boolean isAbility = true;
|
||||
ArrayList<CostPart> costParts = new ArrayList<CostPart>();
|
||||
|
||||
public ArrayList<CostPart> getCostParts(){ return costParts; }
|
||||
|
||||
private boolean sacCost = false;
|
||||
|
||||
/**
|
||||
* <p>Getter for the field <code>sacCost</code>.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean getSacCost() {
|
||||
return sacCost;
|
||||
}
|
||||
|
||||
private boolean tapCost = false;
|
||||
|
||||
/**
|
||||
* <p>getTap.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean getTap() {
|
||||
return tapCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>hasNoManaCost.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean hasNoManaCost() {
|
||||
for(CostPart part : costParts)
|
||||
if (part instanceof CostMana)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isOnlyManaCost.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isOnlyManaCost() {
|
||||
// Only used by Morph and Equip... why do we need this?
|
||||
for(CostPart part : costParts)
|
||||
if (!(part instanceof CostMana))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>getTotalMana.</p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public String getTotalMana() {
|
||||
for(CostPart part : costParts)
|
||||
if (part instanceof CostMana)
|
||||
return part.toString();
|
||||
|
||||
return "0";
|
||||
}
|
||||
|
||||
private String name;
|
||||
|
||||
// Parsing Strings
|
||||
private final static String tapXStr = "tapXType<";
|
||||
private final static String subStr = "SubCounter<";
|
||||
private final static String addStr = "AddCounter<";
|
||||
private final static String lifeStr = "PayLife<";
|
||||
private final static String discStr = "Discard<";
|
||||
private final static String sacStr = "Sac<";
|
||||
private final static String exileStr = "Exile<";
|
||||
private final static String exileFromHandStr = "ExileFromHand<";
|
||||
private final static String exileFromGraveStr = "ExileFromGrave<";
|
||||
private final static String exileFromTopStr = "ExileFromTop<";
|
||||
private final static String returnStr = "Return<";
|
||||
|
||||
/**
|
||||
* <p>Constructor for Cost.</p>
|
||||
*
|
||||
* @param parse a {@link java.lang.String} object.
|
||||
* @param cardName a {@link java.lang.String} object.
|
||||
* @param bAbility a boolean.
|
||||
*/
|
||||
public Cost(String parse, String cardName, boolean bAbility) {
|
||||
isAbility = bAbility;
|
||||
// when adding new costs for cost string, place them here
|
||||
name = cardName;
|
||||
|
||||
while (parse.contains(tapXStr)) {
|
||||
String[] splitStr = abCostParse(parse, tapXStr, 3);
|
||||
parse = abUpdateParse(parse, tapXStr);
|
||||
|
||||
String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
costParts.add(new CostTapType(splitStr[0], splitStr[1], description));
|
||||
}
|
||||
|
||||
while (parse.contains(subStr)) {
|
||||
// SubCounter<NumCounters/CounterType>
|
||||
String[] splitStr = abCostParse(parse, subStr, 4);
|
||||
parse = abUpdateParse(parse, subStr);
|
||||
|
||||
String type = splitStr.length > 2 ? splitStr[2] : null;
|
||||
String description = splitStr.length > 3 ? splitStr[3] : null;
|
||||
|
||||
costParts.add(new CostRemoveCounter(splitStr[0], Counters.valueOf(splitStr[1]), type, description));
|
||||
}
|
||||
|
||||
|
||||
while (parse.contains(addStr)) {
|
||||
// AddCounter<NumCounters/CounterType>
|
||||
String[] splitStr = abCostParse(parse, addStr, 2);
|
||||
parse = abUpdateParse(parse, addStr);
|
||||
|
||||
costParts.add(new CostPutCounter(splitStr[0], Counters.valueOf(splitStr[1])));
|
||||
}
|
||||
|
||||
// While no card has "PayLife<2> PayLife<3> there might be a card that Changes Cost by adding a Life Payment
|
||||
while (parse.contains(lifeStr)) {
|
||||
// PayLife<LifeCost>
|
||||
String[] splitStr = abCostParse(parse, lifeStr, 1);
|
||||
parse = abUpdateParse(parse, lifeStr);
|
||||
|
||||
costParts.add(new CostPayLife(splitStr[0]));
|
||||
}
|
||||
|
||||
|
||||
while (parse.contains(discStr)) {
|
||||
// Discard<NumCards/Type>
|
||||
String[] splitStr = abCostParse(parse, discStr, 3);
|
||||
parse = abUpdateParse(parse, discStr);
|
||||
|
||||
String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
costParts.add(new CostDiscard(splitStr[0], splitStr[1], description));
|
||||
}
|
||||
|
||||
|
||||
while (parse.contains(sacStr)) {
|
||||
sacCost = true;
|
||||
String[] splitStr = abCostParse(parse, sacStr, 3);
|
||||
parse = abUpdateParse(parse, sacStr);
|
||||
|
||||
String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
costParts.add(new CostSacrifice(splitStr[0], splitStr[1], description));
|
||||
}
|
||||
|
||||
|
||||
while (parse.contains(exileStr)) {
|
||||
String[] splitStr = abCostParse(parse, exileStr, 3);
|
||||
parse = abUpdateParse(parse, exileStr);
|
||||
|
||||
String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
costParts.add(new CostExile(splitStr[0], splitStr[1], description, Constant.Zone.Battlefield));
|
||||
}
|
||||
|
||||
|
||||
while (parse.contains(exileFromHandStr)) {
|
||||
String[] splitStr = abCostParse(parse, exileFromHandStr, 3);
|
||||
parse = abUpdateParse(parse, exileFromHandStr);
|
||||
|
||||
String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
costParts.add(new CostExile(splitStr[0], splitStr[1], description, Constant.Zone.Hand));
|
||||
}
|
||||
|
||||
|
||||
while (parse.contains(exileFromGraveStr)) {
|
||||
String[] splitStr = abCostParse(parse, exileFromGraveStr, 3);
|
||||
parse = abUpdateParse(parse, exileFromGraveStr);
|
||||
|
||||
String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
costParts.add(new CostExile(splitStr[0], splitStr[1], description, Constant.Zone.Graveyard));
|
||||
}
|
||||
|
||||
|
||||
while (parse.contains(exileFromTopStr)) {
|
||||
String[] splitStr = abCostParse(parse, exileFromTopStr, 3);
|
||||
parse = abUpdateParse(parse, exileFromTopStr);
|
||||
|
||||
String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
costParts.add(new CostExile(splitStr[0], splitStr[1], description, Constant.Zone.Library));
|
||||
}
|
||||
|
||||
|
||||
while (parse.contains(returnStr)) {
|
||||
String[] splitStr = abCostParse(parse, returnStr, 3);
|
||||
parse = abUpdateParse(parse, returnStr);
|
||||
|
||||
String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
costParts.add(new CostReturn(splitStr[0], splitStr[1], description));
|
||||
}
|
||||
|
||||
// These won't show up with multiples
|
||||
if (parse.contains("Untap")) {
|
||||
parse = parse.replace("Untap", "").trim();
|
||||
costParts.add(0, new CostUntap());
|
||||
}
|
||||
|
||||
if (parse.contains("Q")) {
|
||||
parse = parse.replace("Q", "").trim();
|
||||
costParts.add(0, new CostUntap());
|
||||
}
|
||||
|
||||
if (parse.contains("T")) {
|
||||
tapCost = true;
|
||||
parse = parse.replace("T", "").trim();
|
||||
costParts.add(0, new CostTap());
|
||||
}
|
||||
|
||||
String stripXCost = parse.replaceAll("X", "");
|
||||
|
||||
int amountX = parse.length() - stripXCost.length();
|
||||
|
||||
String mana = stripXCost.trim();
|
||||
if (mana.equals(""))
|
||||
mana = "0";
|
||||
|
||||
if (amountX > 0 || !mana.equals("0"))
|
||||
costParts.add(0, new CostMana(mana, amountX));
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>abCostParse.</p>
|
||||
*
|
||||
* @param parse a {@link java.lang.String} object.
|
||||
* @param subkey a {@link java.lang.String} object.
|
||||
* @param numParse a int.
|
||||
* @return an array of {@link java.lang.String} objects.
|
||||
*/
|
||||
private String[] abCostParse(String parse, String subkey, int numParse) {
|
||||
int startPos = parse.indexOf(subkey);
|
||||
int endPos = parse.indexOf(">", startPos);
|
||||
String str = parse.substring(startPos, endPos);
|
||||
|
||||
str = str.replace(subkey, "");
|
||||
|
||||
String[] splitStr = str.split("/", numParse);
|
||||
return splitStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>abUpdateParse.</p>
|
||||
*
|
||||
* @param parse a {@link java.lang.String} object.
|
||||
* @param subkey a {@link java.lang.String} object.
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
private String abUpdateParse(String parse, String subkey) {
|
||||
int startPos = parse.indexOf(subkey);
|
||||
int endPos = parse.indexOf(">", startPos);
|
||||
String str = parse.substring(startPos, endPos + 1);
|
||||
return parse.replace(str, "").trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>changeCost.</p>
|
||||
*
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public void changeCost(SpellAbility sa) {
|
||||
// TODO: Change where ChangeCost happens
|
||||
for(CostPart part : costParts){
|
||||
if (part instanceof CostMana){
|
||||
CostMana costMana = (CostMana)part;
|
||||
|
||||
if (getTotalMana() != "0") { // 11/15/10 use getTotalMana() to account for X reduction
|
||||
String mana = getTotalMana();
|
||||
costMana.setAdjustedMana(AllZone.getGameAction().getSpellCostChange(sa, new ManaCost(mana)).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>refundPaidCost.</p>
|
||||
*
|
||||
* @param source a {@link forge.Card} object.
|
||||
*/
|
||||
public void refundPaidCost(Card source) {
|
||||
// prereq: isUndoable is called first
|
||||
for(CostPart part : costParts)
|
||||
part.refund(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isUndoable.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isUndoable() {
|
||||
for(CostPart part : costParts)
|
||||
if (!part.isUndoable())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isReusuableResource.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isReusuableResource() {
|
||||
for(CostPart part : costParts)
|
||||
if (!part.isReusable())
|
||||
return false;
|
||||
|
||||
return isAbility;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>toString.</p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public String toString() {
|
||||
if (isAbility)
|
||||
return abilityToString();
|
||||
else
|
||||
return spellToString(true);
|
||||
}
|
||||
|
||||
// maybe add a conversion method that turns the amounts into words 1=a(n), 2=two etc.
|
||||
|
||||
/**
|
||||
* <p>toStringAlt.</p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public String toStringAlt() {
|
||||
return spellToString(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>spellToString.</p>
|
||||
*
|
||||
* @param bFlag a boolean.
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
private String spellToString(boolean bFlag) {
|
||||
StringBuilder cost = new StringBuilder();
|
||||
boolean first = true;
|
||||
|
||||
if (bFlag)
|
||||
cost.append("As an additional cost to cast ").append(name).append(", ");
|
||||
else{
|
||||
// usually no additional mana cost for spells
|
||||
// only three Alliances cards have additional mana costs, but they are basically kicker/multikicker
|
||||
/*
|
||||
if (!getTotalMana().equals("0")) {
|
||||
cost.append("pay ").append(getTotalMana());
|
||||
first = false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
for(CostPart part : costParts){
|
||||
if (part instanceof CostMana)
|
||||
continue;
|
||||
if (!first)
|
||||
cost.append("and ");
|
||||
cost.append(part.toString()).append(" ");
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (first)
|
||||
return "";
|
||||
|
||||
if (bFlag)
|
||||
cost.append(".").append("\n");
|
||||
|
||||
return cost.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>abilityToString.</p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
private String abilityToString() {
|
||||
StringBuilder cost = new StringBuilder();
|
||||
boolean first = true;
|
||||
|
||||
for(CostPart part : costParts){
|
||||
if (!first)
|
||||
cost.append(", ");
|
||||
cost.append(part.toString());
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (first) // No costs, append 0
|
||||
cost.append("0");
|
||||
|
||||
cost.append(": ");
|
||||
return cost.toString();
|
||||
}
|
||||
|
||||
// TODO: If a Cost needs to pay more than 10 of something, fill this array as appropriate
|
||||
/** Constant <code>numNames="{zero, a, two, three, four, five, six, "{trunked}</code> */
|
||||
private static final String[] numNames = {"zero", "a", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};
|
||||
/** Constant <code>vowelPattern</code> */
|
||||
private static final Pattern vowelPattern = Pattern.compile("^[aeiou]", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
|
||||
public static String convertAmountTypeToWords(Integer i, String amount, String type){
|
||||
if (i == null)
|
||||
return convertAmountTypeToWords(amount, type);
|
||||
|
||||
return convertIntAndTypeToWords(i.intValue(), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>convertIntAndTypeToWords.</p>
|
||||
*
|
||||
* @param i a int.
|
||||
* @param type a {@link java.lang.String} object.
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public static String convertIntAndTypeToWords(int i, String type) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (i >= numNames.length) {
|
||||
sb.append(i);
|
||||
} else if (1 == i && vowelPattern.matcher(type).find())
|
||||
sb.append("an");
|
||||
else
|
||||
sb.append(numNames[i]);
|
||||
|
||||
sb.append(" ");
|
||||
sb.append(type);
|
||||
if (1 != i)
|
||||
sb.append("s");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public static String convertAmountTypeToWords(String amount, String type) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(amount);
|
||||
sb.append(" ");
|
||||
sb.append(type);
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
190
src/main/java/forge/card/cost/CostDiscard.java
Normal file
190
src/main/java/forge/card/cost/CostDiscard.java
Normal file
@@ -0,0 +1,190 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.AllZone;
|
||||
import forge.AllZoneUtil;
|
||||
import forge.Card;
|
||||
import forge.CardList;
|
||||
import forge.CardListUtil;
|
||||
import forge.Constant;
|
||||
import forge.Player;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostDiscard extends CostPartWithList {
|
||||
// Discard<Num/Type{/TypeDescription}>
|
||||
|
||||
public CostDiscard(String amount, String type, String description){
|
||||
this.amount = amount;
|
||||
this.type = type;
|
||||
this.typeDescription = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Discard");
|
||||
|
||||
Integer i = convertAmount();
|
||||
|
||||
if (getThis()) {
|
||||
sb.append(" ").append(type);
|
||||
}
|
||||
else if (type.equals("Hand")) {
|
||||
sb.append(" your hand");
|
||||
}
|
||||
else if (type.equals("LastDrawn")) {
|
||||
sb.append(" last drawn card");
|
||||
}
|
||||
else {
|
||||
StringBuilder desc = new StringBuilder();
|
||||
|
||||
if (type.equals("Card") || type.equals("Random"))
|
||||
desc.append("Card");
|
||||
else
|
||||
desc.append(typeDescription == null ? type : typeDescription).append(" card");
|
||||
|
||||
sb.append(Cost.convertAmountTypeToWords(i, amount, desc.toString()));
|
||||
|
||||
if (type.equals("Random"))
|
||||
sb.append(" at random");
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
CardList handList = AllZoneUtil.getPlayerHand(activator);
|
||||
String type = getType();
|
||||
Integer amount = convertAmount();
|
||||
|
||||
if (getThis()) {
|
||||
if (!AllZone.getZone(source).is(Constant.Zone.Hand))
|
||||
return false;
|
||||
} else if (type.equals("Hand")) {
|
||||
// this will always work
|
||||
} else if (type.equals("LastDrawn")) {
|
||||
Card c = activator.getLastDrawnCard();
|
||||
return handList.contains(c);
|
||||
} else {
|
||||
if (!type.equals("Random")) {
|
||||
handList = handList.getValidCards(type.split(";"), activator, source);
|
||||
}
|
||||
if (amount != null && amount > handList.size()) {
|
||||
// not enough cards in hand to pay
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
Player activator = ability.getActivatingPlayer();
|
||||
for (Card c : list)
|
||||
activator.discard(c, ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
Player activator = ability.getActivatingPlayer();
|
||||
CardList handList = AllZoneUtil.getPlayerHand(activator);
|
||||
String discType = getType();
|
||||
String amount = getAmount();
|
||||
|
||||
if (getThis()) {
|
||||
activator.discard(source, ability);
|
||||
payment.setPaidManaPart(this, true);
|
||||
} else if (discType.equals("Hand")) {
|
||||
activator.discardHand(ability);
|
||||
payment.setPaidManaPart(this, true);
|
||||
} else if (discType.equals("LastDrawn")) {
|
||||
if (handList.contains(activator.getLastDrawnCard())) {
|
||||
activator.discard(activator.getLastDrawnCard(), ability);
|
||||
payment.setPaidManaPart(this, true);
|
||||
}
|
||||
} else {
|
||||
Integer c = convertAmount();
|
||||
|
||||
if (discType.equals("Random")) {
|
||||
if (c == null){
|
||||
String sVar = source.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")){
|
||||
c = CostUtil.chooseXValue(source, handList.size());
|
||||
}
|
||||
else{
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
|
||||
activator.discardRandom(c, ability);
|
||||
payment.setPaidManaPart(this, true);
|
||||
} else {
|
||||
String validType[] = discType.split(";");
|
||||
handList = handList.getValidCards(validType, activator, ability.getSourceCard());
|
||||
|
||||
if (c == null){
|
||||
String sVar = source.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")){
|
||||
c = CostUtil.chooseXValue(source, handList.size());
|
||||
}
|
||||
else{
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
|
||||
CostUtil.setInput(Cost_Input.input_discardCost(discType, handList, ability, payment, this, c));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
String type = getType();
|
||||
Player activator = ability.getActivatingPlayer();
|
||||
CardList hand = AllZoneUtil.getPlayerHand(activator);
|
||||
resetList();
|
||||
if (type.equals("LastDrawn")){
|
||||
if (!hand.contains(activator.getLastDrawnCard()))
|
||||
return false;
|
||||
list.add(activator.getLastDrawnCard());
|
||||
}
|
||||
|
||||
else if (getThis()){
|
||||
if (!hand.contains(source))
|
||||
return false;
|
||||
|
||||
list.add(source);
|
||||
}
|
||||
|
||||
else if (type.equals("Hand")){
|
||||
list.addAll(hand);
|
||||
}
|
||||
|
||||
else{
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
|
||||
if (type.equals("Random")){
|
||||
list = CardListUtil.getRandomSubList(hand, c);
|
||||
}
|
||||
else{
|
||||
list = AllZone.getGameAction().AI_discardNumType(c, type.split(";"), ability);
|
||||
}
|
||||
}
|
||||
return list != null;
|
||||
}
|
||||
}
|
||||
127
src/main/java/forge/card/cost/CostExile.java
Normal file
127
src/main/java/forge/card/cost/CostExile.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.AllZone;
|
||||
import forge.AllZoneUtil;
|
||||
import forge.Card;
|
||||
import forge.CardList;
|
||||
import forge.ComputerUtil;
|
||||
import forge.Constant;
|
||||
import forge.Player;
|
||||
import forge.PlayerZone;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostExile extends CostPartWithList {
|
||||
//Exile<Num/Type{/TypeDescription}>
|
||||
//ExileFromHand<Num/Type{/TypeDescription}>
|
||||
//ExileFromGraveyard<Num/Type{/TypeDescription}>
|
||||
//ExileFromLibrary<Num/Type{/TypeDescription}>
|
||||
|
||||
private String from = Constant.Zone.Battlefield;
|
||||
|
||||
public String getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public CostExile(String amount, String type, String description, String from){
|
||||
this.amount = amount;
|
||||
this.type = type;
|
||||
this.typeDescription = description;
|
||||
if (from != null)
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Exile ");
|
||||
|
||||
if (getThis()) {
|
||||
sb.append(type);
|
||||
}
|
||||
else{
|
||||
Integer i = convertAmount();
|
||||
String desc = typeDescription == null ? type : typeDescription;
|
||||
|
||||
sb.append(Cost.convertAmountTypeToWords(i, amount, desc));
|
||||
}
|
||||
|
||||
if (from.equals("Battlefield")){
|
||||
if (!getThis())
|
||||
sb.append(" you control");
|
||||
}
|
||||
else{
|
||||
sb.append(" from your ").append(from);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
PlayerZone zone = AllZone.getZone(getFrom(), activator);
|
||||
if (!getThis()) {
|
||||
CardList typeList = AllZoneUtil.getCardsInZone(zone);
|
||||
|
||||
typeList = typeList.getValidCards(getType().split(";"), activator, source);
|
||||
|
||||
Integer amount = convertAmount();
|
||||
if (amount != null && typeList.size() < amount)
|
||||
return false;
|
||||
} else if (!AllZoneUtil.isCardInZone(zone, source))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
for (Card c : list)
|
||||
AllZone.getGameAction().exile(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
String amount = getAmount();
|
||||
Integer c = convertAmount();
|
||||
CardList list = AllZoneUtil.getCardsInZone(getFrom(), ability.getActivatingPlayer());
|
||||
if (c == null){
|
||||
String sVar = source.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")){
|
||||
c = CostUtil.chooseXValue(source, list.size());
|
||||
}
|
||||
else{
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
if (getThis())
|
||||
CostUtil.setInput(Cost_Input.exileThis(ability, payment, this));
|
||||
else
|
||||
CostUtil.setInput(Cost_Input.exileType(ability, this, getType(), payment, c));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
resetList();
|
||||
if (getThis())
|
||||
list.add(source);
|
||||
else{
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
list = ComputerUtil.chooseExileFrom(getFrom(), getType(), source, ability.getTargetCard(), c);
|
||||
if (list == null)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
104
src/main/java/forge/card/cost/CostMana.java
Normal file
104
src/main/java/forge/card/cost/CostMana.java
Normal file
@@ -0,0 +1,104 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import forge.Card;
|
||||
import forge.ComputerUtil;
|
||||
import forge.Player;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostMana extends CostPart {
|
||||
//"Leftover"
|
||||
private String mana = "";
|
||||
private int amountX = 0;
|
||||
private String adjustedMana = "";
|
||||
|
||||
public String getMana() {
|
||||
// Only used for Human to pay for non-X cost first
|
||||
return mana;
|
||||
}
|
||||
|
||||
public void setMana(String sCost) {
|
||||
mana = sCost;
|
||||
}
|
||||
|
||||
public boolean hasNoXManaCost() {
|
||||
return amountX == 0;
|
||||
}
|
||||
|
||||
public int getXMana() {
|
||||
return amountX;
|
||||
}
|
||||
|
||||
public void setXMana(int xCost) {
|
||||
amountX = xCost;
|
||||
}
|
||||
|
||||
public String getAdjustedMana() {
|
||||
return adjustedMana;
|
||||
}
|
||||
|
||||
public void setAdjustedMana(String adjustedMana) {
|
||||
this.adjustedMana = adjustedMana;
|
||||
}
|
||||
|
||||
public CostMana(String mana, int amount){
|
||||
this.mana = mana.trim();
|
||||
this.amountX = amount;
|
||||
this.isUndoable = true;
|
||||
this.isReusable = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(Strings.repeat("X ", amountX));
|
||||
if (!mana.equals("0"))
|
||||
sb.append(mana);
|
||||
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
// For now, this will always return true. But this should probably be checked at some point
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
ComputerUtil.payManaCost(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
int manaToAdd = 0;
|
||||
if (!hasNoXManaCost()) {
|
||||
// if X cost is a defined value, other than xPaid
|
||||
if (!source.getSVar("X").equals("Count$xPaid")) {
|
||||
// this currently only works for things about Targeted object
|
||||
manaToAdd = AbilityFactory.calculateAmount(source, "X", ability) * getXMana();
|
||||
}
|
||||
}
|
||||
if (!getMana().equals("0") || manaToAdd > 0)
|
||||
CostUtil.setInput(Cost_Input.input_payMana(ability, payment, this, manaToAdd));
|
||||
else if (getXMana() > 0)
|
||||
CostUtil.setInput(Cost_Input.input_payXMana(ability, payment, this, getXMana()));
|
||||
|
||||
// We return false here because the Inputs set above should recall payment.payCosts()
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
68
src/main/java/forge/card/cost/CostPart.java
Normal file
68
src/main/java/forge/card/cost/CostPart.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Player;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public abstract class CostPart {
|
||||
protected boolean isReusable = false;
|
||||
protected boolean isUndoable = false;
|
||||
protected boolean optional = false;
|
||||
protected String optionalType = null;
|
||||
protected String amount = "1";
|
||||
protected String type = "Card";
|
||||
protected String typeDescription = null;
|
||||
|
||||
public String getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean getThis() {
|
||||
return type.equals("CARDNAME");
|
||||
}
|
||||
|
||||
public String getTypeDescription() {
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
public String getDescriptiveType(){
|
||||
return typeDescription == null ? type : typeDescription;
|
||||
}
|
||||
|
||||
public boolean isReusable(){
|
||||
return isReusable;
|
||||
}
|
||||
|
||||
public boolean isUndoable(){
|
||||
return isUndoable;
|
||||
}
|
||||
|
||||
public String getOptionalType() {
|
||||
return optionalType;
|
||||
}
|
||||
|
||||
public void setOptionalType(String optionalType) {
|
||||
this.optionalType = optionalType;
|
||||
}
|
||||
|
||||
public Integer convertAmount(){
|
||||
Integer i = null;
|
||||
try{
|
||||
i = Integer.parseInt(amount);
|
||||
}catch(NumberFormatException e){}
|
||||
return i;
|
||||
}
|
||||
|
||||
public abstract boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost);
|
||||
|
||||
public abstract boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment);
|
||||
public abstract void payAI(SpellAbility ability, Card source, Cost_Payment payment);
|
||||
public abstract boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment);
|
||||
|
||||
public abstract String toString();
|
||||
public abstract void refund(Card source);
|
||||
}
|
||||
12
src/main/java/forge/card/cost/CostPartWithList.java
Normal file
12
src/main/java/forge/card/cost/CostPartWithList.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardList;
|
||||
|
||||
public abstract class CostPartWithList extends CostPart {
|
||||
protected CardList list = null;
|
||||
public CardList getList() { return list; }
|
||||
public void setList(CardList setList) { list = setList; }
|
||||
public void resetList() { list = new CardList(); }
|
||||
public void addToList(Card c) { list.add(c); }
|
||||
}
|
||||
109
src/main/java/forge/card/cost/CostPayLife.java
Normal file
109
src/main/java/forge/card/cost/CostPayLife.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.AllZone;
|
||||
import forge.Card;
|
||||
import forge.GameActionUtil;
|
||||
import forge.Player;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostPayLife extends CostPart {
|
||||
private int lastPaidAmount = 0;
|
||||
|
||||
public int getLastPaidAmount(){
|
||||
return lastPaidAmount;
|
||||
}
|
||||
|
||||
public void setLastPaidAmount(int paidAmount){
|
||||
lastPaidAmount = paidAmount;
|
||||
}
|
||||
|
||||
public CostPayLife(String amount){
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Pay ").append(amount).append(" Life");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
// Really should be activating player
|
||||
source.getController().payLife(lastPaidAmount * -1, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
Integer amount = convertAmount();
|
||||
if (amount != null && !activator.canPayLife(amount)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
AllZone.getComputerPlayer().payLife(getLastPaidAmount(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
String amount = getAmount();
|
||||
int life = ability.getActivatingPlayer().getLife();
|
||||
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
String sVar = source.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")){
|
||||
c = CostUtil.chooseXValue(source, life);
|
||||
}
|
||||
else{
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(source.getName()).append(" - Pay ").append(c).append(" Life?");
|
||||
|
||||
if (GameActionUtil.showYesNoDialog(source, sb.toString())) {
|
||||
AllZone.getHumanPlayer().payLife(c, null);
|
||||
setLastPaidAmount(c);
|
||||
payment.setPaidManaPart(this, true);
|
||||
} else {
|
||||
payment.setCancel(true);
|
||||
payment.getRequirements().finishPaying();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
Player activator = ability.getActivatingPlayer();
|
||||
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
String sVar = source.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")){
|
||||
// This decision should be locked in the AF and be calculable at this state
|
||||
//c = chooseXValue(life);
|
||||
// Figure out what to do here
|
||||
}
|
||||
else{
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
if (!activator.canPayLife(c)){
|
||||
return false;
|
||||
}
|
||||
|
||||
setLastPaidAmount(c);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
80
src/main/java/forge/card/cost/CostPutCounter.java
Normal file
80
src/main/java/forge/card/cost/CostPutCounter.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Counters;
|
||||
import forge.Player;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostPutCounter extends CostPart {
|
||||
// Put Counter doesn't really have a "Valid" portion of the cost
|
||||
private Counters counter;
|
||||
private int lastPaidAmount = 0;
|
||||
|
||||
public Counters getCounter() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
public void setLastPaidAmount(int paidAmount){
|
||||
lastPaidAmount = paidAmount;
|
||||
}
|
||||
|
||||
public CostPutCounter(String amount, Counters counter){
|
||||
this.type = "CARDNAME";
|
||||
isReusable = true;
|
||||
this.amount = amount;
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (counter.getName().equals("Loyalty"))
|
||||
sb.append("+").append(amount);
|
||||
else {
|
||||
sb.append("Put ");
|
||||
Integer i = convertAmount();
|
||||
sb.append(Cost.convertAmountTypeToWords(i, amount, counter.getName()));
|
||||
|
||||
sb.append(" on ").append(type);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
source.subtractCounter(counter, lastPaidAmount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
// PutCounter can always be paid as a Cost
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
source.addCounterFromNonEffect(getCounter(), c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
|
||||
source.addCounterFromNonEffect(getCounter(), c);
|
||||
payment.setPaidManaPart(this, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
126
src/main/java/forge/card/cost/CostRemoveCounter.java
Normal file
126
src/main/java/forge/card/cost/CostRemoveCounter.java
Normal file
@@ -0,0 +1,126 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Counters;
|
||||
import forge.Player;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostRemoveCounter extends CostPart {
|
||||
// SubCounter<Num/Counter/{Type/TypeDescription}>
|
||||
|
||||
private Counters counter;
|
||||
private int lastPaidAmount = 0;
|
||||
|
||||
|
||||
public Counters getCounter() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
public void setLastPaidAmount(int paidAmount){
|
||||
lastPaidAmount = paidAmount;
|
||||
}
|
||||
|
||||
public CostRemoveCounter(String amount, Counters counter, String type, String description){
|
||||
isReusable = true;
|
||||
this.amount = amount;
|
||||
this.counter = counter;
|
||||
|
||||
if (type != null)
|
||||
this.type = type;
|
||||
else
|
||||
this.type = "CARDNAME";
|
||||
|
||||
this.typeDescription = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (counter.getName().equals("Loyalty"))
|
||||
sb.append("-").append(amount);
|
||||
else {
|
||||
sb.append("Remove ");
|
||||
Integer i = convertAmount();
|
||||
sb.append(Cost.convertAmountTypeToWords(i, amount, counter.getName()));
|
||||
|
||||
sb.append(" from ").append(typeDescription == null ? type : typeDescription);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
source.addCounterFromNonEffect(counter, lastPaidAmount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
Counters c = getCounter();
|
||||
|
||||
Integer amount = convertAmount();
|
||||
if (amount != null && source.getCounters(c) - amount < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
source.subtractCounter(getCounter(), c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
String amount = getAmount();
|
||||
Counters type = getCounter();
|
||||
Integer c = convertAmount();
|
||||
int maxCounters = source.getCounters(type);
|
||||
|
||||
if (amount.equals("All")){
|
||||
c = maxCounters;
|
||||
}
|
||||
else{
|
||||
if (c == null){
|
||||
String sVar = source.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")){
|
||||
c = CostUtil.chooseXValue(source, maxCounters);
|
||||
}
|
||||
else{
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maxCounters >= c) {
|
||||
source.setSVar("CostCountersRemoved", "Number$"+Integer.toString(c));
|
||||
source.subtractCounter(type, c);
|
||||
setLastPaidAmount(c);
|
||||
payment.setPaidManaPart(this, true);
|
||||
} else {
|
||||
payment.setCancel(true);
|
||||
payment.getRequirements().finishPaying();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
if (c > source.getCounters(getCounter())) {
|
||||
System.out.println("Not enough " + getCounter() + " on " + source.getName());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
113
src/main/java/forge/card/cost/CostReturn.java
Normal file
113
src/main/java/forge/card/cost/CostReturn.java
Normal file
@@ -0,0 +1,113 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.AllZone;
|
||||
import forge.AllZoneUtil;
|
||||
import forge.Card;
|
||||
import forge.CardList;
|
||||
import forge.ComputerUtil;
|
||||
import forge.Player;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostReturn extends CostPartWithList {
|
||||
// Return<Num/Type{/TypeDescription}>
|
||||
|
||||
public CostReturn(String amount, String type, String description){
|
||||
this.amount = amount;
|
||||
this.type = type;
|
||||
this.typeDescription = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Return ");
|
||||
|
||||
Integer i = convertAmount();
|
||||
String pronoun = "its";
|
||||
|
||||
if (getThis())
|
||||
sb.append(type);
|
||||
else {
|
||||
String desc = typeDescription == null ? type : typeDescription;
|
||||
if (i != null){
|
||||
sb.append(Cost.convertIntAndTypeToWords(i, desc));
|
||||
if (i > 1)
|
||||
pronoun = "their";
|
||||
}
|
||||
else
|
||||
sb.append(Cost.convertAmountTypeToWords(amount, desc));
|
||||
|
||||
sb.append(" you control");
|
||||
}
|
||||
sb.append(" to ").append(pronoun).append(" owner's hand");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
if (!getThis()) {
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(activator);
|
||||
typeList = typeList.getValidCards(getType().split(";"), activator, source);
|
||||
|
||||
Integer amount = convertAmount();
|
||||
if (amount != null && typeList.size() < amount)
|
||||
return false;
|
||||
} else if (!AllZoneUtil.isCardInPlay(source))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
for (Card c : list)
|
||||
AllZone.getGameAction().moveToHand(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
String amount = getAmount();
|
||||
Integer c = convertAmount();
|
||||
Player activator = ability.getActivatingPlayer();
|
||||
CardList list = AllZoneUtil.getPlayerCardsInPlay(activator);
|
||||
if (c == null) {
|
||||
String sVar = source.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")) {
|
||||
c = CostUtil.chooseXValue(source, list.size());
|
||||
} else {
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
if (getThis())
|
||||
CostUtil.setInput(Cost_Input.returnThis(ability, payment, this));
|
||||
else
|
||||
CostUtil.setInput(Cost_Input.returnType(ability, getType(), payment, this, c));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
resetList();
|
||||
if (getThis())
|
||||
list.add(source);
|
||||
else{
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
|
||||
list = ComputerUtil.chooseReturnType(getType(), source, ability.getTargetCard(), c);
|
||||
if (list == null)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
132
src/main/java/forge/card/cost/CostSacrifice.java
Normal file
132
src/main/java/forge/card/cost/CostSacrifice.java
Normal file
@@ -0,0 +1,132 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.AllZone;
|
||||
import forge.AllZoneUtil;
|
||||
import forge.Card;
|
||||
import forge.CardList;
|
||||
import forge.ComputerUtil;
|
||||
import forge.Player;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostSacrifice extends CostPartWithList {
|
||||
|
||||
public CostSacrifice(String amount, String type, String description){
|
||||
this.amount = amount;
|
||||
this.type = type;
|
||||
this.typeDescription = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Sacrifice ");
|
||||
|
||||
Integer i = convertAmount();
|
||||
|
||||
if (getThis())
|
||||
sb.append(type);
|
||||
else{
|
||||
String desc = typeDescription == null ? type : typeDescription;
|
||||
if (i != null)
|
||||
sb.append(Cost.convertIntAndTypeToWords(i, desc));
|
||||
else
|
||||
sb.append(Cost.convertAmountTypeToWords(amount, desc));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
// You can always sac all
|
||||
if (!getThis()) {
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(activator);
|
||||
typeList = typeList.getValidCards(getType().split(";"), activator, source);
|
||||
|
||||
Integer amount = convertAmount();
|
||||
|
||||
if (amount != null && typeList.size() < amount)
|
||||
return false;
|
||||
|
||||
// If amount is null, it's either "ALL" or "X"
|
||||
// if X is defined, it needs to be calculated and checked, if X is choice, it can be Paid even if it's 0
|
||||
} else if (!AllZoneUtil.isCardInPlay(source))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
for (Card c : list)
|
||||
AllZone.getGameAction().sacrifice(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
String amount = getAmount();
|
||||
String type = getType();
|
||||
Player activator = ability.getActivatingPlayer();
|
||||
CardList list = AllZoneUtil.getPlayerCardsInPlay(activator);
|
||||
list = list.getValidCards(type.split(";"), activator, source);
|
||||
|
||||
if (getThis()){
|
||||
CostUtil.setInput(Cost_Input.sacrificeThis(ability, payment, this));
|
||||
}
|
||||
else if (amount.equals("All")){
|
||||
Cost_Input.sacrificeAll(ability, payment, this, list);
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
String sVar = source.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")){
|
||||
c = CostUtil.chooseXValue(source, list.size());
|
||||
}
|
||||
else{
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
|
||||
CostUtil.setInput(Cost_Input.sacrificeFromList(ability, payment, this, list, c));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
resetList();
|
||||
Player activator = ability.getActivatingPlayer();
|
||||
if (getThis()){
|
||||
list.add(source);
|
||||
}
|
||||
else if (amount.equals("All")) {
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(activator);
|
||||
typeList = typeList.getValidCards(type.split(","), activator, source);
|
||||
// Does the AI want to use Sacrifice All?
|
||||
return false;
|
||||
} else{
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
if (source.getSVar(amount).equals("XChoice")){
|
||||
return false;
|
||||
}
|
||||
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
list = ComputerUtil.chooseSacrificeType(type, source, ability.getTargetCard(), c);
|
||||
if (list == null)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
47
src/main/java/forge/card/cost/CostTap.java
Normal file
47
src/main/java/forge/card/cost/CostTap.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Player;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostTap extends CostPart {
|
||||
public CostTap(){
|
||||
isReusable = true;
|
||||
isUndoable = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tap";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
source.untap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
return !(source.isTapped() || source.isSick());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
source.tap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
//if (!canPay(ability, source, ability.getActivatingPlayer(), payment.getCost()))
|
||||
// return false;
|
||||
|
||||
source.tap();
|
||||
payment.setPaidManaPart(this, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
113
src/main/java/forge/card/cost/CostTapType.java
Normal file
113
src/main/java/forge/card/cost/CostTapType.java
Normal file
@@ -0,0 +1,113 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.AllZoneUtil;
|
||||
import forge.Card;
|
||||
import forge.CardList;
|
||||
import forge.ComputerUtil;
|
||||
import forge.Player;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostTapType extends CostPartWithList {
|
||||
public CostTapType(String amount, String type, String description){
|
||||
list = new CardList();
|
||||
isReusable = true;
|
||||
this.amount = amount;
|
||||
this.type = type;
|
||||
this.typeDescription = description;
|
||||
}
|
||||
|
||||
public String getDescription(){
|
||||
return typeDescription == null ? type : typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Tap ");
|
||||
|
||||
Integer i = convertAmount();
|
||||
String desc = getDescription();
|
||||
|
||||
sb.append(Cost.convertAmountTypeToWords(i, amount, "untapped " + desc));
|
||||
|
||||
sb.append(" you control");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void addToTappedList(Card c) {
|
||||
list.add(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
for (Card c : list){
|
||||
c.untap();
|
||||
}
|
||||
|
||||
list.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(activator);
|
||||
|
||||
typeList = typeList.getValidCards(getType().split(";"), activator, source);
|
||||
|
||||
if (cost.getTap())
|
||||
typeList.remove(source);
|
||||
typeList = typeList.filter(AllZoneUtil.untapped);
|
||||
|
||||
Integer amount = convertAmount();
|
||||
if (typeList.size() == 0 || (amount != null && typeList.size() < amount))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
for (Card c : list)
|
||||
c.tap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(source.getController());
|
||||
typeList = typeList.getValidCards(getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard());
|
||||
String amount = getAmount();
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
String sVar = source.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")){
|
||||
c = CostUtil.chooseXValue(source, typeList.size());
|
||||
}
|
||||
else{
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
|
||||
CostUtil.setInput(Cost_Input.input_tapXCost(this, typeList, ability, payment, c));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
boolean tap = payment.getCost().getTap();
|
||||
Integer c = convertAmount();
|
||||
if (c == null){
|
||||
// Determine Amount
|
||||
}
|
||||
|
||||
list = ComputerUtil.chooseTapType(getType(), source, tap, c);
|
||||
|
||||
if (list == null) {
|
||||
System.out.println("Couldn't find a valid card to tap for: " + source.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
47
src/main/java/forge/card/cost/CostUntap.java
Normal file
47
src/main/java/forge/card/cost/CostUntap.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Player;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CostUntap extends CostPart {
|
||||
public CostUntap(){
|
||||
isReusable = true;
|
||||
isUndoable = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Untap";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(Card source) {
|
||||
source.tap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) {
|
||||
return !(source.isUntapped() || source.isSick());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payAI(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
source.untap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
//if (!canPay(ability, source, ability.getActivatingPlayer(), payment.getCost()))
|
||||
// return false;
|
||||
|
||||
source.untap();
|
||||
payment.setPaidManaPart(this, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
153
src/main/java/forge/card/cost/CostUtil.java
Normal file
153
src/main/java/forge/card/cost/CostUtil.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import forge.AllZone;
|
||||
import forge.AllZoneUtil;
|
||||
import forge.Card;
|
||||
import forge.CardList;
|
||||
import forge.ComputerUtil;
|
||||
import forge.Counters;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.gui.GuiUtils;
|
||||
import forge.gui.input.Input;
|
||||
|
||||
public class CostUtil {
|
||||
static private Random r = new Random();
|
||||
static private double P1P1Percent = .1;
|
||||
static private double OtherPercent = .25;
|
||||
|
||||
static public boolean checkSacrificeCost(Cost cost, Card source){
|
||||
for(CostPart part : cost.getCostParts()){
|
||||
if (part instanceof CostSacrifice){
|
||||
CostSacrifice sac = (CostSacrifice)part;
|
||||
|
||||
String type = sac.getType();
|
||||
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
|
||||
typeList = typeList.getValidCards(type.split(","), source.getController(), source);
|
||||
if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static public boolean checkCreatureSacrificeCost(Cost cost, Card source){
|
||||
for(CostPart part : cost.getCostParts()){
|
||||
if (part instanceof CostSacrifice){
|
||||
CostSacrifice sac = (CostSacrifice)part;
|
||||
if (sac.getThis() && source.isCreature())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static public boolean checkLifeCost(Cost cost, Card source, int remainingLife){
|
||||
for(CostPart part : cost.getCostParts()){
|
||||
if (part instanceof CostPayLife){
|
||||
CostPayLife payLife = (CostPayLife)part;
|
||||
if (AllZone.getComputerPlayer().getLife() - payLife.convertAmount() < remainingLife)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static public boolean checkDiscardCost(Cost cost, Card source){
|
||||
for(CostPart part : cost.getCostParts()){
|
||||
if (part instanceof CostDiscard)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static public boolean checkRemoveCounterCost(Cost cost, Card source){
|
||||
for(CostPart part : cost.getCostParts()){
|
||||
if (part instanceof CostRemoveCounter){
|
||||
CostRemoveCounter remCounter = (CostRemoveCounter)part;
|
||||
|
||||
// A card has a 25% chance per counter to be able to pass through here
|
||||
// 4+ counters will always pass. 0 counters will never
|
||||
Counters type = remCounter.getCounter();
|
||||
double percent = type.name().equals("P1P1") ? P1P1Percent : OtherPercent;
|
||||
int currentNum = source.getCounters(type);
|
||||
|
||||
double chance = percent * (currentNum / part.convertAmount());
|
||||
if (chance <= r.nextFloat())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static public boolean checkAddM1M1CounterCost(Cost cost, Card source){
|
||||
for(CostPart part : cost.getCostParts()){
|
||||
if (part instanceof CostPutCounter){
|
||||
CostPutCounter addCounter = (CostPutCounter)part;
|
||||
Counters type = addCounter.getCounter();
|
||||
|
||||
if (type.equals(Counters.M1M1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static public boolean hasDiscardHandCost(Cost cost){
|
||||
for(CostPart part : cost.getCostParts()){
|
||||
if (part instanceof CostDiscard){
|
||||
CostDiscard disc = (CostDiscard)part;
|
||||
if (disc.getType().equals("Hand"))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static public Integer determineAmount(CostPart part, Card source, SpellAbility ability, int maxChoice){
|
||||
String amount = part.getAmount();
|
||||
Integer c = part.convertAmount();
|
||||
if (c == null){
|
||||
String sVar = source.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")){
|
||||
c = CostUtil.chooseXValue(source, maxChoice);
|
||||
}
|
||||
else{
|
||||
c = AbilityFactory.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static public int chooseXValue(Card card, int maxValue){
|
||||
String chosen = card.getSVar("ChosenX");
|
||||
if (chosen.length() > 0){
|
||||
return AbilityFactory.calculateAmount(card, "ChosenX", null);
|
||||
}
|
||||
|
||||
Integer[] choiceArray = new Integer[maxValue+1];
|
||||
for(int i = 0; i < choiceArray.length; i++){
|
||||
choiceArray[i] = i;
|
||||
}
|
||||
Object o = GuiUtils.getChoice(card.toString() + " - Choose a Value for X", choiceArray);
|
||||
int chosenX = (Integer)o;
|
||||
card.setSVar("ChosenX", "Number$"+Integer.toString(chosenX));
|
||||
|
||||
return chosenX;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>setInput.</p>
|
||||
*
|
||||
* @param in a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
static public void setInput(Input in) {
|
||||
// Just a shortcut..
|
||||
AllZone.getInputControl().setInput(in, true);
|
||||
}
|
||||
}
|
||||
678
src/main/java/forge/card/cost/Cost_Input.java
Normal file
678
src/main/java/forge/card/cost/Cost_Input.java
Normal file
@@ -0,0 +1,678 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import forge.AllZone;
|
||||
import forge.AllZoneUtil;
|
||||
import forge.ButtonUtil;
|
||||
import forge.Card;
|
||||
import forge.CardList;
|
||||
import forge.Constant;
|
||||
import forge.Phase;
|
||||
import forge.Player;
|
||||
import forge.PlayerZone;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.gui.input.Input;
|
||||
import forge.gui.input.Input_PayManaCostUtil;
|
||||
|
||||
public class Cost_Input {
|
||||
// ******************************************************************************
|
||||
// *********** Inputs used by Cost_Payment below here ***************************
|
||||
// ******************************************************************************
|
||||
|
||||
/**
|
||||
* <p>input_payMana.</p>
|
||||
*
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @param manaToAdd a int.
|
||||
* @return a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
public static Input input_payMana(final SpellAbility sa, final Cost_Payment payment, final CostMana costMana, final int manaToAdd) {
|
||||
final ManaCost manaCost;
|
||||
|
||||
if (Phase.getGameBegins() == 1) {
|
||||
if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) {
|
||||
manaCost = new ManaCost("0");
|
||||
} else {
|
||||
String mana = costMana.getMana();
|
||||
manaCost = new ManaCost(mana);
|
||||
manaCost.increaseColorlessMana(manaToAdd);
|
||||
}
|
||||
} else {
|
||||
System.out.println("Is input_payMana ever called when the Game isn't in progress?");
|
||||
manaCost = new ManaCost(sa.getManaCost());
|
||||
}
|
||||
|
||||
Input payMana = new Input() {
|
||||
private ManaCost mana = manaCost;
|
||||
private static final long serialVersionUID = 3467312982164195091L;
|
||||
|
||||
private final String originalManaCost = costMana.getMana();
|
||||
|
||||
private int phyLifeToLose = 0;
|
||||
|
||||
private void resetManaCost() {
|
||||
mana = new ManaCost(originalManaCost);
|
||||
phyLifeToLose = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(Card card, PlayerZone zone) {
|
||||
// prevent cards from tapping themselves if ability is a tapability, although it should already be tapped
|
||||
if (sa.getSourceCard().equals(card) && sa.isTapAbility()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mana = Input_PayManaCostUtil.activateManaAbility(sa, card, mana);
|
||||
|
||||
if (mana.isPaid())
|
||||
done();
|
||||
else if (AllZone.getInputControl().getInput() == this)
|
||||
showMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectPlayer(Player player) {
|
||||
if (player.isHuman()) {
|
||||
if (manaCost.payPhyrexian()) {
|
||||
phyLifeToLose += 2;
|
||||
}
|
||||
|
||||
showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
private void done() {
|
||||
Card source = sa.getSourceCard();
|
||||
if (phyLifeToLose > 0)
|
||||
AllZone.getHumanPlayer().payLife(phyLifeToLose, source);
|
||||
source.setColorsPaid(mana.getColorsPaid());
|
||||
source.setSunburstValue(mana.getSunburst());
|
||||
resetManaCost();
|
||||
stop();
|
||||
|
||||
if (costMana.hasNoXManaCost() || manaToAdd > 0){
|
||||
payment.paidCost(costMana);
|
||||
}
|
||||
else{
|
||||
source.setXManaCostPaid(0);
|
||||
CostUtil.setInput(input_payXMana(sa, payment, costMana, costMana.getXMana()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
stop();
|
||||
resetManaCost();
|
||||
payment.cancelCost();
|
||||
AllZone.getHumanBattlefield().updateObservers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
String displayMana = mana.toString().replace("X", "").trim();
|
||||
AllZone.getDisplay().showMessage("Pay Mana Cost: " + displayMana);
|
||||
|
||||
StringBuilder msg = new StringBuilder("Pay Mana Cost: " + displayMana);
|
||||
if (phyLifeToLose > 0) {
|
||||
msg.append(" (");
|
||||
msg.append(phyLifeToLose);
|
||||
msg.append(" life paid for phyrexian mana)");
|
||||
}
|
||||
|
||||
if (mana.containsPhyrexianMana()) {
|
||||
msg.append("\n(Click on your life total to pay life for phyrexian mana.)");
|
||||
}
|
||||
|
||||
AllZone.getDisplay().showMessage(msg.toString());
|
||||
if (mana.isPaid())
|
||||
done();
|
||||
}
|
||||
};
|
||||
return payMana;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>input_payXMana.</p>
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @param costMana TODO
|
||||
* @param numX a int.
|
||||
*
|
||||
* @return a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
public static Input input_payXMana(final SpellAbility sa, final Cost_Payment payment, final CostMana costMana, final int numX) {
|
||||
Input payX = new Input() {
|
||||
private static final long serialVersionUID = -6900234444347364050L;
|
||||
int xPaid = 0;
|
||||
ManaCost manaCost = new ManaCost(Integer.toString(numX));
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (manaCost.toString().equals(Integer.toString(numX))) // Can only cancel if partially paid an X value
|
||||
ButtonUtil.enableAll();
|
||||
else
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
|
||||
AllZone.getDisplay().showMessage("Pay X Mana Cost for " + sa.getSourceCard().getName() + "\n" + xPaid + " Paid so far.");
|
||||
}
|
||||
|
||||
// selectCard
|
||||
@Override
|
||||
public void selectCard(Card card, PlayerZone zone) {
|
||||
if (sa.getSourceCard().equals(card) && sa.isTapAbility()) {
|
||||
// this really shouldn't happen but just in case
|
||||
return;
|
||||
}
|
||||
|
||||
manaCost = Input_PayManaCostUtil.activateManaAbility(sa, card, manaCost);
|
||||
if (manaCost.isPaid()) {
|
||||
manaCost = new ManaCost(Integer.toString(numX));
|
||||
xPaid++;
|
||||
}
|
||||
|
||||
if (AllZone.getInputControl().getInput() == this)
|
||||
showMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
stop();
|
||||
payment.cancelCost();
|
||||
AllZone.getHumanBattlefield().updateObservers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonOK() {
|
||||
stop();
|
||||
payment.getCard().setXManaCostPaid(xPaid);
|
||||
payment.paidCost(costMana);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return payX;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>input_discardCost.</p>
|
||||
* @param discType a {@link java.lang.String} object.
|
||||
* @param handList a {@link forge.CardList} object.
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @param part TODO
|
||||
* @param nNeeded a int.
|
||||
*
|
||||
* @return a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
public static Input input_discardCost(final String discType, final CardList handList, SpellAbility sa, final Cost_Payment payment, final CostPart part, final int nNeeded) {
|
||||
final SpellAbility sp = sa;
|
||||
Input target = new Input() {
|
||||
private static final long serialVersionUID = -329993322080934435L;
|
||||
|
||||
int nDiscard = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
boolean any = discType.equals("Any") ? true : false;
|
||||
if (AllZone.getHumanHand().size() == 0) stop();
|
||||
StringBuilder type = new StringBuilder("");
|
||||
if (any || !discType.equals("Card")) {
|
||||
type.append(" ").append(discType);
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Select ");
|
||||
if (any) {
|
||||
sb.append("any ");
|
||||
} else {
|
||||
sb.append("a ").append(type.toString()).append(" ");
|
||||
}
|
||||
sb.append("card to discard.");
|
||||
if (nNeeded > 1) {
|
||||
sb.append(" You have ");
|
||||
sb.append(nNeeded - nDiscard);
|
||||
sb.append(" remaining.");
|
||||
}
|
||||
AllZone.getDisplay().showMessage(sb.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(Card card, PlayerZone zone) {
|
||||
if (zone.is(Constant.Zone.Hand) && handList.contains(card)) {
|
||||
// send in CardList for Typing
|
||||
card.getController().discard(card, sp);
|
||||
handList.remove(card);
|
||||
nDiscard++;
|
||||
|
||||
//in case no more cards in hand
|
||||
if (nDiscard == nNeeded)
|
||||
done();
|
||||
else if (AllZone.getHumanHand().size() == 0) // this really shouldn't happen
|
||||
cancel();
|
||||
else
|
||||
showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
stop();
|
||||
payment.paidCost(part);
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
}//input_discard()
|
||||
|
||||
/**
|
||||
* <p>sacrificeThis.</p>
|
||||
*
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @param part TODO
|
||||
* @return a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
public static Input sacrificeThis(final SpellAbility sa, final Cost_Payment payment, final CostPart part) {
|
||||
Input target = new Input() {
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
Card card = sa.getSourceCard();
|
||||
if (card.getController().isHuman() && AllZoneUtil.isCardInPlay(card)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(card.getName());
|
||||
sb.append(" - Sacrifice?");
|
||||
Object[] possibleValues = {"Yes", "No"};
|
||||
Object choice = JOptionPane.showOptionDialog(null, sb.toString(), card.getName() + " - Cost",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
|
||||
null, possibleValues, possibleValues[0]);
|
||||
if (choice.equals(0)) {
|
||||
payment.getAbility().addCostToHashList(card, "Sacrificed");
|
||||
AllZone.getGameAction().sacrifice(card);
|
||||
stop();
|
||||
payment.paidCost(part);
|
||||
} else {
|
||||
stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
}//input_sacrifice()
|
||||
|
||||
/**
|
||||
* <p>sacrificeType.</p>
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @param part TODO
|
||||
* @param typeList TODO
|
||||
* @param num TODO
|
||||
*
|
||||
* @return a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
public static Input sacrificeFromList(final SpellAbility sa, final Cost_Payment payment, final CostSacrifice part, final CardList typeList, final int nNeeded) {
|
||||
Input target = new Input() {
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
private int nSacrifices = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
StringBuilder msg = new StringBuilder("Sacrifice ");
|
||||
int nLeft = nNeeded - nSacrifices;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(part.getDescriptiveType());
|
||||
if (nLeft > 1) {
|
||||
msg.append("s");
|
||||
}
|
||||
|
||||
AllZone.getDisplay().showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(Card card, PlayerZone zone) {
|
||||
if (typeList.contains(card)) {
|
||||
nSacrifices++;
|
||||
payment.getAbility().addCostToHashList(card, "Sacrificed");
|
||||
AllZone.getGameAction().sacrifice(card);
|
||||
typeList.remove(card);
|
||||
//in case nothing else to sacrifice
|
||||
if (nSacrifices == nNeeded)
|
||||
done();
|
||||
else if (typeList.size() == 0) // this really shouldn't happen
|
||||
cancel();
|
||||
else
|
||||
showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public void done() {
|
||||
stop();
|
||||
payment.paidCost(part);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
}//sacrificeType()
|
||||
|
||||
/**
|
||||
* <p>sacrificeAllType.</p>
|
||||
*
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @param part TODO
|
||||
* @param typeList TODO
|
||||
*/
|
||||
public static void sacrificeAll(final SpellAbility sa, final Cost_Payment payment, CostPart part, CardList typeList) {
|
||||
// TODO Ask First
|
||||
for (Card card : typeList) {
|
||||
payment.getAbility().addCostToHashList(card, "Sacrificed");
|
||||
AllZone.getGameAction().sacrifice(card);
|
||||
}
|
||||
|
||||
payment.setPaidManaPart(part, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>exileThis.</p>
|
||||
*
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @param costExile TODO
|
||||
* @return a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
public static Input exileThis(final SpellAbility sa, final Cost_Payment payment, final CostExile part) {
|
||||
Input target = new Input() {
|
||||
private static final long serialVersionUID = 678668673002725001L;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
Card card = sa.getSourceCard();
|
||||
if (sa.getActivatingPlayer().isHuman() && AllZoneUtil.isCardInZone(AllZone.getZone(part.getFrom(), sa.getActivatingPlayer()), card)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(card.getName());
|
||||
sb.append(" - Exile?");
|
||||
Object[] possibleValues = {"Yes", "No"};
|
||||
Object choice = JOptionPane.showOptionDialog(null, sb.toString(), card.getName() + " - Cost",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
|
||||
null, possibleValues, possibleValues[0]);
|
||||
if (choice.equals(0)) {
|
||||
payment.getAbility().addCostToHashList(card, "Exiled");
|
||||
AllZone.getGameAction().exile(card);
|
||||
stop();
|
||||
payment.paidCost(part);
|
||||
} else {
|
||||
stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
}//input_exile()
|
||||
|
||||
|
||||
/**
|
||||
* <p>exileType.</p>
|
||||
*
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param costExile TODO
|
||||
* @param type a {@link java.lang.String} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @return a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
public static Input exileType(final SpellAbility sa, final CostExile part, final String type, final Cost_Payment payment, final int nNeeded) {
|
||||
Input target = new Input() {
|
||||
private static final long serialVersionUID = 1403915758082824694L;
|
||||
|
||||
private CardList typeList;
|
||||
private int nExiles = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
StringBuilder msg = new StringBuilder("Exile ");
|
||||
int nLeft = nNeeded - nExiles;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(type);
|
||||
if (nLeft > 1) {
|
||||
msg.append("s");
|
||||
}
|
||||
|
||||
typeList = AllZoneUtil.getPlayerCardsInPlay(sa.getSourceCard().getController());
|
||||
typeList = typeList.getValidCards(type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
AllZone.getDisplay().showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(Card card, PlayerZone zone) {
|
||||
if (typeList.contains(card)) {
|
||||
nExiles++;
|
||||
payment.getAbility().addCostToHashList(card, "Exiled");
|
||||
AllZone.getGameAction().exile(card);
|
||||
typeList.remove(card);
|
||||
//in case nothing else to exile
|
||||
if (nExiles == nNeeded)
|
||||
done();
|
||||
else if (typeList.size() == 0) // this really shouldn't happen
|
||||
cancel();
|
||||
else
|
||||
showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public void done() {
|
||||
stop();
|
||||
payment.paidCost(part);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
}//exileType()
|
||||
|
||||
/**
|
||||
* <p>input_tapXCost.</p>
|
||||
*
|
||||
* @param nCards a int.
|
||||
* @param cardType a {@link java.lang.String} object.
|
||||
* @param cardList a {@link forge.CardList} object.
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @return a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
public static Input input_tapXCost(final CostTapType tapType, final CardList cardList, SpellAbility sa, final Cost_Payment payment, final int nCards) {
|
||||
Input target = new Input() {
|
||||
|
||||
private static final long serialVersionUID = 6438988130447851042L;
|
||||
int nTapped = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (cardList.size() == 0) stop();
|
||||
|
||||
int left = nCards - nTapped;
|
||||
AllZone.getDisplay().showMessage("Select a " + tapType.getDescription() + " to tap (" + left + " left)");
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(Card card, PlayerZone zone) {
|
||||
if (zone.is(Constant.Zone.Battlefield) && cardList.contains(card) && card.isUntapped()) {
|
||||
// send in CardList for Typing
|
||||
card.tap();
|
||||
tapType.addToList(card);
|
||||
cardList.remove(card);
|
||||
payment.getAbility().addCostToHashList(card, "Tapped");
|
||||
nTapped++;
|
||||
|
||||
if (nTapped == nCards)
|
||||
done();
|
||||
else if (cardList.size() == 0) // this really shouldn't happen
|
||||
cancel();
|
||||
else
|
||||
showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
stop();
|
||||
payment.paidCost(tapType);
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
}//input_tapXCost()
|
||||
|
||||
/**
|
||||
* <p>returnThis.</p>
|
||||
*
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @param part TODO
|
||||
* @return a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
public static Input returnThis(final SpellAbility sa, final Cost_Payment payment, final CostPart part) {
|
||||
Input target = new Input() {
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
Card card = sa.getSourceCard();
|
||||
if (card.getController().isHuman() && AllZoneUtil.isCardInPlay(card)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(card.getName());
|
||||
sb.append(" - Return to Hand?");
|
||||
Object[] possibleValues = {"Yes", "No"};
|
||||
Object choice = JOptionPane.showOptionDialog(null, sb.toString(), card.getName() + " - Cost",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
|
||||
null, possibleValues, possibleValues[0]);
|
||||
if (choice.equals(0)) {
|
||||
AllZone.getGameAction().moveToHand(card);
|
||||
stop();
|
||||
payment.paidCost(part);
|
||||
} else {
|
||||
stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
}//input_sacrifice()
|
||||
|
||||
|
||||
/**
|
||||
* <p>returnType.</p>
|
||||
*
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param type a {@link java.lang.String} object.
|
||||
* @param payment a {@link forge.card.cost.Cost_Payment} object.
|
||||
* @param part TODO
|
||||
* @return a {@link forge.gui.input.Input} object.
|
||||
*/
|
||||
public static Input returnType(final SpellAbility sa, final String type, final Cost_Payment payment, final CostPart part, final int nNeeded) {
|
||||
Input target = new Input() {
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
private CardList typeList;
|
||||
private int nReturns = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
StringBuilder msg = new StringBuilder("Return ");
|
||||
int nLeft = nNeeded - nReturns;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(type);
|
||||
if (nLeft > 1) {
|
||||
msg.append("s");
|
||||
}
|
||||
|
||||
typeList = AllZoneUtil.getPlayerCardsInPlay(sa.getSourceCard().getController());
|
||||
typeList = typeList.getValidCards(type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
AllZone.getDisplay().showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(Card card, PlayerZone zone) {
|
||||
if (typeList.contains(card)) {
|
||||
nReturns++;
|
||||
AllZone.getGameAction().moveToHand(card);
|
||||
typeList.remove(card);
|
||||
//in case nothing else to return
|
||||
if (nReturns == nNeeded)
|
||||
done();
|
||||
else if (typeList.size() == 0) // this really shouldn't happen
|
||||
cancel();
|
||||
else
|
||||
showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public void done() {
|
||||
stop();
|
||||
payment.paidCost(part);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
}//returnType()
|
||||
}
|
||||
235
src/main/java/forge/card/cost/Cost_Payment.java
Normal file
235
src/main/java/forge/card/cost/Cost_Payment.java
Normal file
@@ -0,0 +1,235 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.AllZone;
|
||||
import forge.Card;
|
||||
import forge.Player;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellAbility_Requirements;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Cost_Payment class.</p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Cost_Payment {
|
||||
private Cost cost = null;
|
||||
private SpellAbility ability = null;
|
||||
private Card card = null;
|
||||
private SpellAbility_Requirements req = null;
|
||||
private boolean bCancel = false;
|
||||
private Map<CostPart, Boolean> paidCostParts = new HashMap<CostPart, Boolean>();
|
||||
|
||||
/**
|
||||
* <p>Getter for the field <code>cost</code>.</p>
|
||||
*
|
||||
* @return a {@link forge.card.cost.Cost} object.
|
||||
*/
|
||||
public Cost getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Getter for the field <code>ability</code>.</p>
|
||||
*
|
||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public SpellAbility getAbility() {
|
||||
return ability;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Getter for the field <code>card</code>.</p>
|
||||
*
|
||||
* @return a {@link forge.Card} object.
|
||||
*/
|
||||
public Card getCard() {
|
||||
return card;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>setRequirements.</p>
|
||||
*
|
||||
* @param reqs a {@link forge.card.spellability.SpellAbility_Requirements} object.
|
||||
*/
|
||||
public void setRequirements(SpellAbility_Requirements reqs) {
|
||||
req = reqs;
|
||||
}
|
||||
|
||||
public SpellAbility_Requirements getRequirements(){
|
||||
return req;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>setCancel.</p>
|
||||
*
|
||||
* @param cancel a boolean.
|
||||
*/
|
||||
public void setCancel(boolean cancel) {
|
||||
bCancel = cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isCanceled.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isCanceled() {
|
||||
return bCancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Constructor for Cost_Payment.</p>
|
||||
*
|
||||
* @param cost a {@link forge.card.cost.Cost} object.
|
||||
* @param abil a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public Cost_Payment(Cost cost, SpellAbility abil) {
|
||||
this.cost = cost;
|
||||
this.ability = abil;
|
||||
card = abil.getSourceCard();
|
||||
|
||||
for(CostPart part : cost.getCostParts()){
|
||||
paidCostParts.put(part, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>canPayAdditionalCosts.</p>
|
||||
*
|
||||
* @param cost a {@link forge.card.cost.Cost} object.
|
||||
* @param ability a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean canPayAdditionalCosts(Cost cost, SpellAbility ability) {
|
||||
if (cost == null)
|
||||
return true;
|
||||
|
||||
Player activator = ability.getActivatingPlayer();
|
||||
final Card card = ability.getSourceCard();
|
||||
|
||||
for(CostPart part : cost.getCostParts()){
|
||||
if (!part.canPay(ability, card, activator, cost))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setPaidManaPart(CostPart part, boolean bPaid){
|
||||
paidCostParts.put(part, bPaid);
|
||||
}
|
||||
|
||||
public void paidCost(CostPart part){
|
||||
setPaidManaPart(part, true);
|
||||
payCost();
|
||||
}
|
||||
|
||||
public void cancelCost(){
|
||||
setCancel(true);
|
||||
req.finishPaying();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>payCost.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean payCost() {
|
||||
// Nothing actually ever checks this return value, is it needed?
|
||||
if (bCancel) {
|
||||
req.finishPaying();
|
||||
return false;
|
||||
}
|
||||
|
||||
for(CostPart part : cost.getCostParts()){
|
||||
// This portion of the cost is already paid for, keep moving
|
||||
if (paidCostParts.get(part))
|
||||
continue;
|
||||
|
||||
if (!part.payHuman(ability, card, this))
|
||||
return false;
|
||||
}
|
||||
|
||||
resetUndoList();
|
||||
req.finishPaying();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isAllPaid.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isAllPaid() {
|
||||
for(CostPart part : paidCostParts.keySet()){
|
||||
if (!paidCostParts.get(part))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>resetUndoList.</p>
|
||||
*/
|
||||
public void resetUndoList() {
|
||||
for(CostPart part : paidCostParts.keySet()){
|
||||
if (part instanceof CostPartWithList){
|
||||
((CostPartWithList)part).resetList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>cancelPayment.</p>
|
||||
*/
|
||||
public void cancelPayment() {
|
||||
for(CostPart part : paidCostParts.keySet()){
|
||||
if (paidCostParts.get(part) && part.isUndoable())
|
||||
part.refund(card);
|
||||
}
|
||||
|
||||
// Move this to CostMana
|
||||
AllZone.getManaPool().unpaid(ability, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>payComputerCosts.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean payComputerCosts() {
|
||||
// canPayAdditionalCosts now Player Agnostic
|
||||
|
||||
// Just in case it wasn't set, but honestly it shouldn't have gotten here without being set
|
||||
Player activator = AllZone.getComputerPlayer();
|
||||
ability.setActivatingPlayer(activator);
|
||||
|
||||
Card source = ability.getSourceCard();
|
||||
ArrayList<CostPart> parts = cost.getCostParts();
|
||||
|
||||
// Set all of the decisions before attempting to pay anything
|
||||
for(CostPart part : parts){
|
||||
if (!part.decideAIPayment(ability, source, this))
|
||||
return false;
|
||||
}
|
||||
|
||||
for(CostPart part : parts){
|
||||
part.payAI(ability, ability.getSourceCard(), this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>changeCost.</p>
|
||||
*/
|
||||
public void changeCost() {
|
||||
cost.changeCost(ability);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package forge.card.spellability;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.Cost_Payment;
|
||||
|
||||
|
||||
/**
|
||||
@@ -27,7 +29,7 @@ abstract public class Ability_Activated extends SpellAbility implements java.io.
|
||||
* <p>Constructor for Ability_Activated.</p>
|
||||
*
|
||||
* @param sourceCard a {@link forge.Card} object.
|
||||
* @param abCost a {@link forge.card.spellability.Cost} object.
|
||||
* @param abCost a {@link forge.card.cost.Cost} object.
|
||||
* @param tgt a {@link forge.card.spellability.Target} object.
|
||||
*/
|
||||
public Ability_Activated(Card sourceCard, Cost abCost, Target tgt) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import forge.AllZone;
|
||||
import forge.AllZoneUtil;
|
||||
import forge.Card;
|
||||
import forge.Player;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.mana.ManaPool;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -51,7 +52,7 @@ abstract public class Ability_Mana extends Ability_Activated implements java.io.
|
||||
* <p>Constructor for Ability_Mana.</p>
|
||||
*
|
||||
* @param sourceCard a {@link forge.Card} object.
|
||||
* @param cost a {@link forge.card.spellability.Cost} object.
|
||||
* @param cost a {@link forge.card.cost.Cost} object.
|
||||
* @param produced a {@link java.lang.String} object.
|
||||
*/
|
||||
public Ability_Mana(Card sourceCard, Cost cost, String produced) {
|
||||
@@ -62,7 +63,7 @@ abstract public class Ability_Mana extends Ability_Activated implements java.io.
|
||||
* <p>Constructor for Ability_Mana.</p>
|
||||
*
|
||||
* @param sourceCard a {@link forge.Card} object.
|
||||
* @param cost a {@link forge.card.spellability.Cost} object.
|
||||
* @param cost a {@link forge.card.cost.Cost} object.
|
||||
* @param produced a {@link java.lang.String} object.
|
||||
* @param num a int.
|
||||
*/
|
||||
@@ -189,7 +190,7 @@ abstract public class Ability_Mana extends Ability_Activated implements java.io.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isSacrifice() {
|
||||
return this.getPayCosts().getSacCost();
|
||||
return payCosts.getSacCost();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,8 @@
|
||||
package forge.card.spellability;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.Cost_Payment;
|
||||
import forge.error.ErrorViewer;
|
||||
|
||||
|
||||
@@ -32,7 +34,7 @@ abstract public class Spell extends SpellAbility implements java.io.Serializable
|
||||
* <p>Constructor for Spell.</p>
|
||||
*
|
||||
* @param sourceCard a {@link forge.Card} object.
|
||||
* @param abCost a {@link forge.card.spellability.Cost} object.
|
||||
* @param abCost a {@link forge.card.cost.Cost} object.
|
||||
* @param abTgt a {@link forge.card.spellability.Target} object.
|
||||
*/
|
||||
public Spell(Card sourceCard, Cost abCost, Target abTgt) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package forge.card.spellability;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.mana.Mana;
|
||||
import forge.gui.input.Input;
|
||||
|
||||
@@ -505,7 +506,7 @@ public abstract class SpellAbility {
|
||||
/**
|
||||
* <p>Getter for the field <code>payCosts</code>.</p>
|
||||
*
|
||||
* @return a {@link forge.card.spellability.Cost} object.
|
||||
* @return a {@link forge.card.cost.Cost} object.
|
||||
*/
|
||||
public Cost getPayCosts() {
|
||||
return payCosts;
|
||||
@@ -514,7 +515,7 @@ public abstract class SpellAbility {
|
||||
/**
|
||||
* <p>Setter for the field <code>payCosts</code>.</p>
|
||||
*
|
||||
* @param abCost a {@link forge.card.spellability.Cost} object.
|
||||
* @param abCost a {@link forge.card.cost.Cost} object.
|
||||
*/
|
||||
public void setPayCosts(Cost abCost) {
|
||||
payCosts = abCost;
|
||||
@@ -752,6 +753,14 @@ public abstract class SpellAbility {
|
||||
chosenTarget.resetTargets();
|
||||
|
||||
resetTriggeringObjects();
|
||||
|
||||
//Clear SVars
|
||||
for(String store : Card.getStorableSVars()){
|
||||
String value = sourceCard.getSVar(store);
|
||||
if (value.length() > 0){
|
||||
sourceCard.setSVar(store, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@ import forge.AllZone;
|
||||
import forge.Card;
|
||||
import forge.PlayerZone;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.cost.Cost_Payment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -46,7 +47,7 @@ public class SpellAbility_Requirements {
|
||||
*
|
||||
* @param sa a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param ts a {@link forge.card.spellability.Target_Selection} object.
|
||||
* @param cp a {@link forge.card.spellability.Cost_Payment} object.
|
||||
* @param cp a {@link forge.card.cost.Cost_Payment} object.
|
||||
*/
|
||||
public SpellAbility_Requirements(SpellAbility sa, Target_Selection ts, Cost_Payment cp) {
|
||||
ability = sa;
|
||||
|
||||
@@ -44,7 +44,9 @@ public class SpellAbility_StackInstance {
|
||||
|
||||
// Triggers
|
||||
private HashMap<String, Object> triggeringObjects = new HashMap<String, Object>();
|
||||
|
||||
|
||||
private HashMap<String, String> storedSVars = new HashMap<String, String>();
|
||||
|
||||
/**
|
||||
* <p>Constructor for SpellAbility_StackInstance.</p>
|
||||
*
|
||||
@@ -76,6 +78,17 @@ public class SpellAbility_StackInstance {
|
||||
tc = target.getTargetChoices();
|
||||
ability.getTarget().resetTargets();
|
||||
}
|
||||
|
||||
Card source = ability.getSourceCard();
|
||||
|
||||
//Store SVars and Clear
|
||||
for(String store : Card.getStorableSVars()){
|
||||
String value = source.getSVar(store);
|
||||
if (value.length() > 0){
|
||||
storedSVars.put(store, value);
|
||||
source.setSVar(store, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,6 +114,15 @@ public class SpellAbility_StackInstance {
|
||||
// Triggered
|
||||
ability.setAllTriggeringObjects(triggeringObjects);
|
||||
|
||||
// Add SVars back in
|
||||
Card source = ability.getSourceCard();
|
||||
for(String store : storedSVars.keySet()){
|
||||
String value = storedSVars.get(store);
|
||||
if (value.length() > 0){
|
||||
source.setSVar(store, value);
|
||||
}
|
||||
}
|
||||
|
||||
return ability;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.card.spellability;
|
||||
import forge.*;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.cardFactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.trigger.Trigger;
|
||||
import forge.gui.input.Input;
|
||||
|
||||
@@ -135,7 +136,7 @@ public class Spell_Permanent extends Spell {
|
||||
* <p>Constructor for Spell_Permanent.</p>
|
||||
*
|
||||
* @param sourceCard a {@link forge.Card} object.
|
||||
* @param cost a {@link forge.card.spellability.Cost} object.
|
||||
* @param cost a {@link forge.card.cost.Cost} object.
|
||||
* @param tgt a {@link forge.card.spellability.Target} object.
|
||||
*/
|
||||
public Spell_Permanent(Card sourceCard, Cost cost, Target tgt) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package forge.card.trigger;
|
||||
|
||||
import forge.*;
|
||||
import forge.card.abilityFactory.AbilityFactory;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.*;
|
||||
import forge.gui.input.Input;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package forge.card.trigger;
|
||||
import forge.AllZone;
|
||||
import forge.Card;
|
||||
import forge.Player;
|
||||
import forge.card.spellability.Cost;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellAbility_StackInstance;
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ package forge.quest.data.pet;
|
||||
import forge.AllZone;
|
||||
import forge.Card;
|
||||
import forge.Constant;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.Ability_Activated;
|
||||
import forge.card.spellability.Cost;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.quest.data.bazaar.QuestStallManager;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user