ai cost decisions now use visitors

This commit is contained in:
Maxmtg
2013-12-27 09:26:39 +00:00
parent c45fe42129
commit 1ede72b64a
34 changed files with 737 additions and 803 deletions

View File

@@ -0,0 +1,666 @@
package forge.ai;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CounterType;
import forge.game.card.CardPredicates.Presets;
import forge.game.cost.CostAddMana;
import forge.game.cost.CostChooseCreatureType;
import forge.game.cost.CostDamage;
import forge.game.cost.CostDiscard;
import forge.game.cost.CostDraw;
import forge.game.cost.CostExile;
import forge.game.cost.CostExileAndPay;
import forge.game.cost.CostExiledMoveToGrave;
import forge.game.cost.CostFlipCoin;
import forge.game.cost.CostGainControl;
import forge.game.cost.CostGainLife;
import forge.game.cost.CostMill;
import forge.game.cost.CostPartMana;
import forge.game.cost.CostPayLife;
import forge.game.cost.CostPutCardToLib;
import forge.game.cost.CostPutCounter;
import forge.game.cost.CostRemoveAnyCounter;
import forge.game.cost.CostRemoveCounter;
import forge.game.cost.CostReturn;
import forge.game.cost.CostReveal;
import forge.game.cost.CostSacrifice;
import forge.game.cost.CostTap;
import forge.game.cost.CostTapType;
import forge.game.cost.CostUnattach;
import forge.game.cost.CostUntap;
import forge.game.cost.CostUntapType;
import forge.game.cost.PaymentDecision;
import forge.game.cost.ICostVisitor;
import forge.game.player.Player;
import forge.game.player.PlayerControllerAi;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellPermanent;
import forge.game.zone.ZoneType;
public class AiCostDecision implements ICostVisitor<PaymentDecision> {
private final Player ai;
private final SpellAbility ability;
private final Card source;
public AiCostDecision(Player ai0, SpellAbility sa, Card source0) {
ai = ai0;
ability = sa;
source = source0;
}
@Override
public PaymentDecision visit(CostAddMana cost) {
Integer c = cost.convertAmount();
if (c == null) {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
return new PaymentDecision(c);
}
@Override
public PaymentDecision visit(CostChooseCreatureType cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null; // cannot pay
} else {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
}
return new PaymentDecision(c);
}
@Override
public PaymentDecision visit(CostDiscard cost) {
final String type = cost.getType();
final List<Card> hand = ai.getCardsIn(ZoneType.Hand);
if (type.equals("LastDrawn")) {
if (!hand.contains(ai.getLastDrawnCard())) {
return null;
}
return new PaymentDecision(ai.getLastDrawnCard());
}
else if (cost.payCostFromSource()) {
if (!hand.contains(source)) {
return null;
}
return new PaymentDecision(source);
}
else if (type.equals("Hand")) {
return new PaymentDecision(hand);
}
if (type.contains("WithSameName")) {
return null;
}
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
if (type.equals("Random")) {
return new PaymentDecision(CardLists.getRandomSubList(hand, c));
}
else {
final AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
return new PaymentDecision(aic.getCardsToDiscard(c, type.split(";"), ability));
}
}
@Override
public PaymentDecision visit(CostDamage cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null; // cannot pay
} else {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
}
return new PaymentDecision(c);
}
@Override
public PaymentDecision visit(CostDraw cost) {
Integer c = cost.convertAmount();
if (c == null) {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
return new PaymentDecision(c);
}
@Override
public PaymentDecision visit(CostExile cost) {
if (cost.payCostFromSource()) {
return new PaymentDecision(source);
}
if (cost.getType().equals("All")) {
return new PaymentDecision(new ArrayList<Card>(ai.getCardsIn(cost.getFrom())));
}
else if (cost.getType().contains("FromTopGrave")) {
return null;
}
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
if (cost.getFrom().equals(ZoneType.Library)) {
return new PaymentDecision(ai.getCardsIn(ZoneType.Library, c));
}
else if (cost.sameZone) {
// TODO Determine exile from same zone for AI
return null;
}
else {
List<Card> chosen = ComputerUtil.chooseExileFrom(ai, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c);
return null == chosen ? null : new PaymentDecision(chosen);
}
}
@Override
public PaymentDecision visit(CostExileAndPay cost) {
List<Card> validGrave = CardLists.getValidCards(ability.getActivatingPlayer().getZone(ZoneType.Graveyard), "Creature", ability.getActivatingPlayer(), ability.getSourceCard());
if(validGrave.size() == 0)
{
return null;
}
Card bestCard = null;
int bestScore = 0;
for(Card candidate : validGrave)
{
boolean selectable = false;
for(SpellAbility sa : candidate.getSpellAbilities())
{
if(sa instanceof SpellPermanent)
{
if(ComputerUtilCost.canPayCost(sa, ai))
{
selectable = true;
}
}
}
if(!selectable)
{
continue;
}
int candidateScore = ComputerUtilCard.evaluateCreature(candidate);
if(candidateScore > bestScore)
{
bestScore = candidateScore;
bestCard = candidate;
}
}
return bestCard == null ? null : new PaymentDecision(bestCard);
}
@Override
public PaymentDecision visit(CostExiledMoveToGrave cost) {
Integer c = cost.convertAmount();
List<Card> chosen = new ArrayList<Card>();
if (c == null) {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
List<Card> typeList = ai.getGame().getCardsIn(ZoneType.Exile);
typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), ai, source);
if (typeList.size() < c) {
return null;
}
CardLists.sortByPowerAsc(typeList);
Collections.reverse(typeList);
for (int i = 0; i < c; i++) {
chosen.add(typeList.get(i));
}
return chosen.isEmpty() ? null : new PaymentDecision(chosen);
}
@Override
public PaymentDecision visit(CostFlipCoin cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
return new PaymentDecision(c);
}
@Override
public PaymentDecision visit(CostGainControl cost) {
if (cost.payCostFromSource())
return new PaymentDecision(source);
Integer c = cost.convertAmount();
if (c == null) {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
final List<Card> typeList = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ai, source);
if (typeList.size() < c) {
return null;
}
CardLists.sortByPowerAsc(typeList);
final List<Card> res = new ArrayList<Card>();
for (int i = 0; i < c; i++) {
res.add(typeList.get(i));
}
return res.isEmpty() ? null : new PaymentDecision(res);
}
@Override
public PaymentDecision visit(CostGainLife cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
} else {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
}
final List<Player> oppsThatCanGainLife = new ArrayList<Player>();
for (final Player opp : ai.getOpponents()) {
if (opp.canGainLife()) {
oppsThatCanGainLife.add(opp);
}
}
if (oppsThatCanGainLife.size() == 0) {
return null;
}
return new PaymentDecision(c);
}
@Override
public PaymentDecision visit(CostMill cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
List<Card> topLib = ai.getCardsIn(ZoneType.Library, c);
return topLib.size() < c ? null : new PaymentDecision(topLib);
}
@Override
public PaymentDecision visit(CostPartMana cost) {
return new PaymentDecision(0);
}
@Override
public PaymentDecision visit(CostPayLife cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
} else {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
}
if (!ai.canPayLife(c)) {
return null;
}
// activator.payLife(c, null);
return new PaymentDecision(c);
}
@Override
public PaymentDecision visit(CostPutCardToLib cost) {
Integer c = cost.convertAmount();
final Game game = ai.getGame();
List<Card> chosen = new ArrayList<Card>();
List<Card> list;
if (cost.isSameZone()) {
list = new ArrayList<Card>(game.getCardsIn(cost.getFrom()));
} else {
list = new ArrayList<Card>(ai.getCardsIn(cost.getFrom()));
}
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
list = CardLists.getValidCards(list, cost.getType().split(";"), ai, source);
if (cost.isSameZone()) {
// Jotun Grunt
// TODO: improve AI
final List<Player> players = game.getPlayers();
for (Player p : players) {
List<Card> enoughType = CardLists.filter(list, CardPredicates.isOwner(p));
if (enoughType.size() >= c) {
chosen.addAll(enoughType);
break;
}
}
chosen = chosen.subList(0, c);
} else {
chosen = ComputerUtil.choosePutToLibraryFrom(ai, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c);
}
return chosen.isEmpty() ? null : new PaymentDecision(chosen);
}
@Override
public PaymentDecision visit(CostPutCounter cost) {
if (cost.payCostFromSource()) {
return new PaymentDecision(source);
}
final List<Card> typeList = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ai, source);
Card card = null;
if (cost.getType().equals("Creature.YouCtrl")) {
card = ComputerUtilCard.getWorstCreatureAI(typeList);
} else {
card = ComputerUtilCard.getWorstPermanentAI(typeList, false, false, false, false);
}
return new PaymentDecision(card);
}
@Override
public PaymentDecision visit(CostTap cost) {
return new PaymentDecision(0);
}
@Override
public PaymentDecision visit(CostTapType cost) {
final String amount = cost.getAmount();
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) {
List<Card> typeList =
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard());
typeList = CardLists.filter(typeList, Presets.UNTAPPED);
c = typeList.size();
source.setSVar("ChosenX", "Number$" + Integer.toString(c));
} else {
c = AbilityUtils.calculateAmount(source, amount, ability);
}
}
if (cost.getType().contains("sharesCreatureTypeWith") || cost.getType().contains("withTotalPowerGE")) {
return null;
}
List<Card> totap = ComputerUtil.chooseTapType(ai, cost.getType(), source, !cost.canTapSource, c);
if (totap == null) {
System.out.println("Couldn't find a valid card to tap for: " + source.getName());
return null;
}
return new PaymentDecision(totap);
}
@Override
public PaymentDecision visit(CostSacrifice cost) {
if (cost.payCostFromSource()) {
return new PaymentDecision(source);
}
if (cost.getAmount().equals("All")) {
/*List<Card> typeList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Battlefield));
typeList = CardLists.getValidCards(typeList, cost.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 = cost.convertAmount();
if (c == null) {
if (ability.getSVar(cost.getAmount()).equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
List<Card> list = ComputerUtil.chooseSacrificeType(ai, cost.getType(), source, ability.getTargetCard(), c);
return new PaymentDecision(list);
}
@Override
public PaymentDecision visit(CostReturn cost) {
if (cost.payCostFromSource())
return new PaymentDecision(source);
Integer c = cost.convertAmount();
if (c == null) {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
List<Card> res = ComputerUtil.chooseReturnType(ai, cost.getType(), source, ability.getTargetCard(), c);
return res.isEmpty() ? null : new PaymentDecision(res);
}
@Override
public PaymentDecision visit(CostReveal cost) {
final String type = cost.getType();
List<Card> hand = new ArrayList<Card>(ai.getCardsIn(ZoneType.Hand));
if (cost.payCostFromSource()) {
if (!hand.contains(source)) {
return null;
}
return new PaymentDecision(source);
}
if (cost.getType().equals("Hand"))
return new PaymentDecision(new ArrayList<Card>(ai.getCardsIn(ZoneType.Hand)));
if (cost.getType().equals("SameColor")) {
return null;
}
hand = CardLists.getValidCards(hand, type.split(";"), ai, source);
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
if (sVar.equals("XChoice")) {
c = hand.size();
} else {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
}
final AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
return new PaymentDecision(aic.getCardsToDiscard(c, type.split(";"), ability));
}
@Override
public PaymentDecision visit(CostRemoveAnyCounter cost) {
final String amount = cost.getAmount();
final int c = AbilityUtils.calculateAmount(source, amount, ability);
final String type = cost.getType();
List<Card> typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), ai, source);
List<Card> hperms = CardLists.filter(typeList, new Predicate<Card>() {
@Override
public boolean apply(final Card crd) {
for (final CounterType c1 : CounterType.values()) {
if (crd.getCounters(c1) >= c && ComputerUtil.isNegativeCounter(c1, crd)) {
return true;
}
}
return false;
}
});
// Only find cards with enough negative counters
// TODO: add ai for Chisei, Heart of Oceans
return hperms.isEmpty() ? null : new PaymentDecision(hperms);
}
@Override
public PaymentDecision visit(CostRemoveCounter cost) {
final String amount = cost.getAmount();
Integer c = cost.convertAmount();
final String type = cost.getType();
if (c == null) {
final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) {
return null;
}
if (amount.equals("All")) {
c = source.getCounters(cost.getCounter());
} else {
c = AbilityUtils.calculateAmount(source, amount, ability);
}
}
if (!cost.payCostFromSource()) {
List<Card> typeList;
if (type.equals("OriginalHost")) {
typeList = Lists.newArrayList(ability.getOriginalHost());
} else {
typeList = CardLists.getValidCards(ai.getCardsIn(cost.getZone()), type.split(";"), ai, source);
}
for (Card card : typeList) {
if (card.getCounters(cost.getCounter()) >= c) {
return new PaymentDecision(card);
}
}
return null;
}
if (c > source.getCounters(cost.getCounter())) {
System.out.println("Not enough " + cost.getCounter() + " on " + source.getName());
return null;
}
PaymentDecision result = new PaymentDecision(source);
result.c = c; // cost.cntRemoved = c;
return result;
}
@Override
public PaymentDecision visit(CostUntapType cost) {
final String amount = cost.getAmount();
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) {
List<Card> typeList = ai.getGame().getCardsIn(ZoneType.Battlefield);
typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), ai, ability.getSourceCard());
if (!cost.canUntapSource) {
typeList.remove(source);
}
typeList = CardLists.filter(typeList, Presets.TAPPED);
c = typeList.size();
source.setSVar("ChosenX", "Number$" + Integer.toString(c));
} else {
c = AbilityUtils.calculateAmount(source, amount, ability);
}
}
List<Card> list = ComputerUtil.chooseUntapType(ai, cost.getType(), source, cost.canUntapSource, c);
if (list == null) {
System.out.println("Couldn't find a valid card to untap for: " + source.getName());
return null;
}
return new PaymentDecision(list);
}
@Override
public PaymentDecision visit(CostUntap cost) {
return new PaymentDecision(0);
}
@Override
public PaymentDecision visit(CostUnattach cost) {
Card cardToUnattach = cost.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);
}
}

View File

@@ -1,8 +0,0 @@
package forge.ai;
import forge.game.cost.PaymentDecision;
import forge.game.cost.ICostVisitor;
public class AiCostPayment extends ICostVisitor.Base<PaymentDecision> {
}

View File

@@ -18,6 +18,7 @@
*/
package forge.ai.ability;
import forge.ai.AiCostDecision;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCost;
import forge.ai.ComputerUtilMana;
@@ -65,10 +66,10 @@ public class DrawAi extends SpellAbilityAi {
}
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
AiCostDecision aiDecisions = new AiCostDecision(ai, sa, source);
for (final CostPart part : abCost.getCostParts()) {
if (part instanceof CostDiscard) {
CostDiscard cd = (CostDiscard) part;
PaymentDecision decision = cd.decideAIPayment(ai, sa, sa.getSourceCard());
PaymentDecision decision = part.accept(aiDecisions);
if ( null == decision )
return false;
for (Card discard : decision.cards) {

View File

@@ -151,24 +151,6 @@ public class CostAddMana extends CostPart {
return true;
}
/*
* (non-Javadoc)
*
* @see
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
* , forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final PaymentDecision decideAIPayment(final Player ai, final SpellAbility ability, final Card source) {
Integer c = this.convertAmount();
if (c == null) {
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
}
return new PaymentDecision(c);
}
@Override
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);

View File

@@ -20,7 +20,6 @@ package forge.game.cost;
import java.util.ArrayList;
import forge.card.CardType;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
@@ -85,28 +84,8 @@ public class CostChooseCreatureType extends CostPart {
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player 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; // cannot pay
} else {
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
}
}
return new PaymentDecision(c);
}
@Override
public boolean payAI(PaymentDecision decision, Player ai,
SpellAbility ability, Card source) {
public boolean payAI(PaymentDecision decision, Player ai, SpellAbility ability, Card source) {
String choice = ai.getController().chooseSomeType("Creature", ability, new ArrayList<String>(CardType.getCreatureTypes()), new ArrayList<String>());
source.setChosenType(choice);
return true;

View File

@@ -98,30 +98,6 @@ public class CostDamage extends CostPart {
return false;
}
/*
* (non-Javadoc)
*
* @see
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
* , forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final PaymentDecision decideAIPayment(final Player 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 null; // cannot pay
} else {
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
}
}
return new PaymentDecision(c);
}
@Override
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);

View File

@@ -21,13 +21,11 @@ import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Predicate;
import forge.ai.AiController;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.player.Player;
import forge.game.player.PlayerControllerAi;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.gui.input.InputSelectCardsFromList;
@@ -257,52 +255,6 @@ public class CostDiscard extends CostPartWithList {
}
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
final String type = this.getType();
final List<Card> hand = ai.getCardsIn(ZoneType.Hand);
if (type.equals("LastDrawn")) {
if (!hand.contains(ai.getLastDrawnCard())) {
return null;
}
return new PaymentDecision(ai.getLastDrawnCard());
}
else if (this.payCostFromSource()) {
if (!hand.contains(source)) {
return null;
}
return new PaymentDecision(source);
}
else if (type.equals("Hand")) {
return new PaymentDecision(hand);
}
if (type.contains("WithSameName")) {
return null;
}
Integer c = this.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(this.getAmount());
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
}
if (type.equals("Random")) {
return new PaymentDecision(CardLists.getRandomSubList(hand, c));
}
else {
final AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
return new PaymentDecision(aic.getCardsToDiscard(c, type.split(";"), ability));
}
}
/* (non-Javadoc)
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
*/

View File

@@ -122,24 +122,6 @@ public class CostDraw extends CostPart {
return true;
}
/*
* (non-Javadoc)
*
* @see
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
* , forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final PaymentDecision decideAIPayment(final Player ai, final SpellAbility ability, final Card source) {
Integer c = this.convertAmount();
if (c == null) {
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
}
return new PaymentDecision(c);
}
@Override
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);

View File

@@ -22,7 +22,6 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import forge.ai.ComputerUtil;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
@@ -51,7 +50,7 @@ public class CostExile extends CostPartWithList {
*/
private ZoneType from = ZoneType.Battlefield;
private boolean sameZone = false;
public final boolean sameZone;
/**
* Gets the from.
@@ -75,14 +74,14 @@ public class CostExile extends CostPartWithList {
* the from
*/
public CostExile(final String amount, final String type, final String description, final ZoneType from) {
this(amount, type, description, from, false);
}
public CostExile(final String amount, final String type, final String description, final ZoneType from, final boolean sameZone) {
super(amount, type, description);
if (from != null) {
this.from = from;
}
}
public CostExile(final String amount, final String type, final String description, final ZoneType from, final boolean sameZone) {
this(amount, type, description, from);
this.sameZone = sameZone;
}
@@ -459,45 +458,6 @@ public class CostExile extends CostPartWithList {
return "Exiled";
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player 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())));
}
else if (this.getType().contains("FromTopGrave")) {
return null;
}
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);
}
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 {
List<Card> chosen = ComputerUtil.chooseExileFrom(ai, this.getFrom(), this.getType(), source, ability.getTargetCard(), c);
return null == chosen ? null : new PaymentDecision(chosen);
}
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/

