mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
ai cost decisions now use visitors
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -14703,7 +14703,7 @@ forge-gui/src/main/java/forge/Singletons.java svneol=native#text/plain
|
||||
forge-gui/src/main/java/forge/ai/AiAttackController.java svneol=native#text/plain
|
||||
forge-gui/src/main/java/forge/ai/AiBlockController.java svneol=native#text/plain
|
||||
forge-gui/src/main/java/forge/ai/AiController.java svneol=native#text/plain
|
||||
forge-gui/src/main/java/forge/ai/AiCostPayment.java -text
|
||||
forge-gui/src/main/java/forge/ai/AiCostDecision.java -text
|
||||
forge-gui/src/main/java/forge/ai/AiProfileUtil.java -text
|
||||
forge-gui/src/main/java/forge/ai/ComputerUtil.java svneol=native#text/plain
|
||||
forge-gui/src/main/java/forge/ai/ComputerUtilCard.java -text
|
||||
|
||||
666
forge-gui/src/main/java/forge/ai/AiCostDecision.java
Normal file
666
forge-gui/src/main/java/forge/ai/AiCostDecision.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package forge.ai;
|
||||
|
||||
import forge.game.cost.PaymentDecision;
|
||||
import forge.game.cost.ICostVisitor;
|
||||
|
||||
public class AiCostPayment extends ICostVisitor.Base<PaymentDecision> {
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
*
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,51 +318,6 @@ 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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -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,18 +137,6 @@ 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);
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user