mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +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/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/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/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/AiProfileUtil.java -text
|
||||||
forge-gui/src/main/java/forge/ai/ComputerUtil.java svneol=native#text/plain
|
forge-gui/src/main/java/forge/ai/ComputerUtil.java svneol=native#text/plain
|
||||||
forge-gui/src/main/java/forge/ai/ComputerUtilCard.java -text
|
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;
|
package forge.ai.ability;
|
||||||
|
|
||||||
|
import forge.ai.AiCostDecision;
|
||||||
import forge.ai.ComputerUtil;
|
import forge.ai.ComputerUtil;
|
||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
@@ -65,10 +66,10 @@ public class DrawAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
||||||
|
AiCostDecision aiDecisions = new AiCostDecision(ai, sa, source);
|
||||||
for (final CostPart part : abCost.getCostParts()) {
|
for (final CostPart part : abCost.getCostParts()) {
|
||||||
if (part instanceof CostDiscard) {
|
if (part instanceof CostDiscard) {
|
||||||
CostDiscard cd = (CostDiscard) part;
|
PaymentDecision decision = part.accept(aiDecisions);
|
||||||
PaymentDecision decision = cd.decideAIPayment(ai, sa, sa.getSourceCard());
|
|
||||||
if ( null == decision )
|
if ( null == decision )
|
||||||
return false;
|
return false;
|
||||||
for (Card discard : decision.cards) {
|
for (Card discard : decision.cards) {
|
||||||
|
|||||||
@@ -151,24 +151,6 @@ public class CostAddMana extends CostPart {
|
|||||||
return true;
|
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
|
@Override
|
||||||
public <T> T accept(ICostVisitor<T> visitor) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package forge.game.cost;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.game.ability.AbilityUtils;
|
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
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
|
@Override
|
||||||
public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) {
|
public boolean payAI(PaymentDecision decision, 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) {
|
|
||||||
String choice = ai.getController().chooseSomeType("Creature", ability, new ArrayList<String>(CardType.getCreatureTypes()), new ArrayList<String>());
|
String choice = ai.getController().chooseSomeType("Creature", ability, new ArrayList<String>(CardType.getCreatureTypes()), new ArrayList<String>());
|
||||||
source.setChosenType(choice);
|
source.setChosenType(choice);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -98,30 +98,6 @@ public class CostDamage extends CostPart {
|
|||||||
return false;
|
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
|
@Override
|
||||||
public <T> T accept(ICostVisitor<T> visitor) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
|
|||||||
@@ -21,13 +21,11 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
import forge.ai.AiController;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerControllerAi;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.input.InputSelectCardsFromList;
|
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)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -122,24 +122,6 @@ public class CostDraw extends CostPart {
|
|||||||
return true;
|
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
|
@Override
|
||||||
public <T> T accept(ICostVisitor<T> visitor) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import java.util.Collections;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -51,7 +50,7 @@ public class CostExile extends CostPartWithList {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private ZoneType from = ZoneType.Battlefield;
|
private ZoneType from = ZoneType.Battlefield;
|
||||||
private boolean sameZone = false;
|
public final boolean sameZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the from.
|
* Gets the from.
|
||||||
@@ -75,14 +74,14 @@ public class CostExile extends CostPartWithList {
|
|||||||
* the from
|
* the from
|
||||||
*/
|
*/
|
||||||
public CostExile(final String amount, final String type, final String description, final ZoneType 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);
|
super(amount, type, description);
|
||||||
if (from != null) {
|
if (from != null) {
|
||||||
this.from = from;
|
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;
|
this.sameZone = sameZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,45 +458,6 @@ public class CostExile extends CostPartWithList {
|
|||||||
return "Exiled";
|
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)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
* @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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import forge.ai.ComputerUtilCard;
|
|
||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
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;
|
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)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.cost.CostPart#payHuman(forge.card.spellability.SpellAbility, forge.game.GameState)
|
* @see forge.card.cost.CostPart#payHuman(forge.card.spellability.SpellAbility, forge.game.GameState)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.cost;
|
package forge.game.cost;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
@@ -155,36 +153,6 @@ public class CostExiledMoveToGrave extends CostPartWithList {
|
|||||||
targetCard.getGame().getAction().moveToGraveyard(targetCard);
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,22 +106,6 @@ public class CostFlipCoin extends CostPartWithList {
|
|||||||
FlipCoinEffect.flipCoinCall(activator, ability, i);
|
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)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -116,39 +116,6 @@ public class CostGainControl extends CostPartWithList {
|
|||||||
return true;
|
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)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -161,39 +161,6 @@ public class CostGainLife extends CostPart {
|
|||||||
return true;
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
|
|||||||
@@ -147,26 +147,6 @@ public class CostMill extends CostPartWithList {
|
|||||||
targetCard.getGame().getAction().moveToGraveyard(targetCard);
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,21 +149,6 @@ public abstract class CostPart {
|
|||||||
*/
|
*/
|
||||||
public abstract boolean canPay(SpellAbility ability);
|
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 <T> T accept(final ICostVisitor<T> visitor);
|
||||||
|
|
||||||
public abstract boolean payAI(final PaymentDecision decision, final Player ai, SpellAbility ability, Card source);
|
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);
|
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.
|
* TODO: Write javadoc for this method.
|
||||||
* @return
|
* @return
|
||||||
|
|||||||
@@ -138,28 +138,6 @@ public class CostPayLife extends CostPart {
|
|||||||
return false;
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import forge.ai.AiCostDecision;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -178,10 +180,11 @@ public class CostPayment {
|
|||||||
final List<CostPart> parts = this.cost.getCostParts();
|
final List<CostPart> parts = this.cost.getCostParts();
|
||||||
|
|
||||||
Map<Class<? extends CostPart>, PaymentDecision> decisions = new HashMap<Class<? extends CostPart>, PaymentDecision>();
|
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
|
// Set all of the decisions before attempting to pay anything
|
||||||
for (final CostPart part : parts) {
|
for (final CostPart part : parts) {
|
||||||
PaymentDecision decision = part.decideAIPayment(ai, this.ability, source);
|
PaymentDecision decision = part.accept(aiDecisions);
|
||||||
if ( null == decision ) return false;
|
if ( null == decision ) return false;
|
||||||
decisions.put(part.getClass(), decision);
|
decisions.put(part.getClass(), decision);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package forge.game.cost;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -319,51 +318,6 @@ public class CostPutCardToLib extends CostPartWithList {
|
|||||||
targetCard.getGame().getAction().moveToLibrary(targetCard, Integer.parseInt(getLibPos()));
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package forge.game.cost;
|
package forge.game.cost;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import forge.ai.ComputerUtilCard;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
@@ -236,28 +235,6 @@ public class CostPutCounter extends CostPartWithList {
|
|||||||
return "CounterPut";
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,34 +197,6 @@ public class CostRemoveAnyCounter extends CostPartWithList {
|
|||||||
targetCard.subtractCounter(this.getCounter(), 1);
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ public class CostRemoveCounter extends CostPartWithList {
|
|||||||
/**
|
/**
|
||||||
* @return the zone
|
* @return the zone
|
||||||
*/
|
*/
|
||||||
private ZoneType getZone() {
|
public final ZoneType getZone() {
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,50 +375,6 @@ public class CostRemoveCounter extends CostPartWithList {
|
|||||||
return "CounterRemove";
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package forge.game.cost;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
@@ -154,27 +153,6 @@ public class CostReturn extends CostPartWithList {
|
|||||||
return false;
|
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)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
* @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.base.Predicate;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.ai.AiController;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerControllerAi;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.input.InputSelectCardsFromList;
|
import forge.gui.input.InputSelectCardsFromList;
|
||||||
@@ -114,44 +112,6 @@ public class CostReveal extends CostPartWithList {
|
|||||||
return true;
|
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)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package forge.game.cost;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
@@ -184,37 +183,6 @@ public class CostSacrifice extends CostPartWithList {
|
|||||||
return "Sacrificed";
|
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
|
// Inputs
|
||||||
public <T> T accept(ICostVisitor<T> visitor) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
|
|||||||
@@ -101,13 +101,6 @@ public class CostTap extends CostPart {
|
|||||||
return true;
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
@@ -37,7 +36,7 @@ import forge.gui.input.InputSelectCardsFromList;
|
|||||||
*/
|
*/
|
||||||
public class CostTapType extends CostPartWithList {
|
public class CostTapType extends CostPartWithList {
|
||||||
|
|
||||||
private final boolean canTapSource;
|
public final boolean canTapSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new cost tap type.
|
* Instantiates a new cost tap type.
|
||||||
@@ -263,40 +262,6 @@ public class CostTapType extends CostPartWithList {
|
|||||||
return executePayment(ability, inp.getSelected());
|
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)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
* @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class CostUnattach extends CostPartWithList {
|
|||||||
return false;
|
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 (getType().equals("CARDNAME")) {
|
||||||
if (source.isEquipping()) {
|
if (source.isEquipping()) {
|
||||||
return source;
|
return source;
|
||||||
@@ -137,18 +137,6 @@ public class CostUnattach extends CostPartWithList {
|
|||||||
return "Unattached";
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
|
|||||||
@@ -92,14 +92,6 @@ public class CostUntap extends CostPart {
|
|||||||
return true;
|
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)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card)
|
* @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;
|
package forge.game.cost;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
@@ -33,7 +32,7 @@ import forge.gui.input.InputSelectCardsFromList;
|
|||||||
*/
|
*/
|
||||||
public class CostUntapType extends CostPartWithList {
|
public class CostUntapType extends CostPartWithList {
|
||||||
|
|
||||||
private final boolean canUntapSource;
|
public final boolean canUntapSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new cost untap type.
|
* Instantiates a new cost untap type.
|
||||||
@@ -173,39 +172,6 @@ public class CostUntapType extends CostPartWithList {
|
|||||||
return "Untapped";
|
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) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,162 +2,162 @@ package forge.game.cost;
|
|||||||
|
|
||||||
public interface ICostVisitor<T> {
|
public interface ICostVisitor<T> {
|
||||||
|
|
||||||
public T visit(CostGainControl costGainControl);
|
public T visit(CostGainControl cost);
|
||||||
public T visit(CostChooseCreatureType costChooseCreatureType);
|
public T visit(CostChooseCreatureType cost);
|
||||||
public T visit(CostDiscard costDiscard);
|
public T visit(CostDiscard cost);
|
||||||
public T visit(CostDamage costDamage);
|
public T visit(CostDamage cost);
|
||||||
public T visit(CostDraw costDraw);
|
public T visit(CostDraw cost);
|
||||||
public T visit(CostExile costExile);
|
public T visit(CostExile cost);
|
||||||
public T visit(CostExileAndPay costExileAndPay);
|
public T visit(CostExileAndPay cost);
|
||||||
public T visit(CostExiledMoveToGrave costExiledMoveToGrave);
|
public T visit(CostExiledMoveToGrave cost);
|
||||||
public T visit(CostFlipCoin costFlipCoin);
|
public T visit(CostFlipCoin cost);
|
||||||
public T visit(CostMill costMill);
|
public T visit(CostMill cost);
|
||||||
public T visit(CostAddMana costAddMana);
|
public T visit(CostAddMana cost);
|
||||||
public T visit(CostPayLife costPayLife);
|
public T visit(CostPayLife cost);
|
||||||
public T visit(CostGainLife costGainLife);
|
public T visit(CostGainLife cost);
|
||||||
public T visit(CostPartMana costPartMana);
|
public T visit(CostPartMana cost);
|
||||||
public T visit(CostPutCardToLib costPutCardToLib);
|
public T visit(CostPutCardToLib cost);
|
||||||
public T visit(CostTap costTap);
|
public T visit(CostTap cost);
|
||||||
public T visit(CostSacrifice costSacrifice);
|
public T visit(CostSacrifice cost);
|
||||||
public T visit(CostReturn costReturn);
|
public T visit(CostReturn cost);
|
||||||
public T visit(CostReveal costReveal);
|
public T visit(CostReveal cost);
|
||||||
public T visit(CostRemoveAnyCounter costRemoveAnyCounter);
|
public T visit(CostRemoveAnyCounter cost);
|
||||||
public T visit(CostRemoveCounter costRemoveCounter);
|
public T visit(CostRemoveCounter cost);
|
||||||
public T visit(CostPutCounter costPutCounter);
|
public T visit(CostPutCounter cost);
|
||||||
public T visit(CostUntapType costUntapType);
|
public T visit(CostUntapType cost);
|
||||||
public T visit(CostUntap costUntap);
|
public T visit(CostUntap cost);
|
||||||
public T visit(CostUnattach costUnattach);
|
public T visit(CostUnattach cost);
|
||||||
public T visit(CostTapType costTapType);
|
public T visit(CostTapType cost);
|
||||||
|
|
||||||
public static class Base<T> implements ICostVisitor<T> {
|
public static class Base<T> implements ICostVisitor<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostGainControl costGainControl) {
|
public T visit(CostGainControl cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostChooseCreatureType costChooseCreatureType) {
|
public T visit(CostChooseCreatureType cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostDiscard costDiscard) {
|
public T visit(CostDiscard cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostDamage costDamage) {
|
public T visit(CostDamage cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostDraw costDraw) {
|
public T visit(CostDraw cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostExile costExile) {
|
public T visit(CostExile cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostExileAndPay costExileAndPay) {
|
public T visit(CostExileAndPay cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostExiledMoveToGrave costExiledMoveToGrave) {
|
public T visit(CostExiledMoveToGrave cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostFlipCoin costFlipCoin) {
|
public T visit(CostFlipCoin cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostMill costMill) {
|
public T visit(CostMill cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostAddMana costAddMana) {
|
public T visit(CostAddMana cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostPayLife costPayLife) {
|
public T visit(CostPayLife cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostGainLife costGainLife) {
|
public T visit(CostGainLife cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostPartMana costPartMana) {
|
public T visit(CostPartMana cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostPutCardToLib costPutCardToLib) {
|
public T visit(CostPutCardToLib cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostTap costTap) {
|
public T visit(CostTap cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostSacrifice costSacrifice) {
|
public T visit(CostSacrifice cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostReturn costReturn) {
|
public T visit(CostReturn cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostReveal costReveal) {
|
public T visit(CostReveal cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostRemoveAnyCounter costRemoveAnyCounter) {
|
public T visit(CostRemoveAnyCounter cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostRemoveCounter costRemoveCounter) {
|
public T visit(CostRemoveCounter cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostPutCounter costPutCounter) {
|
public T visit(CostPutCounter cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostUntapType costUntapType) {
|
public T visit(CostUntapType cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostUntap costUntap) {
|
public T visit(CostUntap cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostUnattach costUnattach) {
|
public T visit(CostUnattach cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(CostTapType costTapType) {
|
public T visit(CostTapType cost) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import java.util.Map.Entry;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.JOptionPane;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user