View File

@@ -3,7 +3,6 @@ package forge.game.cost;
import java.util.ArrayList;
import java.util.List;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCost;
import forge.game.card.Card;
import forge.game.card.CardLists;
@@ -43,51 +42,6 @@ public class CostExileAndPay extends CostPartWithList {
return CardLists.getValidCards(ability.getActivatingPlayer().getZone(ZoneType.Graveyard), "Creature", ability.getActivatingPlayer(), ability.getSourceCard()).size() > 0;
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
List<Card> validGrave = CardLists.getValidCards(ability.getActivatingPlayer().getZone(ZoneType.Graveyard), "Creature", ability.getActivatingPlayer(), ability.getSourceCard());
if(validGrave.size() == 0)
{
return null;
}
Card bestCard = null;
int bestScore = 0;
for(Card candidate : validGrave)
{
boolean selectable = false;
for(SpellAbility sa : candidate.getSpellAbilities())
{
if(sa instanceof SpellPermanent)
{
if(ComputerUtilCost.canPayCost(sa, ai))
{
selectable = true;
}
}
}
if(!selectable)
{
continue;
}
int candidateScore = ComputerUtilCard.evaluateCreature(candidate);
if(candidateScore > bestScore)
{
bestScore = candidateScore;
bestCard = candidate;
}
}
return bestCard == null ? null : new PaymentDecision(bestCard);
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#payHuman(forge.card.spellability.SpellAbility, forge.game.GameState)
*/

View File

@@ -17,8 +17,6 @@
*/
package forge.game.cost;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import forge.game.ability.AbilityUtils;
@@ -155,36 +153,6 @@ public class CostExiledMoveToGrave extends CostPartWithList {
targetCard.getGame().getAction().moveToGraveyard(targetCard);
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
Integer c = this.convertAmount();
List<Card> chosen = new ArrayList<Card>();
if (c == null) {
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
}
List<Card> typeList = ai.getGame().getCardsIn(ZoneType.Exile);
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), ai, source);
if (typeList.size() < c) {
return null;
}
CardLists.sortByPowerAsc(typeList);
Collections.reverse(typeList);
for (int i = 0; i < c; i++) {
chosen.add(typeList.get(i));
}
return chosen.isEmpty() ? null : new PaymentDecision(chosen);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);
}

