mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
Costs no longer keep AI's choice in the CostPart class,
CardList has filter method to apply 2 filters sequentially Untap: old inputs replaced with synchronized ones. InputProxy - using an AtomicReference to hold current input, just in case.
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -13713,6 +13713,7 @@ src/main/java/forge/card/cost/CostUntap.java -text
|
||||
src/main/java/forge/card/cost/CostUntapType.java -text
|
||||
src/main/java/forge/card/cost/CostUtil.java -text
|
||||
src/main/java/forge/card/cost/InputPayCostBase.java -text
|
||||
src/main/java/forge/card/cost/PaymentDecision.java -text
|
||||
src/main/java/forge/card/cost/package-info.java svneol=native#text/plain
|
||||
src/main/java/forge/card/mana/IParserManaCost.java -text
|
||||
src/main/java/forge/card/mana/Mana.java svneol=native#text/plain
|
||||
|
||||
@@ -8993,7 +8993,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
if (getController() == null) {
|
||||
return false;
|
||||
}
|
||||
return getController().getCardsIn(ZoneType.Battlefield).contains(this);
|
||||
return getController().getZone(ZoneType.Battlefield).contains(this);
|
||||
}
|
||||
|
||||
public void onCleanupPhase(final Player turn) {
|
||||
|
||||
@@ -254,6 +254,10 @@ public class CardLists {
|
||||
return Lists.newArrayList(Iterables.filter(cardList, filt));
|
||||
}
|
||||
|
||||
public static List<Card> filter(Iterable<Card> cardList, Predicate<Card> f1, Predicate<Card> f2) {
|
||||
return Lists.newArrayList(Iterables.filter(Iterables.filter(cardList, f1), f2));
|
||||
}
|
||||
|
||||
public static List<Card> createCardList(Card c) {
|
||||
List<Card> res = new ArrayList<Card>();
|
||||
res.add(c);
|
||||
|
||||
@@ -21,9 +21,9 @@ public class FThreads {
|
||||
|
||||
private FThreads() { } // no instances supposed
|
||||
|
||||
private final static ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||
private static ExecutorService getCachedPool() { return threadPool; }
|
||||
private final static ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(1);
|
||||
private final static ExecutorService cachedPool = Executors.newCachedThreadPool();
|
||||
private static ExecutorService getCachedPool() { return cachedPool; }
|
||||
private final static ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2);
|
||||
private static ScheduledExecutorService getScheduledPool() { return scheduledPool; }
|
||||
|
||||
// This pool is designed to parallel CPU or IO intensive tasks like parse cards or download images, assuming a load factor of 0.5
|
||||
|
||||
@@ -28,6 +28,7 @@ import forge.card.ability.SpellAbilityAi;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostDiscard;
|
||||
import forge.card.cost.CostPart;
|
||||
import forge.card.cost.PaymentDecision;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
@@ -70,8 +71,10 @@ public class DrawAi extends SpellAbilityAi {
|
||||
for (final CostPart part : abCost.getCostParts()) {
|
||||
if (part instanceof CostDiscard) {
|
||||
CostDiscard cd = (CostDiscard) part;
|
||||
cd.decideAIPayment((AIPlayer) ai, sa, sa.getSourceCard(), null);
|
||||
for (Card discard : cd.getList()) {
|
||||
PaymentDecision decision = cd.decideAIPayment((AIPlayer) ai, sa, sa.getSourceCard());
|
||||
if ( null == decision )
|
||||
return false;
|
||||
for (Card discard : decision.cards) {
|
||||
if (!ComputerUtil.isWorseThanDraw(ai, discard)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,13 +145,22 @@ public class Cost {
|
||||
|
||||
StringBuilder manaParts = new StringBuilder();
|
||||
String[] parts = TextUtil.splitWithParenthesis(parse, ' ', '<', '>');
|
||||
|
||||
// make this before parse so that classes that need it get data in their constructor
|
||||
for(String part : parts) {
|
||||
if ( part.equals("T") || part.equals("Tap") )
|
||||
this.tapCost = true;
|
||||
if ( part.equals("Q") || part.equals("Untap") )
|
||||
this.untapCost = true;
|
||||
}
|
||||
|
||||
for(String part : parts) {
|
||||
if( "XCantBe0".equals(part) )
|
||||
xCantBe0 = true;
|
||||
else if ( "X".equals(part) )
|
||||
amountX++;
|
||||
else {
|
||||
CostPart cp = parseCostPart(part);
|
||||
CostPart cp = parseCostPart(part, tapCost, untapCost);
|
||||
if ( null != cp )
|
||||
this.costParts.add(cp);
|
||||
else
|
||||
@@ -175,22 +184,20 @@ public class Cost {
|
||||
if( cp instanceof CostUntap ) {
|
||||
costParts.remove(iCp);
|
||||
costParts.add(0, cp);
|
||||
untapCost = true;
|
||||
}
|
||||
if( cp instanceof CostTap ) {
|
||||
costParts.remove(iCp);
|
||||
costParts.add(0, cp);
|
||||
tapCost = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static CostPart parseCostPart(String parse) {
|
||||
private static CostPart parseCostPart(String parse, boolean tapCost, boolean untapCost) {
|
||||
|
||||
if(parse.startsWith("tapXType<")) {
|
||||
final String[] splitStr = abCostParse(parse, 3);
|
||||
final String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
return new CostTapType(splitStr[0], splitStr[1], description);
|
||||
return new CostTapType(splitStr[0], splitStr[1], description, tapCost);
|
||||
}
|
||||
|
||||
if(parse.startsWith("untapYType<")) {
|
||||
@@ -337,9 +344,9 @@ public class Cost {
|
||||
* @return an array of {@link java.lang.String} objects.
|
||||
*/
|
||||
private static String[] abCostParse(final String parse, final int numParse) {
|
||||
final int startPos = parse.indexOf("<");
|
||||
final int startPos = 1 + parse.indexOf("<");
|
||||
final int endPos = parse.indexOf(">", startPos);
|
||||
String str = parse.substring(startPos + 1, endPos);
|
||||
String str = parse.substring(startPos, endPos);
|
||||
|
||||
final String[] splitStr = str.split("/", numParse);
|
||||
return splitStr;
|
||||
|
||||
@@ -29,33 +29,7 @@ import forge.gui.GuiDialog;
|
||||
* The Class CostPayLife.
|
||||
*/
|
||||
public class CostDamage extends CostPart {
|
||||
private int lastPaidAmount = 0;
|
||||
|
||||
/**
|
||||
* Gets the last paid amount.
|
||||
*
|
||||
* @return the last paid amount
|
||||
*/
|
||||
public final int getLastPaidAmount() {
|
||||
return this.lastPaidAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last paid amount.
|
||||
*
|
||||
* @param paidAmount
|
||||
* the new last paid amount
|
||||
*/
|
||||
public final void setLastPaidAmount(final int paidAmount) {
|
||||
this.lastPaidAmount = paidAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new cost pay life.
|
||||
*
|
||||
* @param amount
|
||||
* the amount
|
||||
*/
|
||||
public CostDamage(final String amount) {
|
||||
this.setAmount(amount);
|
||||
}
|
||||
@@ -91,8 +65,8 @@ public class CostDamage extends CostPart {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
ability.getActivatingPlayer().addDamage(this.getLastPaidAmount(), source);
|
||||
public final void payAI(final PaymentDecision decision, final AIPlayer ai, SpellAbility ability, Card source) {
|
||||
ability.getActivatingPlayer().addDamage(decision.c, source);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -139,21 +113,19 @@ public class CostDamage extends CostPart {
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
public final PaymentDecision decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source) {
|
||||
Integer c = this.convertAmount();
|
||||
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(this.getAmount());
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")) {
|
||||
return false;
|
||||
return null; // cannot pay
|
||||
} else {
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
}
|
||||
|
||||
// activator.payLife(c, null);
|
||||
this.setLastPaidAmount(c);
|
||||
return true;
|
||||
return new PaymentDecision(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import forge.game.GameState;
|
||||
import forge.game.player.AIPlayer;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
/**
|
||||
* The Class CostDiscard.
|
||||
@@ -145,19 +146,6 @@ public class CostDiscard extends CostPartWithList {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
for (final Card c : this.getList()) {
|
||||
executePayment(ability, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -172,27 +160,20 @@ public class CostDiscard extends CostPartWithList {
|
||||
List<Card> handList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Hand));
|
||||
String discardType = this.getType();
|
||||
final String amount = this.getAmount();
|
||||
this.resetList();
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
if (!handList.contains(source)) {
|
||||
return false;
|
||||
return handList.contains(source) && executePayment(ability, source);
|
||||
}
|
||||
executePayment(ability, source);
|
||||
return true;
|
||||
//this.addToList(source);
|
||||
} else if (discardType.equals("Hand")) {
|
||||
this.setList(handList);
|
||||
activator.discardHand(ability);
|
||||
return true;
|
||||
} else if (discardType.equals("LastDrawn")) {
|
||||
|
||||
if (discardType.equals("Hand")) {
|
||||
return executePayment(ability, handList);
|
||||
}
|
||||
|
||||
if (discardType.equals("LastDrawn")) {
|
||||
final Card lastDrawn = activator.getLastDrawnCard();
|
||||
if (!handList.contains(lastDrawn)) {
|
||||
return false;
|
||||
return handList.contains(lastDrawn) && executePayment(ability, lastDrawn);
|
||||
}
|
||||
executePayment(ability, lastDrawn);
|
||||
return true;
|
||||
} else {
|
||||
|
||||
Integer c = this.convertAmount();
|
||||
|
||||
if (discardType.equals("Random")) {
|
||||
@@ -206,8 +187,8 @@ public class CostDiscard extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
|
||||
this.setList(activator.discardRandom(c, ability));
|
||||
return true;
|
||||
return executePayment(ability, Aggregates.random(handList, c));
|
||||
|
||||
} else {
|
||||
String type = new String(discardType);
|
||||
boolean sameName = false;
|
||||
@@ -248,73 +229,62 @@ public class CostDiscard extends CostPartWithList {
|
||||
FThreads.setInputAndWait(inp);
|
||||
if( inp.hasCancelled() || inp.getSelected().size() != c)
|
||||
return false;
|
||||
for(Card crd : inp.getSelected())
|
||||
executePayment(ability, crd);
|
||||
return true;
|
||||
}
|
||||
|
||||
return executePayment(ability, inp.getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
final String type = this.getType();
|
||||
|
||||
final List<Card> hand = ai.getCardsIn(ZoneType.Hand);
|
||||
this.resetList();
|
||||
if (type.equals("LastDrawn")) {
|
||||
if (!hand.contains(ai.getLastDrawnCard())) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
this.addToList(ai.getLastDrawnCard());
|
||||
return new PaymentDecision(ai.getLastDrawnCard());
|
||||
}
|
||||
|
||||
else if (this.payCostFromSource()) {
|
||||
if (!hand.contains(source)) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
this.addToList(source);
|
||||
return new PaymentDecision(source);
|
||||
}
|
||||
|
||||
else if (type.equals("Hand")) {
|
||||
this.getList().addAll(hand);
|
||||
return new PaymentDecision(hand);
|
||||
}
|
||||
|
||||
else {
|
||||
if (type.contains("WithSameName")) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(this.getAmount());
|
||||
if (sVar.equals("XChoice")) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
|
||||
if (type.equals("Random")) {
|
||||
this.setList(CardLists.getRandomSubList(hand, c));
|
||||
return new PaymentDecision(CardLists.getRandomSubList(hand, c));
|
||||
} else {
|
||||
this.setList(ai.getAi().getCardsToDiscard(c, type.split(";"), ability));
|
||||
return new PaymentDecision(ai.getAi().getCardsToDiscard(c, type.split(";"), ability));
|
||||
}
|
||||
}
|
||||
return this.getList() != null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard) {
|
||||
this.addToList(targetCard);
|
||||
protected void doPayment(SpellAbility ability, Card targetCard) {
|
||||
targetCard.getController().discard(targetCard, ability);
|
||||
}
|
||||
|
||||
@@ -326,6 +296,14 @@ public class CostDiscard extends CostPartWithList {
|
||||
return "Discarded";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void payAI(PaymentDecision decision, AIPlayer ai, SpellAbility ability, Card source) {
|
||||
executePayment(ability, decision.cards);
|
||||
}
|
||||
|
||||
// Inputs
|
||||
|
||||
}
|
||||
|
||||
@@ -505,28 +505,6 @@ public class CostExile extends CostPartWithList {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
for (final Card c : this.getList()) {
|
||||
Singletons.getModel().getGame().getAction().exile(c);
|
||||
if (this.from.equals(ZoneType.Stack)) {
|
||||
ArrayList<SpellAbility> spells = c.getSpellAbilities();
|
||||
for (SpellAbility spell : spells) {
|
||||
if (c.isInZone(ZoneType.Exile)) {
|
||||
final SpellAbilityStackInstance si = Singletons.getModel().getGame().getStack().getInstanceFromSpellAbility(spell);
|
||||
Singletons.getModel().getGame().getStack().remove(si);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -597,51 +575,7 @@ public class CostExile extends CostPartWithList {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
this.resetList();
|
||||
if (this.payCostFromSource()) {
|
||||
this.getList().add(source);
|
||||
} else if (this.getType().equals("All")) {
|
||||
this.setList(new ArrayList<Card>(ability.getActivatingPlayer().getCardsIn(this.getFrom())));
|
||||
} else {
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(this.getAmount());
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sVar.equals("YChoice")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
|
||||
if (this.from.equals(ZoneType.Library)) {
|
||||
this.setList(ai.getCardsIn(ZoneType.Library, c));
|
||||
} else if (this.sameZone) {
|
||||
// TODO Determine exile from same zone for AI
|
||||
return false;
|
||||
} else {
|
||||
this.setList(ComputerUtil.chooseExileFrom(ai, this.getFrom(), this.getType(), source,
|
||||
ability.getTargetCard(), c));
|
||||
}
|
||||
if ((this.getList() == null) || (this.getList().size() < c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Inputs
|
||||
|
||||
@@ -683,8 +617,7 @@ public class CostExile extends CostPartWithList {
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard) {
|
||||
addToList(targetCard);
|
||||
protected void doPayment(SpellAbility ability, Card targetCard) {
|
||||
ability.getActivatingPlayer().getGame().getAction().exile(targetCard);
|
||||
}
|
||||
|
||||
@@ -696,4 +629,57 @@ public class CostExile extends CostPartWithList {
|
||||
// TODO Auto-generated method stub
|
||||
return "Exiled";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
if (this.payCostFromSource()) {
|
||||
return new PaymentDecision(source);
|
||||
}
|
||||
|
||||
if (this.getType().equals("All")) {
|
||||
return new PaymentDecision(new ArrayList<Card>(ai.getCardsIn(this.getFrom())));
|
||||
}
|
||||
|
||||
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(this.getAmount());
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice") || sVar.equals("YChoice")) {
|
||||
return null;
|
||||
}
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
|
||||
if (this.from.equals(ZoneType.Library)) {
|
||||
return new PaymentDecision(ai.getCardsIn(ZoneType.Library, c));
|
||||
} else if (this.sameZone) {
|
||||
// TODO Determine exile from same zone for AI
|
||||
return null;
|
||||
} else {
|
||||
return new PaymentDecision(ComputerUtil.chooseExileFrom(ai, this.getFrom(), this.getType(), source, ability.getTargetCard(), c));
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void payAI(PaymentDecision decision, AIPlayer ai, SpellAbility ability, Card source) {
|
||||
for (final Card c : decision.cards) {
|
||||
executePayment(ability, c);
|
||||
if (this.from.equals(ZoneType.Stack)) {
|
||||
ArrayList<SpellAbility> spells = c.getSpellAbilities();
|
||||
for (SpellAbility spell : spells) {
|
||||
if (c.isInZone(ZoneType.Exile)) {
|
||||
final SpellAbilityStackInstance si = ai.getGame().getStack().getInstanceFromSpellAbility(spell);
|
||||
ai.getGame().getStack().remove(si);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,26 +33,6 @@ import forge.gui.GuiChoose;
|
||||
*/
|
||||
public class CostGainLife extends CostPart {
|
||||
private final int cntPlayers; // MAX_VALUE means ALL/EACH PLAYERS
|
||||
private int lastPaidAmount = 0;
|
||||
|
||||
/**
|
||||
* Gets the last paid amount.
|
||||
*
|
||||
* @return the last paid amount
|
||||
*/
|
||||
public final int getLastPaidAmount() {
|
||||
return this.lastPaidAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last paid amount.
|
||||
*
|
||||
* @param paidAmount
|
||||
* the new last paid amount
|
||||
*/
|
||||
public final void setLastPaidAmount(final int paidAmount) {
|
||||
this.lastPaidAmount = paidAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new cost gain life.
|
||||
@@ -109,7 +89,7 @@ public class CostGainLife extends CostPart {
|
||||
}
|
||||
}
|
||||
|
||||
return cntPlayers < Integer.MAX_VALUE ? cntAbleToGainLife >= cntPlayers : cntAbleToGainLife == possibleTargets.size();
|
||||
return cntAbleToGainLife >= cntPlayers || cntPlayers == Integer.MAX_VALUE && cntAbleToGainLife == possibleTargets.size();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -119,12 +99,12 @@ public class CostGainLife extends CostPart {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payAI(final PaymentDecision decision, final AIPlayer ai, SpellAbility ability, Card source) {
|
||||
int playersLeft = cntPlayers;
|
||||
for (final Player opp : getPotentialTargets(game, ai, source)) {
|
||||
for (final Player opp : getPotentialTargets(ai.getGame(), ai, source)) {
|
||||
if (opp.canGainLife() && playersLeft > 0) {
|
||||
playersLeft--;
|
||||
opp.gainLife(this.getLastPaidAmount(), null);
|
||||
opp.gainLife(decision.c, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,15 +170,13 @@ public class CostGainLife extends CostPart {
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
|
||||
|
||||
public final PaymentDecision decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source) {
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(this.getAmount());
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")) {
|
||||
return false;
|
||||
return null;
|
||||
} else {
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
@@ -212,9 +190,9 @@ public class CostGainLife extends CostPart {
|
||||
}
|
||||
|
||||
if (oppsThatCanGainLife.size() == 0) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
this.setLastPaidAmount(c);
|
||||
return true;
|
||||
|
||||
return new PaymentDecision(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,9 @@
|
||||
*/
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.GameState;
|
||||
@@ -49,6 +46,14 @@ public class CostMill extends CostPartWithList {
|
||||
this.setAmount(amount);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#getHashForList()
|
||||
*/
|
||||
@Override
|
||||
public String getHashForList() {
|
||||
return "Milled";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -74,50 +79,6 @@ public class CostMill extends CostPartWithList {
|
||||
return i < zone.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
this.resetList();
|
||||
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(this.getAmount());
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
|
||||
this.setList(new ArrayList<Card>(ai.getCardsIn(ZoneType.Library, c)));
|
||||
|
||||
if ((this.getList() == null) || (this.getList().size() < c)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
for (final Card c : this.getList()) {
|
||||
Singletons.getModel().getGame().getAction().moveToGraveyard(c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -143,21 +104,13 @@ public class CostMill extends CostPartWithList {
|
||||
}
|
||||
final List<Card> list = activator.getCardsIn(ZoneType.Library, c);
|
||||
|
||||
if ((list == null) || (list.size() > c)) {
|
||||
// I don't believe this is possible
|
||||
return false;
|
||||
}
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Mill ").append(c).append(" cards from your library?");
|
||||
|
||||
if ( false == GuiDialog.confirm(source, sb.toString()) )
|
||||
return false;
|
||||
|
||||
this.resetList();
|
||||
final Iterator<Card> itr = list.iterator();
|
||||
while (itr.hasNext()) {
|
||||
final Card card = itr.next();
|
||||
for(final Card card : list) { // this list is a copy, no exception expected
|
||||
executePayment(ability, card);
|
||||
}
|
||||
return true;
|
||||
@@ -193,17 +146,27 @@ public class CostMill extends CostPartWithList {
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard) {
|
||||
this.addToList(targetCard);
|
||||
protected void doPayment(SpellAbility ability, Card targetCard) {
|
||||
ability.getActivatingPlayer().getGame().getAction().moveToGraveyard(targetCard);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#getHashForList()
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public String getHashForList() {
|
||||
return "Milled";
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(this.getAmount());
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
|
||||
List<Card> topLib = ai.getCardsIn(ZoneType.Library, c);
|
||||
return topLib.size() < c ? null : new PaymentDecision(topLib);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,17 +28,8 @@ import forge.game.player.Player;
|
||||
* The Class CostPart.
|
||||
*/
|
||||
public abstract class CostPart {
|
||||
|
||||
/** The optional. */
|
||||
// private boolean optional = false;
|
||||
|
||||
/** The amount. */
|
||||
private String amount = "1";
|
||||
|
||||
/** The type. */
|
||||
private final String type;
|
||||
|
||||
/** The type description. */
|
||||
private final String typeDescription;
|
||||
|
||||
/**
|
||||
@@ -171,7 +162,7 @@ public abstract class CostPart {
|
||||
* {@link forge.card.cost.CostPayment}
|
||||
* @return true, if successful
|
||||
*/
|
||||
public abstract boolean decideAIPayment(final AIPlayer ai, SpellAbility ability, Card source, CostPayment payment);
|
||||
public abstract PaymentDecision decideAIPayment(final AIPlayer ai, SpellAbility ability, Card source);
|
||||
|
||||
/**
|
||||
* Pay ai.
|
||||
@@ -186,7 +177,7 @@ public abstract class CostPart {
|
||||
* {@link forge.card.cost.CostPayment}
|
||||
* @param game
|
||||
*/
|
||||
public abstract void payAI(final AIPlayer ai, SpellAbility ability, Card source, CostPayment payment, GameState game);
|
||||
public abstract void payAI(final PaymentDecision decision, final AIPlayer ai, SpellAbility ability, Card source);
|
||||
|
||||
/**
|
||||
* Pay human.
|
||||
|
||||
@@ -187,14 +187,11 @@ public class CostPartMana extends CostPart {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public void payAI(PaymentDecision decision, AIPlayer ai, SpellAbility ability, Card source) {
|
||||
ComputerUtilMana.payManaCost(ai, ability);
|
||||
}
|
||||
|
||||
@@ -235,16 +232,12 @@ public class CostPartMana extends CostPart {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
return true;
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
return new PaymentDecision(0);
|
||||
}
|
||||
|
||||
// Inputs
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
*/
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardUtil;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.player.AIPlayer;
|
||||
|
||||
/**
|
||||
* The Class CostPartWithList.
|
||||
@@ -31,7 +31,7 @@ import forge.card.spellability.SpellAbility;
|
||||
public abstract class CostPartWithList extends CostPart {
|
||||
|
||||
/** The list. */
|
||||
private Set<Card> list = new HashSet<Card>();
|
||||
private final List<Card> list = new ArrayList<Card>();
|
||||
// set is here because executePayment() adds card to list, while ai's decide payment does the same thing.
|
||||
// set allows to avoid duplication
|
||||
|
||||
@@ -40,21 +40,10 @@ public abstract class CostPartWithList extends CostPart {
|
||||
*
|
||||
* @return the list
|
||||
*/
|
||||
public final Set<Card> getList() {
|
||||
public final List<Card> getList() {
|
||||
return this.list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list.
|
||||
*
|
||||
* @param setList
|
||||
* the new list
|
||||
*/
|
||||
public final void setList(final List<Card> setList) {
|
||||
this.list.clear();
|
||||
list.addAll(setList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset list.
|
||||
*/
|
||||
@@ -62,13 +51,7 @@ public abstract class CostPartWithList extends CostPart {
|
||||
this.list.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the to list.
|
||||
*
|
||||
* @param c
|
||||
* the c
|
||||
*/
|
||||
public final void addToList(final Card c) {
|
||||
protected final void addToList(final Card c) {
|
||||
this.list.add(c);
|
||||
}
|
||||
|
||||
@@ -105,14 +88,33 @@ public abstract class CostPartWithList extends CostPart {
|
||||
*/
|
||||
public CostPartWithList(final String amount, final String type, final String description) {
|
||||
super(amount, type, description);
|
||||
this.resetList();
|
||||
}
|
||||
|
||||
public abstract void executePayment(SpellAbility ability, Card targetCard);
|
||||
public final boolean executePayment(SpellAbility ability, Card targetCard) {
|
||||
addToList(targetCard);
|
||||
doPayment(ability, targetCard);
|
||||
return true;
|
||||
}
|
||||
|
||||
// always returns true, made this to inline with return
|
||||
public final boolean executePayment(SpellAbility ability, Collection<Card> targetCards) {
|
||||
for(Card c: targetCards)
|
||||
executePayment(ability, c);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract void doPayment(SpellAbility ability, Card targetCard);
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @return
|
||||
*/
|
||||
public abstract String getHashForList();
|
||||
|
||||
@Override
|
||||
public void payAI(PaymentDecision decision, AIPlayer ai, SpellAbility ability, Card source) {
|
||||
executePayment(ability, decision.cards);
|
||||
reportPaidCardsTo(ability);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,26 +29,7 @@ import forge.gui.GuiDialog;
|
||||
* The Class CostPayLife.
|
||||
*/
|
||||
public class CostPayLife extends CostPart {
|
||||
private int lastPaidAmount = 0;
|
||||
|
||||
/**
|
||||
* Gets the last paid amount.
|
||||
*
|
||||
* @return the last paid amount
|
||||
*/
|
||||
public final int getLastPaidAmount() {
|
||||
return this.lastPaidAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last paid amount.
|
||||
*
|
||||
* @param paidAmount
|
||||
* the new last paid amount
|
||||
*/
|
||||
public final void setLastPaidAmount(final int paidAmount) {
|
||||
this.lastPaidAmount = paidAmount;
|
||||
}
|
||||
int paidAmount = 0;
|
||||
|
||||
/**
|
||||
* Instantiates a new cost pay life.
|
||||
@@ -80,7 +61,7 @@ public class CostPayLife extends CostPart {
|
||||
@Override
|
||||
public final void refund(final Card source) {
|
||||
// Really should be activating player
|
||||
source.getController().payLife(this.lastPaidAmount * -1, null);
|
||||
source.getController().payLife(this.paidAmount * -1, null);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -104,15 +85,14 @@ public class CostPayLife extends CostPart {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
ai.payLife(this.getLastPaidAmount(), null);
|
||||
public void payAI(PaymentDecision decision, AIPlayer ai, SpellAbility ability, Card source) {
|
||||
// TODO Auto-generated method stub
|
||||
paidAmount = decision.c;
|
||||
ai.payLife(paidAmount, null);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -153,34 +133,29 @@ public class CostPayLife extends CostPart {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
paidAmount = c;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(this.getAmount());
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")) {
|
||||
return false;
|
||||
return null;
|
||||
} else {
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
}
|
||||
if (!ai.canPayLife(c)) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
// activator.payLife(c, null);
|
||||
this.setLastPaidAmount(c);
|
||||
return true;
|
||||
return new PaymentDecision(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.Map;
|
||||
import forge.Card;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.GameState;
|
||||
@@ -181,15 +182,17 @@ public class CostPayment {
|
||||
parts.add(new CostPartMana("0", 0, false));
|
||||
}
|
||||
|
||||
Map<Class<? extends CostPart>, PaymentDecision> decisions = new HashMap<Class<? extends CostPart>, PaymentDecision>();
|
||||
|
||||
// Set all of the decisions before attempting to pay anything
|
||||
for (final CostPart part : parts) {
|
||||
if (!part.decideAIPayment(ai, this.ability, source, this)) {
|
||||
return false;
|
||||
}
|
||||
PaymentDecision decision = part.decideAIPayment(ai, this.ability, source);
|
||||
if ( null == decision ) return false;
|
||||
decisions.put(part.getClass(), decision);
|
||||
}
|
||||
|
||||
for (final CostPart part : parts) {
|
||||
part.payAI(ai, this.ability, this.ability.getSourceCard(), this, game);
|
||||
part.payAI(decisions.get(part.getClass()), ai, this.ability, this.ability.getSourceCard());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -217,16 +217,14 @@ public class CostPutCounter extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public void payAI(PaymentDecision decision, AIPlayer ai, SpellAbility ability, Card source) {
|
||||
Integer c = getNumberOfCounters(ability);
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
executePayment(ability, source, c);
|
||||
} else {
|
||||
// Put counter on chosen card
|
||||
for (final Card card : this.getList()) {
|
||||
executePayment(ability, card);
|
||||
}
|
||||
executePayment(ability, decision.cards);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,20 +258,42 @@ public class CostPutCounter extends CostPartWithList {
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
this.resetList();
|
||||
protected void doPayment(SpellAbility ability, Card targetCard){
|
||||
targetCard.addCounter(this.getCounter(), 1, false);
|
||||
}
|
||||
|
||||
protected void executePayment(SpellAbility ability, Card targetCard, int c) {
|
||||
CounterType counterType = this.getCounter();
|
||||
if( c > 1 ) {
|
||||
Integer oldValue = targetCard.getCounters().get(counterType);
|
||||
int newValue = c + (oldValue == null ? 0 : oldValue.intValue()) - 1;
|
||||
targetCard.getCounters().put(counterType, Integer.valueOf(newValue));
|
||||
}
|
||||
// added c - 1 without firing triggers, the last counter added should fire trigger.
|
||||
executePayment(ability, targetCard);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getHashForList() {
|
||||
return "CounterPut";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
this.addToList(source);
|
||||
return true;
|
||||
} else {
|
||||
return new PaymentDecision(source);
|
||||
|
||||
}
|
||||
|
||||
final List<Card> typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), this.getType().split(";"), ai, source);
|
||||
|
||||
Card card = null;
|
||||
@@ -282,27 +302,6 @@ public class CostPutCounter extends CostPartWithList {
|
||||
} else {
|
||||
card = ComputerUtilCard.getWorstPermanentAI(typeList, false, false, false, false);
|
||||
}
|
||||
this.addToList(card);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard){
|
||||
executePayment(ability, targetCard, 1);
|
||||
}
|
||||
|
||||
public void executePayment(SpellAbility ability, Card targetCard, int c) {
|
||||
targetCard.addCounter(this.getCounter(), c, false);
|
||||
this.addToList(targetCard);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getHashForList() {
|
||||
return "CounterPut";
|
||||
return new PaymentDecision(card);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +183,7 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
|
||||
private final CounterType counter;
|
||||
private int lastPaidAmount = 0;
|
||||
private int cntCounters = 1;
|
||||
private ZoneType zone;
|
||||
|
||||
/**
|
||||
@@ -320,14 +321,11 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public void payAI(PaymentDecision decision, AIPlayer ai, SpellAbility ability, Card source) {
|
||||
final String amount = this.getAmount();
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
@@ -339,10 +337,10 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
}
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
source.subtractCounter(this.counter, c);
|
||||
executePayment(ability, source);
|
||||
} else {
|
||||
for (final Card card : this.getList()) {
|
||||
card.subtractCounter(this.counter, c);
|
||||
for (final Card card : decision.cards) {
|
||||
executePayment(ability, card);
|
||||
}
|
||||
}
|
||||
source.setSVar("CostCountersRemoved", "Number$" + Integer.toString(c));
|
||||
@@ -362,60 +360,57 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
Integer c = this.convertAmount();
|
||||
int maxCounters = 0;
|
||||
|
||||
if (!this.payCostFromSource()) {
|
||||
if (c == null) {
|
||||
if (amount.equals("All"))
|
||||
cntCounters = maxCounters;
|
||||
else if (c == null) {
|
||||
final String sVar = ability.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")) {
|
||||
c = CostUtil.chooseXValue(source, ability, maxCounters);
|
||||
cntCounters = CostUtil.chooseXValue(source, ability, maxCounters);
|
||||
} else {
|
||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||
}
|
||||
cntCounters = AbilityUtils.calculateAmount(source, amount, ability);
|
||||
}
|
||||
} else cntCounters = c;
|
||||
|
||||
|
||||
|
||||
if (!this.payCostFromSource()) {
|
||||
final InputPayment inp;
|
||||
if (this.getZone().equals(ZoneType.Battlefield)) {
|
||||
inp = new InputPayCostRemoveCounterType(c, ability, this.getType(), this);
|
||||
inp = new InputPayCostRemoveCounterType(cntCounters, ability, this.getType(), this);
|
||||
} else {
|
||||
inp = new InputPayCostRemoveCounterFrom(this, this.getType(), ability, c);
|
||||
inp = new InputPayCostRemoveCounterFrom(this, this.getType(), ability, cntCounters);
|
||||
}
|
||||
FThreads.setInputAndWait(inp);
|
||||
if( inp.isPaid() ) source.setSVar("CostCountersRemoved", "Number$" + Integer.toString(c));
|
||||
return inp.isPaid();
|
||||
}
|
||||
|
||||
maxCounters = source.getCounters(this.counter);
|
||||
if (amount.equals("All")) {
|
||||
c = maxCounters;
|
||||
} else {
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")) {
|
||||
c = CostUtil.chooseXValue(source, ability, maxCounters);
|
||||
} else {
|
||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maxCounters < c) return false;
|
||||
|
||||
|
||||
this.addToList(source);
|
||||
source.setSVar("CostCountersRemoved", "Number$" + Integer.toString(c));
|
||||
executePayment(ability, source, c);
|
||||
executePayment(ability, source);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
@Override
|
||||
protected void doPayment(SpellAbility ability, Card targetCard){
|
||||
targetCard.subtractCounter(this.getCounter(), cntCounters);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#getHashForList()
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
public String getHashForList() {
|
||||
return "CounterRemove";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
final String amount = this.getAmount();
|
||||
Integer c = this.convertAmount();
|
||||
|
||||
@@ -423,7 +418,7 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(amount);
|
||||
if (sVar.equals("XChoice")) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
if (amount.equals("All")) {
|
||||
c = source.getCounters(this.counter);
|
||||
@@ -433,41 +428,20 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
}
|
||||
|
||||
if (!this.payCostFromSource()) {
|
||||
this.getList().clear();
|
||||
final List<Card> typeList =
|
||||
CardLists.getValidCards(ai.getCardsIn(this.getZone()), this.getType().split(";"), ai, source);
|
||||
for (Card card : typeList) {
|
||||
if (card.getCounters(this.getCounter()) >= c) {
|
||||
this.addToList(card);
|
||||
return true;
|
||||
return new PaymentDecision(card);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (c > source.getCounters(this.getCounter())) {
|
||||
System.out.println("Not enough " + this.counter + " on " + source.getName());
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard) {
|
||||
executePayment(ability, targetCard, 1);
|
||||
}
|
||||
|
||||
public void executePayment(SpellAbility ability, Card targetCard, int n) {
|
||||
addToList(targetCard);
|
||||
targetCard.subtractCounter(getCounter(), n);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#getHashForList()
|
||||
*/
|
||||
@Override
|
||||
public String getHashForList() {
|
||||
return "CounterRemove";
|
||||
return new PaymentDecision(source);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,19 +111,6 @@ public class CostReturn extends CostPartWithList {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
for (final Card c : this.getList()) {
|
||||
executePayment(ability, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -180,30 +167,24 @@ public class CostReturn extends CostPartWithList {
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
this.resetList();
|
||||
if (this.payCostFromSource()) {
|
||||
this.getList().add(source);
|
||||
} else {
|
||||
public final PaymentDecision decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source) {
|
||||
if (this.payCostFromSource())
|
||||
return new PaymentDecision(source);
|
||||
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
|
||||
this.setList(ComputerUtil.chooseReturnType(ai, this.getType(), source, ability.getTargetCard(), c));
|
||||
if (this.getList().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
List<Card> res = ComputerUtil.chooseReturnType(ai, this.getType(), source, ability.getTargetCard(), c);
|
||||
return res.isEmpty() ? null : new PaymentDecision(res);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard) {
|
||||
addToList(targetCard);
|
||||
protected void doPayment(SpellAbility ability, Card targetCard) {
|
||||
ability.getActivatingPlayer().getGame().getAction().moveToHand(targetCard);
|
||||
}
|
||||
|
||||
@@ -215,6 +196,16 @@ public class CostReturn extends CostPartWithList {
|
||||
return "Returned";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void payAI(PaymentDecision decision, AIPlayer ai, SpellAbility ability, Card source) {
|
||||
for (final Card c : decision.cards) {
|
||||
executePayment(ability, c);
|
||||
}
|
||||
}
|
||||
|
||||
// Inputs
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ import forge.game.player.AIPlayer;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiChoose;
|
||||
import forge.view.ButtonUtil;
|
||||
|
||||
/**
|
||||
@@ -172,29 +171,25 @@ public class CostReveal extends CostPartWithList {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
|
||||
final String type = this.getType();
|
||||
List<Card> hand = new ArrayList<Card>(ai.getCardsIn(ZoneType.Hand));
|
||||
this.resetList();
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
if (!hand.contains(source)) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
return new PaymentDecision(source);
|
||||
}
|
||||
|
||||
this.getList().add(source);
|
||||
} else if (this.getType().equals("Hand")) {
|
||||
this.setList(new ArrayList<Card>(ai.getCardsIn(ZoneType.Hand)));
|
||||
return true;
|
||||
} else {
|
||||
if (this.getType().equals("Hand"))
|
||||
return new PaymentDecision(new ArrayList<Card>(ai.getCardsIn(ZoneType.Hand)));
|
||||
|
||||
hand = CardLists.getValidCards(hand, type.split(";"), ai, source);
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
@@ -206,22 +201,7 @@ public class CostReveal extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
|
||||
this.setList(ai.getAi().getCardsToDiscard(c, type.split(";"), ability));
|
||||
}
|
||||
return this.getList() != null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
GuiChoose.oneOrNone("Revealed cards:", this.getList());
|
||||
for(Card c: getList()) // should not throw concurrent modification here - no items should be added.
|
||||
executePayment(ability, c);
|
||||
return new PaymentDecision(ai.getAi().getCardsToDiscard(c, type.split(";"), ability));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -236,7 +216,6 @@ public class CostReveal extends CostPartWithList {
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
final Card source = ability.getSourceCard();
|
||||
final String amount = this.getAmount();
|
||||
this.resetList();
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
executePayment(ability, source);
|
||||
@@ -304,8 +283,7 @@ public class CostReveal extends CostPartWithList {
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard) {
|
||||
addToList(targetCard);
|
||||
protected void doPayment(SpellAbility ability, Card targetCard) {
|
||||
// write code to actually reveal card
|
||||
}
|
||||
|
||||
|
||||
@@ -184,20 +184,6 @@ public class CostSacrifice extends CostPartWithList {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
this.reportPaidCardsTo(ability);
|
||||
for (final Card c : this.getList()) {
|
||||
executePayment(ability, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -219,18 +205,11 @@ public class CostSacrifice extends CostPartWithList {
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
if (source.getController() == ability.getActivatingPlayer() && source.isInPlay()) {
|
||||
if (!GuiDialog.confirm(source, source.getName() + " - Sacrifice?"))
|
||||
return false;
|
||||
executePayment(ability, source);
|
||||
return true;
|
||||
return GuiDialog.confirm(source, source.getName() + " - Sacrifice?") && executePayment(ability, source);
|
||||
|
||||
}
|
||||
} else if (amount.equals("All")) {
|
||||
this.setList(list);
|
||||
// TODO Ask First
|
||||
for (final Card card : list) {
|
||||
executePayment(ability, card);
|
||||
}
|
||||
return true;
|
||||
return executePayment(ability, list);
|
||||
} else {
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
@@ -251,50 +230,8 @@ public class CostSacrifice extends CostPartWithList {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
this.resetList();
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
if (this.payCostFromSource()) {
|
||||
this.getList().add(source);
|
||||
} else if (this.getAmount().equals("All")) {
|
||||
/*List<Card> typeList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Battlefield));
|
||||
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source);
|
||||
if (activator.hasKeyword("You can't sacrifice creatures to cast spells or activate abilities.")) {
|
||||
typeList = CardLists.getNotType(typeList, "Creature");
|
||||
}*/
|
||||
// Does the AI want to use Sacrifice All?
|
||||
return false;
|
||||
} else {
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
if (ability.getSVar(this.getAmount()).equals("XChoice")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
this.setList(ComputerUtil.chooseSacrificeType(activator, this.getType(), source, ability.getTargetCard(), c));
|
||||
if (this.getList() == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard) {
|
||||
this.addToList(targetCard);
|
||||
protected void doPayment(SpellAbility ability, Card targetCard) {
|
||||
ability.getActivatingPlayer().getGame().getAction().sacrifice(targetCard, ability);
|
||||
}
|
||||
|
||||
@@ -306,6 +243,37 @@ public class CostSacrifice extends CostPartWithList {
|
||||
return "Sacrificed";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
return new PaymentDecision(source);
|
||||
}
|
||||
if (this.getAmount().equals("All")) {
|
||||
/*List<Card> typeList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Battlefield));
|
||||
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source);
|
||||
if (activator.hasKeyword("You can't sacrifice creatures to cast spells or activate abilities.")) {
|
||||
typeList = CardLists.getNotType(typeList, "Creature");
|
||||
}*/
|
||||
// Does the AI want to use Sacrifice All?
|
||||
return null;
|
||||
}
|
||||
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
if (ability.getSVar(this.getAmount()).equals("XChoice")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
}
|
||||
List<Card> list = ComputerUtil.chooseSacrificeType(ai, this.getType(), source, ability.getTargetCard(), c);
|
||||
return new PaymentDecision(list);
|
||||
}
|
||||
|
||||
// Inputs
|
||||
|
||||
}
|
||||
|
||||
@@ -74,14 +74,11 @@ public class CostTap extends CostPart {
|
||||
return source.isUntapped() && (!source.isSick() || source.hasKeyword("CARDNAME may activate abilities as though it has haste."));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public void payAI(PaymentDecision decision, AIPlayer ai, SpellAbility ability, Card source) {
|
||||
source.tap();
|
||||
}
|
||||
|
||||
@@ -102,15 +99,11 @@ public class CostTap extends CostPart {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
return true;
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
return new PaymentDecision(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,8 @@ public class CostTapType extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
|
||||
private final boolean canTapSource;
|
||||
|
||||
/**
|
||||
* Instantiates a new cost tap type.
|
||||
*
|
||||
@@ -110,8 +112,9 @@ public class CostTapType extends CostPartWithList {
|
||||
* @param description
|
||||
* the description
|
||||
*/
|
||||
public CostTapType(final String amount, final String type, final String description) {
|
||||
public CostTapType(final String amount, final String type, final String description, boolean costHasTapSource) {
|
||||
super(amount, type, description);
|
||||
canTapSource = !costHasTapSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -187,19 +190,6 @@ public class CostTapType extends CostPartWithList {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
for (final Card c : this.getList()) {
|
||||
c.tap();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -229,16 +219,11 @@ public class CostTapType extends CostPartWithList {
|
||||
return inp.isPaid();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
final boolean tap = payment.getCost().hasTapCost();
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
final String amount = this.getAmount();
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
@@ -254,22 +239,22 @@ public class CostTapType extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
|
||||
this.setList(ComputerUtil.chooseTapType(ai, this.getType(), source, tap, c));
|
||||
List<Card> totap = ComputerUtil.chooseTapType(ai, this.getType(), source, !canTapSource, c);
|
||||
|
||||
if (this.getList() == null) {
|
||||
|
||||
if (totap == null) {
|
||||
System.out.println("Couldn't find a valid card to tap for: " + source.getName());
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
return true;
|
||||
return new PaymentDecision(totap);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard) {
|
||||
addToList(targetCard);
|
||||
protected void doPayment(SpellAbility ability, Card targetCard) {
|
||||
targetCard.tap();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,26 +86,6 @@ public class CostUnattach extends CostPartWithList {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
Card cardToUnattach = findCardToUnattach(source, (Player) ai, ability);
|
||||
if (cardToUnattach == null) {
|
||||
// We really shouldn't be able to get here if there's nothing to unattach
|
||||
return;
|
||||
}
|
||||
|
||||
Card equippingCard = cardToUnattach.getEquipping().get(0);
|
||||
cardToUnattach.unEquipCard(equippingCard);
|
||||
this.addToList(cardToUnattach);
|
||||
this.reportPaidCardsTo(ability);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -146,30 +126,29 @@ public class CostUnattach extends CostPartWithList {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
this.resetList();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard) {
|
||||
protected void doPayment(SpellAbility ability, Card targetCard) {
|
||||
targetCard.unEquipCard(targetCard.getEquipping().get(0));
|
||||
this.addToList(targetCard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHashForList() {
|
||||
return "Unattached";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
Card cardToUnattach = findCardToUnattach(source, (Player) ai, ability);
|
||||
if (cardToUnattach == null) {
|
||||
// We really shouldn't be able to get here if there's nothing to unattach
|
||||
return null;
|
||||
}
|
||||
return new PaymentDecision(cardToUnattach.getEquippingCard());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,17 +73,6 @@ public class CostUntap extends CostPart {
|
||||
return source.isTapped() && (!source.isSick() || source.hasKeyword("CARDNAME may activate abilities as though it has haste."));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
source.untap();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -101,15 +90,19 @@ public class CostUntap extends CostPart {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
return true;
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
return new PaymentDecision(0);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void payAI(PaymentDecision decision, AIPlayer ai, SpellAbility ability, Card source) {
|
||||
source.untap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ public class CostUntapType extends CostPartWithList {
|
||||
private final CostUntapType untapType;
|
||||
private static final long serialVersionUID = -7151144318287088542L;
|
||||
private int nUntapped = 0;
|
||||
private final SpellAbility sa;
|
||||
|
||||
|
||||
/**
|
||||
@@ -56,13 +57,15 @@ public class CostUntapType extends CostPartWithList {
|
||||
* @param nCards
|
||||
* @param cardList
|
||||
* @param untapType
|
||||
* @param ability
|
||||
* @param sa
|
||||
* @param payment
|
||||
*/
|
||||
public InputPayCostUntapY(int nCards, List<Card> cardList, CostUntapType untapType) {
|
||||
public InputPayCostUntapY(int nCards, List<Card> cardList, CostUntapType untapType, SpellAbility ability) {
|
||||
this.nCards = nCards;
|
||||
this.cardList = cardList;
|
||||
this.untapType = untapType;
|
||||
this.sa = ability;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,14 +84,12 @@ public class CostUntapType extends CostPartWithList {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
|
||||
if (zone.is(ZoneType.Battlefield) && cardList.contains(card) && card.isTapped()) {
|
||||
// send in List<Card> for Typing
|
||||
card.untap();
|
||||
untapType.addToList(card);
|
||||
untapType.executePayment(sa, card);
|
||||
cardList.remove(card);
|
||||
|
||||
this.nUntapped++;
|
||||
@@ -154,17 +155,6 @@ public class CostUntapType extends CostPartWithList {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the card to untapped list.
|
||||
*
|
||||
* @param c
|
||||
* the card
|
||||
*/
|
||||
public final void addToUntappedList(final Card c) {
|
||||
this.getList().add(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -205,19 +195,6 @@ public class CostUntapType extends CostPartWithList {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
for (final Card c : this.getList()) {
|
||||
c.untap();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -246,21 +223,33 @@ public class CostUntapType extends CostPartWithList {
|
||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
InputPayment inp = new InputPayCostUntapY(c, typeList, this);
|
||||
InputPayment inp = new InputPayCostUntapY(c, typeList, this, ability);
|
||||
FThreads.setInputAndWait(inp);
|
||||
return inp.isPaid();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
|
||||
* , forge.Card, forge.card.cost.Cost_Payment)
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public final boolean decideAIPayment(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment) {
|
||||
final boolean untap = payment.getCost().hasUntapCost();
|
||||
protected void doPayment(SpellAbility ability, Card targetCard) {
|
||||
targetCard.untap();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#getHashForList()
|
||||
*/
|
||||
@Override
|
||||
public String getHashForList() {
|
||||
return "Untapped";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) {
|
||||
boolean untap = false; // payment.getCost().hasUntapCost();
|
||||
final String amount = this.getAmount();
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
@@ -279,31 +268,14 @@ public class CostUntapType extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
|
||||
this.setList(ComputerUtil.chooseUntapType(ai, this.getType(), source, untap, c));
|
||||
List<Card> list = ComputerUtil.chooseUntapType(ai, this.getType(), source, untap, c);
|
||||
|
||||
if (this.getList() == null) {
|
||||
if (list == null) {
|
||||
System.out.println("Couldn't find a valid card to untap for: " + source.getName());
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||
*/
|
||||
@Override
|
||||
public void executePayment(SpellAbility ability, Card targetCard) {
|
||||
addToList(targetCard);
|
||||
targetCard.untap();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.cost.CostPartWithList#getHashForList()
|
||||
*/
|
||||
@Override
|
||||
public String getHashForList() {
|
||||
return "Untapped";
|
||||
return new PaymentDecision(list);
|
||||
}
|
||||
|
||||
// Inputs
|
||||
|
||||
35
src/main/java/forge/card/cost/PaymentDecision.java
Normal file
35
src/main/java/forge/card/cost/PaymentDecision.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import forge.Card;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public class PaymentDecision {
|
||||
public int c = 0;
|
||||
public final List<Card> cards = new ArrayList<Card>();
|
||||
|
||||
public PaymentDecision(int cnt) {
|
||||
c = cnt;
|
||||
}
|
||||
|
||||
public PaymentDecision(List<Card> chosen) {
|
||||
cards.addAll(chosen);
|
||||
}
|
||||
|
||||
public PaymentDecision(Card chosen) {
|
||||
cards.add(chosen);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Payment Decision: %d, %s", c, cards);
|
||||
}
|
||||
}
|
||||
@@ -28,9 +28,13 @@ import forge.CardLists;
|
||||
import forge.CardPredicates;
|
||||
import forge.CardPredicates.Presets;
|
||||
import forge.CounterType;
|
||||
import forge.FThreads;
|
||||
import forge.GameEntity;
|
||||
import forge.Singletons;
|
||||
import forge.control.input.InputBase;
|
||||
import forge.control.input.InputSelectCards;
|
||||
import forge.control.input.InputSelectCardsFromList;
|
||||
import forge.control.input.InputSyncronizedBase;
|
||||
import forge.game.GameState;
|
||||
import forge.game.ai.ComputerUtilCard;
|
||||
import forge.game.player.Player;
|
||||
@@ -106,20 +110,28 @@ public class Untap extends Phase {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static final Predicate<Card> CANUNTAP = new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(Card c) {
|
||||
return Untap.canUntap(c);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* doUntap.
|
||||
* </p>
|
||||
*/
|
||||
private void doUntap() {
|
||||
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
|
||||
final Predicate<Card> tappedCanUntap = Predicates.and(Presets.TAPPED, Presets.CANUNTAP);
|
||||
final Player player = game.getPhaseHandler().getPlayerTurn();
|
||||
final Predicate<Card> tappedCanUntap = Predicates.and(Presets.TAPPED, CANUNTAP);
|
||||
|
||||
List<Card> list = new ArrayList<Card>(player.getCardsIn(ZoneType.Battlefield));
|
||||
|
||||
List<Card> bounceList = CardLists.getKeyword(list, "During your next untap step, as you untap your permanents, return CARDNAME to its owner's hand.");
|
||||
for (final Card c : bounceList) {
|
||||
Singletons.getModel().getGame().getAction().moveToHand(c);
|
||||
game.getAction().moveToHand(c);
|
||||
}
|
||||
|
||||
list = CardLists.filter(list, new Predicate<Card>() {
|
||||
@@ -128,16 +140,13 @@ public class Untap extends Phase {
|
||||
if (!Untap.canUntap(c)) {
|
||||
return false;
|
||||
}
|
||||
if (Untap.canOnlyUntapOneLand() && c.isLand()) {
|
||||
if (canOnlyUntapOneLand() && c.isLand()) {
|
||||
return false;
|
||||
}
|
||||
if (c.isArtifact()
|
||||
&& (Singletons.getModel().getGame().isCardInPlay("Damping Field") || Singletons.getModel().getGame().isCardInPlay("Imi Statue"))) {
|
||||
if (c.isArtifact() && (game.isCardInPlay("Damping Field") || game.isCardInPlay("Imi Statue"))) {
|
||||
return false;
|
||||
}
|
||||
if (c.isCreature()
|
||||
&& (Singletons.getModel().getGame().isCardInPlay("Smoke") || Singletons.getModel().getGame().isCardInPlay("Stoic Angel")
|
||||
|| Singletons.getModel().getGame().isCardInPlay("Intruder Alarm"))) {
|
||||
if (c.isCreature() && (game.isCardInPlay("Smoke") || game.isCardInPlay("Stoic Angel") || game.isCardInPlay("Intruder Alarm"))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -181,7 +190,7 @@ public class Untap extends Phase {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((c.getCounters(CounterType.WIND) > 0) && Singletons.getModel().getGame().isCardInPlay("Freyalise's Winds")) {
|
||||
} else if ((c.getCounters(CounterType.WIND) > 0) && game.isCardInPlay("Freyalise's Winds")) {
|
||||
// remove a WIND counter instead of untapping
|
||||
c.subtractCounter(CounterType.WIND, 1);
|
||||
} else {
|
||||
@@ -190,7 +199,7 @@ public class Untap extends Phase {
|
||||
}
|
||||
|
||||
// other players untapping during your untap phase
|
||||
final List<Card> cardsWithKW = CardLists.getKeyword(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield),
|
||||
final List<Card> cardsWithKW = CardLists.getKeyword(game.getCardsIn(ZoneType.Battlefield),
|
||||
"CARDNAME untaps during each other player's untap step.");
|
||||
final List<Player> otherPlayers = player.getOpponents();
|
||||
otherPlayers.addAll(player.getAllies());
|
||||
@@ -200,123 +209,49 @@ public class Untap extends Phase {
|
||||
}
|
||||
// end other players untapping during your untap phase
|
||||
|
||||
if (Untap.canOnlyUntapOneLand()) {
|
||||
if (canOnlyUntapOneLand()) {
|
||||
final List<Card> landList = CardLists.filter(player.getLandsInPlay(), tappedCanUntap);
|
||||
|
||||
if (!landList.isEmpty()) {
|
||||
if (player.isComputer()) {
|
||||
// search for lands the computer has and only untap 1
|
||||
List<Card> landList = player.getLandsInPlay();
|
||||
|
||||
landList = CardLists.filter(landList, tappedCanUntap);
|
||||
if (landList.size() > 0) {
|
||||
landList.get(0).untap();
|
||||
}
|
||||
} else {
|
||||
final InputBase target = new InputBase() {
|
||||
private static final long serialVersionUID = 6653677835629939465L;
|
||||
final InputSelectCards target = new InputSelectCardsFromList(1,1, landList);
|
||||
target.setMessage("Select one tapped land to untap");
|
||||
FThreads.setInputAndWait(target);
|
||||
if( !target.hasCancelled() && !target.getSelected().isEmpty())
|
||||
target.getSelected().get(0).untap();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (game.isCardInPlay("Damping Field") || game.isCardInPlay("Imi Statue")) {
|
||||
final Player turnOwner = game.getPhaseHandler().getPlayerTurn();
|
||||
final List<Card> artList = CardLists.filter(turnOwner.getCardsIn(ZoneType.Battlefield), Presets.ARTIFACTS, tappedCanUntap);
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage("Select one tapped land to untap");
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card c) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(c);
|
||||
if (c.isLand() && zone.is(ZoneType.Battlefield) && c.isTapped() && Untap.canUntap(c)) {
|
||||
c.untap();
|
||||
this.stop();
|
||||
}
|
||||
} // selectCard()
|
||||
}; // Input
|
||||
List<Card> landList = player.getLandsInPlay();
|
||||
landList = CardLists.filter(landList, tappedCanUntap);
|
||||
if (landList.size() > 0) {
|
||||
Singletons.getModel().getMatch().getInput().setInput(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Singletons.getModel().getGame().isCardInPlay("Damping Field") || Singletons.getModel().getGame().isCardInPlay("Imi Statue")) {
|
||||
final Player turnOwner = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
|
||||
if (!artList.isEmpty()) {
|
||||
if (turnOwner.isComputer()) {
|
||||
List<Card> artList = new ArrayList<Card>(turnOwner.getCardsIn(ZoneType.Battlefield));
|
||||
artList = CardLists.filter(artList, Presets.ARTIFACTS);
|
||||
artList = CardLists.filter(artList, tappedCanUntap);
|
||||
if (artList.size() > 0) {
|
||||
ComputerUtilCard.getBestArtifactAI(artList).untap();
|
||||
}
|
||||
} else {
|
||||
final InputBase target = new InputBase() {
|
||||
private static final long serialVersionUID = 5555427219659889707L;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage("Select one tapped artifact to untap");
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card c) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(c);
|
||||
if (c.isArtifact() && zone.is(ZoneType.Battlefield) && c.getController().isHuman()
|
||||
&& Untap.canUntap(c)) {
|
||||
c.untap();
|
||||
this.stop();
|
||||
}
|
||||
} // selectCard()
|
||||
}; // Input
|
||||
List<Card> artList = new ArrayList<Card>(turnOwner.getCardsIn(ZoneType.Battlefield));
|
||||
artList = CardLists.filter(artList, Presets.ARTIFACTS);
|
||||
artList = CardLists.filter(artList, tappedCanUntap);
|
||||
if (artList.size() > 0) {
|
||||
Singletons.getModel().getMatch().getInput().setInput(target);
|
||||
final InputSelectCards target = new InputSelectCardsFromList(1,1, artList);
|
||||
target.setMessage("Select one tapped artifact to untap");
|
||||
FThreads.setInputAndWait(target);
|
||||
if( !target.hasCancelled() && !target.getSelected().isEmpty())
|
||||
target.getSelected().get(0).untap();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((Singletons.getModel().getGame().isCardInPlay("Smoke") || Singletons.getModel().getGame().isCardInPlay("Stoic Angel"))) {
|
||||
if (player.isComputer()) {
|
||||
List<Card> creatures = player.getCreaturesInPlay();
|
||||
creatures = CardLists.filter(creatures, tappedCanUntap);
|
||||
if (creatures.size() > 0) {
|
||||
creatures.get(0).untap();
|
||||
}
|
||||
} else {
|
||||
final InputBase target = new InputBase() {
|
||||
private static final long serialVersionUID = 5555427219659889707L;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage("Select one creature to untap");
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card c) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(c);
|
||||
if (c.isCreature() && zone.is(ZoneType.Battlefield) && c.getController().isHuman()
|
||||
&& Untap.canUntap(c)) {
|
||||
c.untap();
|
||||
this.stop();
|
||||
}
|
||||
} // selectCard()
|
||||
}; // Input
|
||||
if ((game.isCardInPlay("Smoke") || game.isCardInPlay("Stoic Angel"))) {
|
||||
final List<Card> creatures = CardLists.filter(player.getCreaturesInPlay(), tappedCanUntap);
|
||||
if (creatures.size() > 0) {
|
||||
Singletons.getModel().getMatch().getInput().setInput(target);
|
||||
if (!creatures.isEmpty()) {
|
||||
if (player.isComputer()) {
|
||||
creatures.get(0).untap();
|
||||
} else {
|
||||
final InputSelectCards target = new InputSelectCardsFromList(1, 1, creatures);
|
||||
target.setMessage("Select one creature to untap");
|
||||
FThreads.setInputAndWait(target);
|
||||
if( !target.hasCancelled() && !target.getSelected().isEmpty())
|
||||
target.getSelected().get(0).untap();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,11 +269,10 @@ public class Untap extends Phase {
|
||||
game.getStack().chooseOrderOfSimultaneousStackEntryAll();
|
||||
} // end doUntap
|
||||
|
||||
private static boolean canOnlyUntapOneLand() {
|
||||
private boolean canOnlyUntapOneLand() {
|
||||
// Winter Orb was given errata so it no longer matters if it's tapped or
|
||||
// not
|
||||
if (Singletons.getModel().getGame().isCardInPlay("Winter Orb")
|
||||
|| Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().isCardInPlay("Mungha Wurm")) {
|
||||
if (game.isCardInPlay("Winter Orb") || game.getPhaseHandler().getPlayerTurn().isCardInPlay("Mungha Wurm")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package forge.gui;
|
||||
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import forge.Card;
|
||||
import forge.FThreads;
|
||||
@@ -39,7 +40,7 @@ import forge.game.player.Player;
|
||||
public class InputProxy implements Observer {
|
||||
|
||||
/** The input. */
|
||||
private Input input;
|
||||
private AtomicReference<Input> input = new AtomicReference<Input>();
|
||||
private MatchController match = null;
|
||||
|
||||
public void setMatch(MatchController matchController) {
|
||||
@@ -48,7 +49,7 @@ public class InputProxy implements Observer {
|
||||
|
||||
@Override
|
||||
public final synchronized void update(final Observable observable, final Object obj) {
|
||||
this.input = null;
|
||||
this.input.set(null);
|
||||
final GameState game = match.getCurrentGame();
|
||||
final PhaseHandler ph = game.getPhaseHandler();
|
||||
|
||||
@@ -68,7 +69,7 @@ public class InputProxy implements Observer {
|
||||
//System.out.printf(" input is %s \t stack = %s%n", nextInput == null ? "null" : nextInput.getClass().getSimpleName(), match.getInput().printInputStack());
|
||||
|
||||
if (nextInput != null) {
|
||||
this.input = nextInput;
|
||||
this.input.set(nextInput);
|
||||
FThreads.invokeInEDT(new Runnable() { @Override public void run() { nextInput.showMessage(); } });
|
||||
} else if (!ph.isPlayerPriorityAllowed()) {
|
||||
ph.getPriorityPlayer().getController().passPriority();
|
||||
@@ -80,8 +81,9 @@ public class InputProxy implements Observer {
|
||||
* </p>
|
||||
*/
|
||||
public final void selectButtonOK() {
|
||||
if ( null == input ) return;
|
||||
input.selectButtonOK();
|
||||
Input inp = getInput();
|
||||
if ( null != inp )
|
||||
inp.selectButtonOK();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,8 +92,9 @@ public class InputProxy implements Observer {
|
||||
* </p>
|
||||
*/
|
||||
public final void selectButtonCancel() {
|
||||
if ( null == input ) return;
|
||||
input.selectButtonCancel();
|
||||
Input inp = getInput();
|
||||
if ( null != inp )
|
||||
inp.selectButtonCancel();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,8 +106,9 @@ public class InputProxy implements Observer {
|
||||
* a {@link forge.game.player.Player} object.
|
||||
*/
|
||||
public final void selectPlayer(final Player player) {
|
||||
if ( null == input ) return;
|
||||
input.selectPlayer(player);
|
||||
Input inp = getInput();
|
||||
if ( null != inp )
|
||||
inp.selectPlayer(player);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,19 +122,20 @@ public class InputProxy implements Observer {
|
||||
* a {@link forge.game.zone.PlayerZone} object.
|
||||
*/
|
||||
public final void selectCard(final Card card) {
|
||||
if ( null == input ) return;
|
||||
input.selectCard(card);
|
||||
Input inp = getInput();
|
||||
if ( null != inp )
|
||||
inp.selectCard(card);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final String toString() {
|
||||
if ( null == input ) return "(null)";
|
||||
return this.input.toString();
|
||||
Input inp = getInput();
|
||||
return null == inp ? "(null)" : inp.toString();
|
||||
}
|
||||
|
||||
/** @return {@link forge.gui.InputProxy.InputBase} */
|
||||
public Input getInput() {
|
||||
return this.input;
|
||||
return this.input.get();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user