From 76bc152f0d36b23afe7593c6266b70f20c84a5d1 Mon Sep 17 00:00:00 2001 From: jendave Date: Sun, 7 Aug 2011 00:44:16 +0000 Subject: [PATCH] - Fixes, Updates and Ordering in CombatUtil and ComputerUtil. --- src/forge/CombatUtil.java | 90 +++++------- src/forge/ComputerUtil.java | 273 ++++-------------------------------- 2 files changed, 62 insertions(+), 301 deletions(-) diff --git a/src/forge/CombatUtil.java b/src/forge/CombatUtil.java index b770eb48afc..1108759dc6d 100644 --- a/src/forge/CombatUtil.java +++ b/src/forge/CombatUtil.java @@ -2,8 +2,6 @@ package forge; -import static forge.error.ErrorViewer.showError; - import java.util.ArrayList; import java.util.HashMap; import java.util.regex.Matcher; @@ -14,7 +12,6 @@ import com.esotericsoftware.minlog.Log; import forge.card.abilityFactory.AbilityFactory; import forge.card.cardFactory.CardFactoryUtil; import forge.card.spellability.Ability; -import forge.card.spellability.SpellAbility; import forge.card.trigger.Trigger; import forge.gui.GuiUtils; import forge.gui.input.Input_PayManaCost_Ability; @@ -904,7 +901,7 @@ public class CombatUtil { String ability = source.getSVar(trigParams.get("Execute")); AbilityFactory AF = new AbilityFactory(); HashMap abilityParams = AF.getMapParams(ability, source); - if (abilityParams.containsKey("AB")) { + if (abilityParams.containsKey("AB")) { if (abilityParams.get("AB").equals("Pump")) if (!abilityParams.containsKey("ValidTgts") && !abilityParams.containsKey("Tgt")) if (AbilityFactory.getDefinedCards(source, abilityParams.get("Defined"), null).contains(defender)) @@ -1064,46 +1061,25 @@ public class CombatUtil { return toughness; } - public static boolean canRegenerate(Card card) { - Player controller = card.getController(); - CardList l = AllZoneUtil.getCardsInPlay(); - for(Card c:l) - for(SpellAbility sa:c.getSpellAbility()) - // if SA is from AF_Counter don't add to getPlayable - //This try/catch should fix the "computer is thinking" bug - try { - if(sa.canPlay() && ComputerUtil.canPayCost(sa,controller) && sa.getAbilityFactory() != null && sa.isAbility()){ - AbilityFactory af = sa.getAbilityFactory(); - HashMap mapParams = af.getMapParams(); - if (mapParams.get("AB").equals("Regenerate")) - if (AbilityFactory.getDefinedCards(sa.getSourceCard(), mapParams.get("Defined"), sa).contains(card)) - return true; - } - } catch(Exception ex) { - showError(ex, "There is an error in the card code for %s:%n", c.getName(), ex.getMessage()); - } - - return false; - } - //can the blocker destroy the attacker? public static boolean canDestroyAttacker(Card attacker, Card defender, Combat combat, boolean noRegen) { - if(attacker.getName().equals("Sylvan Basilisk") && !defender.getKeyword().contains("Indestructible")) return false; + if(attacker.getName().equals("Sylvan Basilisk") && !defender.hasKeyword("Indestructible")) return false; int flankingMagnitude = 0; - if(attacker.getKeyword().contains("Flanking") && !defender.getKeyword().contains("Flanking")) { + if(attacker.hasKeyword("Flanking") && !defender.hasKeyword("Flanking")) { flankingMagnitude = attacker.getAmountOfKeyword("Flanking"); if(flankingMagnitude >= defender.getNetDefense()) return false; - if(flankingMagnitude >= defender.getNetDefense() - defender.getDamage() && !defender.getKeyword().contains("Indestructible")) + if(flankingMagnitude >= defender.getNetDefense() - defender.getDamage() && !defender.hasKeyword("Indestructible")) return false; - }//flanking - if((attacker.getKeyword().contains("Indestructible") || (canRegenerate(attacker) && !noRegen)) && - !(defender.getKeyword().contains("Wither") || defender.getKeyword().contains("Infect"))) return false; + if(defender.hasKeyword("CARDNAME can't be regenerated.")) noRegen = true; + + if((attacker.hasKeyword("Indestructible") || (ComputerUtil.canRegenerate(attacker) && !noRegen)) && + !(defender.hasKeyword("Wither") || defender.hasKeyword("Infect"))) return false; int defenderDamage = defender.getNetAttack() + predictPowerBonusOfBlocker(attacker, defender); int attackerDamage = attacker.getNetAttack() + predictPowerBonusOfAttacker(attacker, defender, combat); @@ -1119,15 +1095,15 @@ public class CombatUtil { int defenderLife = defender.getKillDamage() + predictToughnessBonusOfBlocker(attacker, defender); int attackerLife = attacker.getKillDamage() + predictToughnessBonusOfAttacker(attacker, defender, combat); - if(defender.getKeyword().contains("Double Strike") ) { - if(defender.getKeyword().contains("Deathtouch") && defenderDamage > 0) return true; + if(defender.hasKeyword("Double Strike") ) { + if(defender.hasKeyword("Deathtouch") && defenderDamage > 0) return true; if(defenderDamage >= attackerLife) return true; //Attacker may kill the blocker before he can deal normal (secondary) damage - if((attacker.getKeyword().contains("Double Strike") || attacker.getKeyword().contains("First Strike")) - && !defender.getKeyword().contains("Indestructible")) { + if((attacker.hasKeyword("Double Strike") || attacker.hasKeyword("First Strike")) + && !defender.hasKeyword("Indestructible")) { if(attackerDamage >= defenderLife) return false; - if(attackerDamage > 0 && attacker.getKeyword().contains("Deathtouch")) return false; + if(attackerDamage > 0 && attacker.hasKeyword("Deathtouch")) return false; } if(attackerLife <= 2 * defenderDamage) return true; }//defender double strike @@ -1135,14 +1111,14 @@ public class CombatUtil { else //no double strike for defender { //Attacker may kill the blocker before he can deal any damage - if(attacker.getKeyword().contains("Double Strike") || attacker.getKeyword().contains("First Strike") - && !defender.getKeyword().contains("Indestructible") && !defender.getKeyword().contains("First Strike")) { + if(attacker.hasKeyword("Double Strike") || attacker.hasKeyword("First Strike") + && !defender.hasKeyword("Indestructible") && !defender.hasKeyword("First Strike")) { if(attackerDamage >= defenderLife) return false; - if(attackerDamage > 0 && attacker.getKeyword().contains("Deathtouch") ) return false; + if(attackerDamage > 0 && attacker.hasKeyword("Deathtouch") ) return false; } - if(defender.getKeyword().contains("Deathtouch") && defenderDamage > 0) return true; + if(defender.hasKeyword("Deathtouch") && defenderDamage > 0) return true; return defenderDamage >= attackerLife; @@ -1156,7 +1132,7 @@ public class CombatUtil { Card attacker = AllZone.Combat.getAttackerBlockedBy(blocker); if(canDestroyBlocker(blocker, attacker, AllZone.Combat, true) && - !(attacker.getKeyword().contains("Wither") || attacker.getKeyword().contains("Infect"))) + !(attacker.hasKeyword("Wither") || attacker.hasKeyword("Infect"))) return true; return false; } @@ -1165,18 +1141,20 @@ public class CombatUtil { public static boolean canDestroyBlocker(Card defender, Card attacker, Combat combat, boolean noRegen) { int flankingMagnitude = 0; - if(attacker.getKeyword().contains("Flanking") && !defender.getKeyword().contains("Flanking")) { + if(attacker.hasKeyword("Flanking") && !defender.hasKeyword("Flanking")) { flankingMagnitude = attacker.getAmountOfKeyword("Flanking"); if(flankingMagnitude >= defender.getNetDefense()) return true; - if((flankingMagnitude >= defender.getKillDamage()) && !defender.getKeyword().contains("Indestructible")) return true; + if((flankingMagnitude >= defender.getKillDamage()) && !defender.hasKeyword("Indestructible")) return true; }//flanking - if((defender.getKeyword().contains("Indestructible") || (canRegenerate(defender) && !noRegen)) && - !(attacker.getKeyword().contains("Wither") || attacker.getKeyword().contains("Infect"))) return false; + if(defender.hasKeyword("CARDNAME can't be regenerated.")) noRegen = true; - if(attacker.getName().equals("Sylvan Basilisk") && !defender.getKeyword().contains("Indestructible")) return true; + if((defender.hasKeyword("Indestructible") || (ComputerUtil.canRegenerate(defender) && !noRegen)) && + !(attacker.hasKeyword("Wither") || attacker.hasKeyword("Infect"))) return false; + + if(attacker.getName().equals("Sylvan Basilisk") && !defender.hasKeyword("Indestructible")) return true; int defenderDamage = defender.getNetAttack() + predictPowerBonusOfBlocker(attacker, defender); int attackerDamage = attacker.getNetAttack() + predictPowerBonusOfAttacker(attacker, defender, combat); @@ -1192,15 +1170,15 @@ public class CombatUtil { int defenderLife = defender.getKillDamage() + predictToughnessBonusOfBlocker(attacker, defender); int attackerLife = attacker.getKillDamage() + predictToughnessBonusOfAttacker(attacker, defender, combat); - if(attacker.getKeyword().contains("Double Strike") ) { - if(attacker.getKeyword().contains("Deathtouch") && attackerDamage > 0) return true; + if(attacker.hasKeyword("Double Strike") ) { + if(attacker.hasKeyword("Deathtouch") && attackerDamage > 0) return true; if(attackerDamage >= defenderLife) return true; //Attacker may kill the blocker before he can deal normal (secondary) damage - if((defender.getKeyword().contains("Double Strike") || defender.getKeyword().contains("First Strike")) - && !attacker.getKeyword().contains("Indestructible")) { + if((defender.hasKeyword("Double Strike") || defender.hasKeyword("First Strike")) + && !attacker.hasKeyword("Indestructible")) { if(defenderDamage >= attackerLife) return false; - if(defenderDamage > 0 && defender.getKeyword().contains("Deathtouch")) return false; + if(defenderDamage > 0 && defender.hasKeyword("Deathtouch")) return false; } if(defenderLife <= 2 * attackerDamage) return true; }//attacker double strike @@ -1208,14 +1186,14 @@ public class CombatUtil { else //no double strike for attacker { //Defender may kill the attacker before he can deal any damage - if(defender.getKeyword().contains("Double Strike") || defender.getKeyword().contains("First Strike") - && !attacker.getKeyword().contains("Indestructible") && !attacker.getKeyword().contains("First Strike")) { + if(defender.hasKeyword("Double Strike") || defender.hasKeyword("First Strike") + && !attacker.hasKeyword("Indestructible") && !attacker.hasKeyword("First Strike")) { if(defenderDamage >= attackerLife) return false; - if(defenderDamage > 0 && defender.getKeyword().contains("Deathtouch")) return false; + if(defenderDamage > 0 && defender.hasKeyword("Deathtouch")) return false; } - if(attacker.getKeyword().contains("Deathtouch") && attackerDamage > 0) return true; + if(attacker.hasKeyword("Deathtouch") && attackerDamage > 0) return true; return attackerDamage >= defenderLife; diff --git a/src/forge/ComputerUtil.java b/src/forge/ComputerUtil.java index 0889d4e4027..899f869fdf0 100644 --- a/src/forge/ComputerUtil.java +++ b/src/forge/ComputerUtil.java @@ -1,6 +1,8 @@ package forge; +import static forge.error.ErrorViewer.showError; + import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -306,55 +308,7 @@ public class ComputerUtil static public boolean canPayCost(SpellAbility sa) { - Card card = sa.getSourceCard(); - - CardList land = getAvailableMana(); - - if(sa.getSourceCard().isLand() /*&& sa.isTapAbility()*/) - { - land.remove(sa.getSourceCard()); - } - // Beached - Delete old - String mana = sa.getPayCosts() != null ? sa.getPayCosts().getTotalMana() : sa.getManaCost(); - - ManaCost cost = new ManaCost(mana); - - // Tack xMana Payments into mana here if X is a set value - if (sa.getPayCosts() != null && cost.getXcounter() > 0){ - String xSvar = card.getSVar("X").equals("Count$xPaid") ? "PayX" : "X"; - // For Count$xPaid set PayX in the AFs then use that here - // Else calculate it as appropriate. - if (!card.getSVar(xSvar).equals("")){ - int manaToAdd = AbilityFactory.calculateAmount(card, xSvar, sa) * cost.getXcounter(); - cost.increaseColorlessMana(manaToAdd); - } - } - - cost = AllZone.GameAction.getSpellCostChange(sa, cost); - if(cost.isPaid()) - return canPayAdditionalCosts(sa); - // Beached - Delete old - ArrayList colors; - - for(int i = 0; i < land.size(); i++) - { - colors = getColors(land.get(i)); - int once = 0; - - for(int j =0; j < colors.size(); j++) - { - if(cost.isNeeded(colors.get(j)) && once == 0) - { - cost.payMana(colors.get(j)); - once++; - } - - if(cost.isPaid()) { - return canPayAdditionalCosts(sa); - } - } - } - return false; + return canPayCost(sa, AllZone.ComputerPlayer); }//canPayCost() static public boolean canPayCost(SpellAbility sa, Player player) @@ -363,7 +317,7 @@ public class ComputerUtil CardList land = getAvailableMana(player); - if(card.isLand() && sa.getPayCosts().getTap()) + if(card.isLand()) { land.remove(card); } @@ -458,170 +412,7 @@ public class ComputerUtil static public boolean canPayAdditionalCosts(SpellAbility sa) { - // Add additional cost checks here before attempting to activate abilities - Cost cost = sa.getPayCosts(); - if (cost == null) - return true; - Card card = sa.getSourceCard(); - - if (cost.getTap() && (card.isTapped() || card.isSick())) - return false; - - if (cost.getUntap() && (card.isUntapped() || card.isSick())) - return false; - - if (cost.getTapXTypeCost()) - { - CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer); - typeList = typeList.getValidCards(cost.getTapXType().split(","),sa.getActivatingPlayer() ,sa.getSourceCard()); - - if (cost.getTap()) - typeList.remove(sa.getSourceCard()); - typeList = typeList.filter(AllZoneUtil.untapped); - - if (cost.getTapXTypeAmount() > typeList.size()) - return false; - } - - if (cost.getSubCounter()){ - Counters c = cost.getCounterType(); - if (card.getCounters(c) - cost.getCounterNum() < 0 || !AllZoneUtil.isCardInPlay(card)){ - return false; - } - } - - if (cost.getAddCounter()){ - // this should always be true - } - - if (cost.getLifeCost()){ - if (AllZone.ComputerPlayer.getLife() <= cost.getLifeAmount()) - return false; - } - - if (cost.getDiscardCost()){ - CardList handList = AllZoneUtil.getPlayerHand(card.getController()); - String discType = cost.getDiscardType(); - int discAmount = cost.getDiscardAmount(); - - if (cost.getDiscardThis()){ - if (!AllZone.getZone(card).getZoneName().equals(Constant.Zone.Hand)) - return false; - } - else if( discType.equals("LastDrawn")) { - //compy can't yet use this effectively - return false; - } - else if (discType.equals("Hand")){ - // this will always work - } - else{ - if (!discType.equals("Any") && !discType.equals("Random")){ - String validType[] = discType.split(","); - handList = handList.getValidCards(validType, sa.getActivatingPlayer(), sa.getSourceCard()); - } - if (discAmount > handList.size()){ - // not enough cards in hand to pay - return false; - } - } - } - - if (cost.getSacCost()){ - // if there's a sacrifice in the cost, just because we can Pay it doesn't mean we want to. - if (!cost.getSacThis()){ - CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer); - typeList = typeList.getValidCards(cost.getSacType().split(","), sa.getActivatingPlayer(), sa.getSourceCard()); - Card target = sa.getTargetCard(); - if (target != null && target.getController().isComputer()) // don't sacrifice the card we're pumping - typeList.remove(target); - - if (cost.getSacAmount() > typeList.size()) - return false; - } - else if (cost.getSacThis() && !AllZoneUtil.isCardInPlay(card)) - return false; - } - - if (cost.getExileCost()){ - // if there's an exile in the cost, just because we can Pay it doesn't mean we want to. - if (!cost.getExileThis()){ - CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer); - typeList = typeList.getValidCards(cost.getExileType().split(","), sa.getActivatingPlayer(), sa.getSourceCard()); - Card target = sa.getTargetCard(); - if (target != null && target.getController().isComputer()) // don't exile the card we're pumping - typeList.remove(target); - - if (cost.getExileAmount() > typeList.size()) - return false; - } - else if (cost.getExileThis() && !AllZoneUtil.isCardInPlay(card)) - return false; - } - - if (cost.getExileFromHandCost()){ - // if there's an exile in the cost, just because we can Pay it doesn't mean we want to. - if (!cost.getExileFromHandThis()){ - CardList typeList = AllZoneUtil.getPlayerHand(AllZone.ComputerPlayer); - typeList = typeList.getValidCards(cost.getExileFromHandType().split(","), sa.getActivatingPlayer(), sa.getSourceCard()); - Card target = sa.getTargetCard(); - if (target != null && target.getController().isComputer()) // don't exile the card we're pumping - typeList.remove(target); - - if (cost.getExileFromHandAmount() > typeList.size()) - return false; - } - else if (cost.getExileFromHandThis() && !AllZoneUtil.isCardInPlayerHand(card.getController(), card)) - return false; - } - - if (cost.getExileFromGraveCost()){ - if (!cost.getExileFromGraveThis()){ - CardList typeList = AllZoneUtil.getPlayerGraveyard(AllZone.ComputerPlayer); - typeList = typeList.getValidCards(cost.getExileFromGraveType().split(","), sa.getActivatingPlayer(), sa.getSourceCard()); - Card target = sa.getTargetCard(); - if (target != null && target.getController().isComputer()) // don't exile the card we're pumping - typeList.remove(target); - - if (cost.getExileFromGraveAmount() > typeList.size()) - return false; - } - else if (cost.getExileFromGraveThis() && !AllZoneUtil.isCardInPlayerGraveyard(card.getController(), card)) - return false; - } - - if(cost.getExileFromTopCost()){ - if(!cost.getExileFromTopThis()){ - CardList typeList = AllZoneUtil.getPlayerCardsInLibrary(AllZone.ComputerPlayer); - typeList = typeList.getValidCards(cost.getExileFromTopType().split(","), sa.getActivatingPlayer(), sa.getSourceCard()); - Card target = sa.getTargetCard(); - if (target != null && target.getController().isComputer()) // don't exile the card we're pumping - typeList.remove(target); - - if (cost.getExileFromTopAmount() > typeList.size()) - return false; - } - else if (cost.getExileFromTopThis() && !AllZoneUtil.isCardInPlayerLibrary(card.getController(), card)) - return false; - } - - if (cost.getReturnCost()){ - // if there's a return in the cost, just because we can Pay it doesn't mean we want to. - if (!cost.getReturnThis()){ - CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer); - typeList = typeList.getValidCards(cost.getReturnType().split(","), sa.getActivatingPlayer(), sa.getSourceCard()); - Card target = sa.getTargetCard(); - if (target != null && target.getController().isComputer()) // don't bounce the card we're pumping - typeList.remove(target); - - if (cost.getReturnAmount() > typeList.size()) - return false; - } - else if (!AllZoneUtil.isCardInPlay(card)) - return false; - } - - return true; + return canPayAdditionalCosts(sa, AllZone.ComputerPlayer); } static public boolean canPayAdditionalCosts(SpellAbility sa, Player player) @@ -938,37 +729,7 @@ public class ComputerUtil static public CardList getAvailableMana() { - CardList list = AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer); - CardList mana = list.filter(new CardListFilter() - { - public boolean addCard(Card c) - { - for (Ability_Mana am : c.getAIPlayableMana()) { - am.setActivatingPlayer(AllZone.ComputerPlayer); - if (am.canPlay()) return true; - } - - return false; - } - });//CardListFilter - - CardList sortedMana = new CardList(); - - for (int i=0; i mapParams = af.getMapParams(); + if (mapParams.get("AB").equals("Regenerate")) + if (AbilityFactory.getDefinedCards(sa.getSourceCard(), mapParams.get("Defined"), sa).contains(card)) + return true; + } + } catch(Exception ex) { + showError(ex, "There is an error in the card code for %s:%n", c.getName(), ex.getMessage()); + } + + return false; + } } \ No newline at end of file