View File

@@ -106,22 +106,6 @@ public class CostFlipCoin extends CostPartWithList {
FlipCoinEffect.flipCoinCall(activator, ability, i);
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player 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);
}
return new PaymentDecision(c);
}
/*
* (non-Javadoc)
*

View File

@@ -116,39 +116,6 @@ public class CostGainControl extends CostPartWithList {
return true;
}
/*
* (non-Javadoc)
*
* @see
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
* , forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final PaymentDecision decideAIPayment(final Player 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);
}
final List<Card> typeList = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), this.getType().split(";"), ai, source);
if (typeList.size() < c) {
return null;
}
CardLists.sortByPowerAsc(typeList);
final List<Card> res = new ArrayList<Card>();
for (int i = 0; i < c; i++) {
res.add(typeList.get(i));
}
return res.isEmpty() ? null : new PaymentDecision(res);
}
/* (non-Javadoc)
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
*/

View File

@@ -161,39 +161,6 @@ public class CostGainLife extends CostPart {
return true;
}
/*
* (non-Javadoc)
*
* @see
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
* , forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final PaymentDecision decideAIPayment(final Player 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 null;
} else {
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
}
}
final List<Player> oppsThatCanGainLife = new ArrayList<Player>();
for (final Player opp : ai.getOpponents()) {
if (opp.canGainLife()) {
oppsThatCanGainLife.add(opp);
}
}
if (oppsThatCanGainLife.size() == 0) {
return null;
}
return new PaymentDecision(c);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);

View File

@@ -147,26 +147,6 @@ public class CostMill extends CostPartWithList {
targetCard.getGame().getAction().moveToGraveyard(targetCard);
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player 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);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);
}

View File

@@ -149,21 +149,6 @@ public abstract class CostPart {
*/
public abstract boolean canPay(SpellAbility ability);
/**
* Decide ai payment.
*
* @param ai
* {@link forge.player.Player}
* @param ability
* {@link forge.game.spellability.SpellAbility}
* @param source
* {@link forge.game.card.Card}
* @param payment
* {@link forge.game.cost.CostPayment}
* @return true, if successful
*/
public abstract PaymentDecision decideAIPayment(final Player ai, SpellAbility ability, Card source);
public abstract <T> T accept(final ICostVisitor<T> visitor);
public abstract boolean payAI(final PaymentDecision decision, final Player ai, SpellAbility ability, Card source);

