/* * (non-Javadoc) * * @see * forge.card.cost.CostPart#canPay(forge.card.spellability.SpellAbility, * forge.Card, forge.Player, forge.card.cost.Cost) */ @Override public final boolean canPay(final SpellAbility ability) { final Player activator = ability.getActivatingPlayer(); final Card source = ability.getHostCard(); CardCollectionView validCards = activator.getCardsIn(ZoneType.Battlefield); validCards = CardLists.getValidCards(validCards, this.getType().split(";"), activator, source); validCards = CardLists.filter( validCards, new Predicate<Card>() { @Override public boolean apply(final Card c) { return c.hasCounters(); } }); if (validCards.isEmpty()) { return false; } Integer i = this.convertAmount(); if (i == null) { i = AbilityUtils.calculateAmount(source, this.getAmount(), ability); } int allCounters = 0; for (Card c : validCards) { final Map<CounterType, Integer> tgtCounters = c.getCounters(); for (Integer value : tgtCounters.values()) { allCounters += value; } } return i <= allCounters; }
@Override public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> choices) { Player chosen = null; if ("Curse".equals(sa.getParam("AILogic"))) { for (Player pc : choices) { if (pc.isOpponentOf(ai)) { chosen = pc; break; } } if (chosen == null) { chosen = Iterables.getFirst(choices, null); System.out.println("No good curse choices. Picking first available: " + chosen); } } else if ("Pump".equals(sa.getParam("AILogic"))) { chosen = Iterables.contains(choices, ai) ? ai : Iterables.getFirst(choices, null); } else if ("BestAllyBoardPosition".equals(sa.getParam("AILogic"))) { List<Player> prefChoices = Lists.newArrayList(choices); prefChoices.removeAll(ai.getOpponents()); if (!prefChoices.isEmpty()) { chosen = ComputerUtil.evaluateBoardPosition(prefChoices); } if (chosen == null) { chosen = Iterables.getFirst(choices, null); System.out.println("No good curse choices. Picking first available: " + chosen); } } else if ("MostCardsInHand".equals(sa.getParam("AILogic"))) { int cardsInHand = 0; for (final Player p : choices) { int hand = p.getCardsIn(ZoneType.Hand).size(); if (hand >= cardsInHand) { chosen = p; cardsInHand = hand; } } } else if ("LeastCreatures".equals(sa.getParam("AILogic"))) { int creats = 50; for (final Player p : choices) { int curr = p.getCreaturesInPlay().size(); if (curr <= creats) { chosen = p; creats = curr; } } } else { System.out.println("Default player choice logic."); chosen = Iterables.contains(choices, ai) ? ai : Iterables.getFirst(choices, null); } return chosen; }
/* (non-Javadoc) * @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, forge.card.spellability.SpellAbility) */ @Override protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) { String logic = sa.getParam("AILogic"); Game game = aiPlayer.getGame(); if ("ZeroToughness".equals(logic)) { // If Creature has Zero Toughness, make sure some static ability is in play // That will grant a toughness bonus final List<Card> list = aiPlayer.getCardsIn(ZoneType.Battlefield); if (!Iterables.any( list, Predicates.or( CardPredicates.nameEquals("Glorious Anthem"), CardPredicates.nameEquals("Gaea's Anthem")))) { return false; } // TODO See if card ETB will survive after Static Effects /* List<Card> cards = game.getCardsIn(ZoneType.Battlefield); for(Card c : cards) { ArrayList<StaticAbility> statics = c.getStaticAbilities(); for(StaticAbility s : statics) { final Map<String, String> stabMap = s.parseParams(); if (!stabMap.get("Mode").equals("Continuous")) { continue; } final String affected = stabMap.get("Affected"); if (affected == null) { continue; } } } */ } // Wait for Main2 if possible if (game.getPhaseHandler().is(PhaseType.MAIN1) && !ComputerUtil.castPermanentInMain1(aiPlayer, sa)) { return false; } // AI shouldn't be retricted all that much for Creatures for now return true; }
/* * (non-Javadoc) * * @see * forge.card.cost.CostPart#canPay(forge.card.spellability.SpellAbility, * forge.Card, forge.Player, forge.card.cost.Cost) */ @Override public final boolean canPay(final SpellAbility ability) { final Player activator = ability.getActivatingPlayer(); final Card source = ability.getHostCard(); if (!this.payCostFromSource()) { boolean needsAnnoucement = ability.hasParam("Announce") && this.getType().contains(ability.getParam("Announce")); CardCollectionView typeList = activator.getCardsIn(ZoneType.Battlefield); typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source); final Integer amount = this.convertAmount(); if (!needsAnnoucement && amount != null && typeList.size() < amount) { return false; } } else if (!source.isInPlay()) { return false; } return true; }
boolean pumpAgainstRemoval(Player ai, SpellAbility sa) { final List<GameObject> objects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa); final List<Card> threatenedTargets = new ArrayList<Card>(); final TargetRestrictions tgt = sa.getTargetRestrictions(); if (tgt == null) { // For pumps without targeting restrictions, just return immediately until this is fleshed // out. return false; } List<Card> targetables = CardLists.getValidCards( ai.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, sa.getHostCard()); targetables = CardLists.getTargetableCards(targetables, sa); targetables = ComputerUtil.getSafeTargets(ai, sa, targetables); for (final Card c : targetables) { if (objects.contains(c)) { threatenedTargets.add(c); } } if (!threatenedTargets.isEmpty()) { ComputerUtilCard.sortByEvaluateCreature(threatenedTargets); for (Card c : threatenedTargets) { sa.getTargets().add(c); if (sa.getTargets().getNumTargeted() >= tgt.getMaxTargets(sa.getHostCard(), sa)) { break; } } if (sa.getTargets().getNumTargeted() > tgt.getMaxTargets(sa.getHostCard(), sa) || sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) { sa.resetTargets(); return false; } return true; } return false; }
protected boolean revealHandTargetAI(final Player ai, final SpellAbility sa) { final TargetRestrictions tgt = sa.getTargetRestrictions(); Player opp = ai.getOpponent(); final int humanHandSize = opp.getCardsIn(ZoneType.Hand).size(); if (tgt != null) { // ability is targeted sa.resetTargets(); final boolean canTgtHuman = opp.canBeTargetedBy(sa); if (!canTgtHuman || (humanHandSize == 0)) { return false; } else { sa.getTargets().add(opp); } } else { // if it's just defined, no big deal } return true; } // revealHandTargetAI()
/* (non-Javadoc) * @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility) */ @Override protected boolean canPlayAI(Player ai, final SpellAbility sa) { Card object1 = null; Card object2 = null; final Card source = sa.getHostCard(); final String type = sa.getParam("Type"); if (sa.hasParam("Object")) { object1 = AbilityUtils.getDefinedCards(source, sa.getParam("Object"), sa).get(0); } else { object1 = source; } final ZoneType zone1 = sa.hasParam("Zone1") ? ZoneType.smartValueOf(sa.getParam("Zone1")) : ZoneType.Battlefield; final ZoneType zone2 = sa.hasParam("Zone2") ? ZoneType.smartValueOf(sa.getParam("Zone2")) : ZoneType.Hand; CardCollection list = new CardCollection(ai.getCardsIn(zone2)); if (type != null) { list = CardLists.getValidCards(list, type, ai, source); } object2 = ComputerUtilCard.getBestAI(list); if (object1 == null || object2 == null || !object1.isInZone(zone1) || !object1.getOwner().equals(ai)) { return false; } if (type.equals("Aura")) { Card c = object1.getEnchantingCard(); if (!c.canBeEnchantedBy(object2)) { return false; } } if (object2.getCMC() > object1.getCMC()) { return MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); } return false; }
private boolean sacrificeTgtAI(final Player ai, final SpellAbility sa) { final Card source = sa.getHostCard(); final TargetRestrictions tgt = sa.getTargetRestrictions(); final boolean destroy = sa.hasParam("Destroy"); Player opp = ai.getOpponent(); if (tgt != null) { sa.resetTargets(); if (!opp.canBeTargetedBy(sa)) { return false; } sa.getTargets().add(opp); final String valid = sa.getParam("SacValid"); String num = sa.getParam("Amount"); num = (num == null) ? "1" : num; final int amount = AbilityUtils.calculateAmount(sa.getHostCard(), num, sa); List<Card> list = CardLists.getValidCards( ai.getOpponent().getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getHostCard()); for (Card c : list) { if (c.hasSVar("SacMe") && Integer.parseInt(c.getSVar("SacMe")) > 3) { return false; } } if (!destroy) { list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(sa)); } else { if (!CardLists.getKeyword(list, "Indestructible").isEmpty()) { // human can choose to destroy indestructibles return false; } } if (list.isEmpty()) { return false; } if (num.equals("X") && source.getSVar(num).equals("Count$xPaid")) { // Set PayX here to maximum value. final int xPay = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), amount); source.setSVar("PayX", Integer.toString(xPay)); } final int half = (amount / 2) + (amount % 2); // Half of amount // rounded up // If the Human has at least half rounded up of the amount to be // sacrificed, cast the spell if (!sa.isTrigger() && list.size() < half) { return false; } } final String defined = sa.getParam("Defined"); final String valid = sa.getParam("SacValid"); if (defined == null) { // Self Sacrifice. } else if (defined.equals("Each") || (defined.equals("Opponent") && !sa.isTrigger())) { // If Sacrifice hits both players: // Only cast it if Human has the full amount of valid // Only cast it if AI doesn't have the full amount of Valid // TODO: Cast if the type is favorable: my "worst" valid is // worse than his "worst" valid final String num = sa.hasParam("Amount") ? sa.getParam("Amount") : "1"; int amount = AbilityUtils.calculateAmount(source, num, sa); if (num.equals("X") && source.getSVar(num).equals("Count$xPaid")) { // Set PayX here to maximum value. amount = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), amount); } List<Card> humanList = CardLists.getValidCards( opp.getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getHostCard()); // Since all of the cards have remAIDeck:True, I enabled 1 for 1 // (or X for X) trades for special decks if (humanList.size() < amount) { return false; } } else if (defined.equals("You")) { List<Card> computerList = CardLists.getValidCards( ai.getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getHostCard()); for (Card c : computerList) { if (c.hasSVar("SacMe") || ComputerUtilCard.evaluateCreature(c) <= 135) { return true; } } return false; } return true; }