View File

@@ -182,15 +182,6 @@ public class CostPartMana extends CostPart {
return ComputerUtilMana.payManaCost(ai, ability);
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
return new PaymentDecision(0);
}
/**
* TODO: Write javadoc for this method.
* @return

View File

@@ -138,28 +138,6 @@ public class CostPayLife extends CostPart {
return false;
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player 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;
} else {
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
}
}
if (!ai.canPayLife(c)) {
return null;
}
// activator.payLife(c, null);
return new PaymentDecision(c);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);
}

View File

@@ -21,6 +21,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import forge.ai.AiCostDecision;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.player.Player;
@@ -178,10 +180,11 @@ public class CostPayment {
final List<CostPart> parts = this.cost.getCostParts();
Map<Class<? extends CostPart>, PaymentDecision> decisions = new HashMap<Class<? extends CostPart>, PaymentDecision>();
AiCostDecision aiDecisions = new AiCostDecision(ai, ability, source);
// Set all of the decisions before attempting to pay anything
for (final CostPart part : parts) {
PaymentDecision decision = part.decideAIPayment(ai, this.ability, source);
PaymentDecision decision = part.accept(aiDecisions);
if ( null == decision ) return false;
decisions.put(part.getClass(), decision);
}

View File

@@ -20,7 +20,6 @@ package forge.game.cost;
import java.util.ArrayList;
import java.util.List;
import forge.ai.ComputerUtil;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
@@ -319,52 +318,7 @@ public class CostPutCardToLib extends CostPartWithList {
targetCard.getGame().getAction().moveToLibrary(targetCard, Integer.parseInt(getLibPos()));
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
Integer c = this.convertAmount();
final Game game = ai.getGame();
List<Card> chosen = new ArrayList<Card>();
List<Card> list;
if (this.sameZone) {
list = new ArrayList<Card>(game.getCardsIn(this.getFrom()));
} else {
list = new ArrayList<Card>(ai.getCardsIn(this.getFrom()));
}
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 = CardLists.getValidCards(list, this.getType().split(";"), ai, source);
if (this.sameZone) {
// Jotun Grunt
// TODO: improve AI
final List<Player> players = game.getPlayers();
for (Player p : players) {
List<Card> enoughType = CardLists.filter(list, CardPredicates.isOwner(p));
if (enoughType.size() >= c) {
chosen.addAll(enoughType);
break;
}
}
chosen = chosen.subList(0, c);
} else {
chosen = ComputerUtil.choosePutToLibraryFrom(ai, this.getFrom(), this.getType(), source, ability.getTargetCard(), c);
}
return chosen.isEmpty() ? null : new PaymentDecision(chosen);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);
}

View File

@@ -18,7 +18,6 @@
package forge.game.cost;
import java.util.List;
import forge.ai.ComputerUtilCard;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
@@ -236,28 +235,6 @@ public class CostPutCounter extends CostPartWithList {
return "CounterPut";
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
if (this.payCostFromSource()) {
return new PaymentDecision(source);
}
final List<Card> typeList = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), this.getType().split(";"), ai, source);
Card card = null;
if (this.getType().equals("Creature.YouCtrl")) {
card = ComputerUtilCard.getWorstCreatureAI(typeList);
} else {
card = ComputerUtilCard.getWorstPermanentAI(typeList, false, false, false, false);
}
return new PaymentDecision(card);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);
}

View File

@@ -197,34 +197,6 @@ public class CostRemoveAnyCounter extends CostPartWithList {
targetCard.subtractCounter(this.getCounter(), 1);
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
final String amount = this.getAmount();
final int c = AbilityUtils.calculateAmount(source, amount, ability);
final String type = this.getType();
List<Card> typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), ai, source);
List<Card> hperms = CardLists.filter(typeList, new Predicate<Card>() {
@Override
public boolean apply(final Card crd) {
for (final CounterType c1 : CounterType.values()) {
if (crd.getCounters(c1) >= c && ComputerUtil.isNegativeCounter(c1, crd)) {
return true;
}
}
return false;
}
});
// Only find cards with enough negative counters
// TODO: add ai for Chisei, Heart of Oceans
return hperms.isEmpty() ? null : new PaymentDecision(hperms);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);
}

View File

@@ -221,7 +221,7 @@ public class CostRemoveCounter extends CostPartWithList {
/**
* @return the zone
*/
private ZoneType getZone() {
public final ZoneType getZone() {
return zone;
}
@@ -375,50 +375,6 @@ public class CostRemoveCounter extends CostPartWithList {
return "CounterRemove";
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
final String amount = this.getAmount();
Integer c = this.convertAmount();
final String type = this.getType();
if (c == null) {
final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) {
return null;
}
if (amount.equals("All")) {
c = source.getCounters(this.counter);
} else {
c = AbilityUtils.calculateAmount(source, amount, ability);
}
}
if (!this.payCostFromSource()) {
List<Card> typeList;
if (type.equals("OriginalHost")) {
typeList = Lists.newArrayList(ability.getOriginalHost());
} else {
typeList = CardLists.getValidCards(ai.getCardsIn(this.getZone()), type.split(";"), ai, source);
}
for (Card card : typeList) {
if (card.getCounters(this.getCounter()) >= c) {
return new PaymentDecision(card);
}
}
return null;
}
if (c > source.getCounters(this.getCounter())) {
System.out.println("Not enough " + this.counter + " on " + source.getName());
return null;
}
this.cntRemoved = c;
return new PaymentDecision(source);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);
}

View File

@@ -20,7 +20,6 @@ package forge.game.cost;
import java.util.ArrayList;
import java.util.List;
import forge.ai.ComputerUtil;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
@@ -154,27 +153,6 @@ public class CostReturn 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 PaymentDecision decideAIPayment(final Player 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);
}
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)
*/

View File

@@ -24,13 +24,11 @@ import java.util.List;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import forge.ai.AiController;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.player.Player;
import forge.game.player.PlayerControllerAi;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.gui.input.InputSelectCardsFromList;
@@ -114,44 +112,6 @@ public class CostReveal extends CostPartWithList {
return true;
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
final String type = this.getType();
List<Card> hand = new ArrayList<Card>(ai.getCardsIn(ZoneType.Hand));
if (this.payCostFromSource()) {
if (!hand.contains(source)) {
return null;
}
return new PaymentDecision(source);
}
if (this.getType().equals("Hand"))
return new PaymentDecision(new ArrayList<Card>(ai.getCardsIn(ZoneType.Hand)));
if (this.getType().equals("SameColor")) {
return null;
}
hand = CardLists.getValidCards(hand, type.split(";"), ai, source);
Integer c = this.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(this.getAmount());
if (sVar.equals("XChoice")) {
c = hand.size();
} else {
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
}
}
final AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
return new PaymentDecision(aic.getCardsToDiscard(c, type.split(";"), ability));
}
/*
* (non-Javadoc)
*

View File

@@ -20,7 +20,6 @@ package forge.game.cost;
import java.util.ArrayList;
import java.util.List;
import forge.ai.ComputerUtil;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
@@ -184,37 +183,6 @@ 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(Player 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
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);

View File

@@ -101,13 +101,6 @@ public class CostTap extends CostPart {
return true;
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
return new PaymentDecision(0);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);

View File

@@ -22,7 +22,6 @@ import java.util.List;
import com.google.common.base.Predicate;
import forge.ai.ComputerUtil;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
@@ -37,7 +36,7 @@ import forge.gui.input.InputSelectCardsFromList;
*/
public class CostTapType extends CostPartWithList {
private final boolean canTapSource;
public final boolean canTapSource;
/**
* Instantiates a new cost tap type.
@@ -263,40 +262,6 @@ public class CostTapType extends CostPartWithList {
return executePayment(ability, inp.getSelected());
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
final String amount = this.getAmount();
Integer c = this.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) {
List<Card> typeList =
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), this.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard());
typeList = CardLists.filter(typeList, Presets.UNTAPPED);
c = typeList.size();
source.setSVar("ChosenX", "Number$" + Integer.toString(c));
} else {
c = AbilityUtils.calculateAmount(source, amount, ability);
}
}
if (this.getType().contains("sharesCreatureTypeWith") || this.getType().contains("withTotalPowerGE")) {
return null;
}
List<Card> totap = ComputerUtil.chooseTapType(ai, this.getType(), source, !canTapSource, c);
if (totap == null) {
System.out.println("Couldn't find a valid card to tap for: " + source.getName());
return null;
}
return new PaymentDecision(totap);
}
/* (non-Javadoc)
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
*/

View File

@@ -104,7 +104,7 @@ public class CostUnattach extends CostPartWithList {
return false;
}
private Card findCardToUnattach(final Card source, Player activator, SpellAbility ability) {
public Card findCardToUnattach(final Card source, Player activator, SpellAbility ability) {
if (getType().equals("CARDNAME")) {
if (source.isEquipping()) {
return source;
@@ -137,19 +137,7 @@ public class CostUnattach extends CostPartWithList {
return "Unattached";
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player 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);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);
}

View File

@@ -92,14 +92,6 @@ public class CostUntap extends CostPart {
return true;
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player 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)
*/

View File

@@ -18,7 +18,6 @@
package forge.game.cost;
import java.util.List;
import forge.ai.ComputerUtil;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
@@ -33,7 +32,7 @@ import forge.gui.input.InputSelectCardsFromList;
*/
public class CostUntapType extends CostPartWithList {
private final boolean canUntapSource;
public final boolean canUntapSource;
/**
* Instantiates a new cost untap type.
@@ -173,39 +172,6 @@ public class CostUntapType extends CostPartWithList {
return "Untapped";
}
/* (non-Javadoc)
* @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
*/
@Override
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
final String amount = this.getAmount();
Integer c = this.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) {
List<Card> typeList = ai.getGame().getCardsIn(ZoneType.Battlefield);
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), ai, ability.getSourceCard());
if (!canUntapSource) {
typeList.remove(source);
}
typeList = CardLists.filter(typeList, Presets.TAPPED);
c = typeList.size();
source.setSVar("ChosenX", "Number$" + Integer.toString(c));
} else {
c = AbilityUtils.calculateAmount(source, amount, ability);
}
}
List<Card> list = ComputerUtil.chooseUntapType(ai, this.getType(), source, canUntapSource, c);
if (list == null) {
System.out.println("Couldn't find a valid card to untap for: " + source.getName());
return null;
}
return new PaymentDecision(list);
}
public <T> T accept(ICostVisitor<T> visitor) {
return visitor.visit(this);
}

View File

@@ -2,162 +2,162 @@ package forge.game.cost;
public interface ICostVisitor<T> {
public T visit(CostGainControl costGainControl);
public T visit(CostChooseCreatureType costChooseCreatureType);
public T visit(CostDiscard costDiscard);
public T visit(CostDamage costDamage);
public T visit(CostDraw costDraw);
public T visit(CostExile costExile);
public T visit(CostExileAndPay costExileAndPay);
public T visit(CostExiledMoveToGrave costExiledMoveToGrave);
public T visit(CostFlipCoin costFlipCoin);
public T visit(CostMill costMill);
public T visit(CostAddMana costAddMana);
public T visit(CostPayLife costPayLife);
public T visit(CostGainLife costGainLife);
public T visit(CostPartMana costPartMana);
public T visit(CostPutCardToLib costPutCardToLib);
public T visit(CostTap costTap);
public T visit(CostSacrifice costSacrifice);
public T visit(CostReturn costReturn);
public T visit(CostReveal costReveal);
public T visit(CostRemoveAnyCounter costRemoveAnyCounter);
public T visit(CostRemoveCounter costRemoveCounter);
public T visit(CostPutCounter costPutCounter);
public T visit(CostUntapType costUntapType);
public T visit(CostUntap costUntap);
public T visit(CostUnattach costUnattach);
public T visit(CostTapType costTapType);
public T visit(CostGainControl cost);
public T visit(CostChooseCreatureType cost);
public T visit(CostDiscard cost);
public T visit(CostDamage cost);
public T visit(CostDraw cost);
public T visit(CostExile cost);
public T visit(CostExileAndPay cost);
public T visit(CostExiledMoveToGrave cost);
public T visit(CostFlipCoin cost);
public T visit(CostMill cost);
public T visit(CostAddMana cost);
public T visit(CostPayLife cost);
public T visit(CostGainLife cost);
public T visit(CostPartMana cost);
public T visit(CostPutCardToLib cost);
public T visit(CostTap cost);
public T visit(CostSacrifice cost);
public T visit(CostReturn cost);
public T visit(CostReveal cost);
public T visit(CostRemoveAnyCounter cost);
public T visit(CostRemoveCounter cost);
public T visit(CostPutCounter cost);
public T visit(CostUntapType cost);
public T visit(CostUntap cost);
public T visit(CostUnattach cost);
public T visit(CostTapType cost);
public static class Base<T> implements ICostVisitor<T> {
@Override
public T visit(CostGainControl costGainControl) {
public T visit(CostGainControl cost) {
return null;
}
@Override
public T visit(CostChooseCreatureType costChooseCreatureType) {
public T visit(CostChooseCreatureType cost) {
return null;
}
@Override
public T visit(CostDiscard costDiscard) {
public T visit(CostDiscard cost) {
return null;
}
@Override
public T visit(CostDamage costDamage) {
public T visit(CostDamage cost) {
return null;
}
@Override
public T visit(CostDraw costDraw) {
public T visit(CostDraw cost) {
return null;
}
@Override
public T visit(CostExile costExile) {
public T visit(CostExile cost) {
return null;
}
@Override
public T visit(CostExileAndPay costExileAndPay) {
public T visit(CostExileAndPay cost) {
return null;
}
@Override
public T visit(CostExiledMoveToGrave costExiledMoveToGrave) {
public T visit(CostExiledMoveToGrave cost) {
return null;
}
@Override
public T visit(CostFlipCoin costFlipCoin) {
public T visit(CostFlipCoin cost) {
return null;
}
@Override
public T visit(CostMill costMill) {
public T visit(CostMill cost) {
return null;
}
@Override
public T visit(CostAddMana costAddMana) {
public T visit(CostAddMana cost) {
return null;
}
@Override
public T visit(CostPayLife costPayLife) {
public T visit(CostPayLife cost) {
return null;
}
@Override
public T visit(CostGainLife costGainLife) {
public T visit(CostGainLife cost) {
return null;
}
@Override
public T visit(CostPartMana costPartMana) {
public T visit(CostPartMana cost) {
return null;
}
@Override
public T visit(CostPutCardToLib costPutCardToLib) {
public T visit(CostPutCardToLib cost) {
return null;
}
@Override
public T visit(CostTap costTap) {
public T visit(CostTap cost) {
return null;
}
@Override
public T visit(CostSacrifice costSacrifice) {
public T visit(CostSacrifice cost) {
return null;
}
@Override
public T visit(CostReturn costReturn) {
public T visit(CostReturn cost) {
return null;
}
@Override
public T visit(CostReveal costReveal) {
public T visit(CostReveal cost) {
return null;
}
@Override
public T visit(CostRemoveAnyCounter costRemoveAnyCounter) {
public T visit(CostRemoveAnyCounter cost) {
return null;
}
@Override
public T visit(CostRemoveCounter costRemoveCounter) {
public T visit(CostRemoveCounter cost) {
return null;
}
@Override
public T visit(CostPutCounter costPutCounter) {
public T visit(CostPutCounter cost) {
return null;
}
@Override
public T visit(CostUntapType costUntapType) {
public T visit(CostUntapType cost) {
return null;
}
@Override
public T visit(CostUntap costUntap) {
public T visit(CostUntap cost) {
return null;
}
@Override
public T visit(CostUnattach costUnattach) {
public T visit(CostUnattach cost) {
return null;
}
@Override
public T visit(CostTapType costTapType) {
public T visit(CostTapType cost) {
return null;
}
}

View File

@@ -9,8 +9,6 @@ import java.util.Map.Entry;
import java.util.Random;
import javax.swing.JList;
import javax.swing.JOptionPane;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;