diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index a447493f261..c517060964d 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -691,7 +691,7 @@ public class ComputerUtilCombat { if (flankingMagnitude >= blocker.getNetToughness()) { return 0; } - if ((flankingMagnitude >= (blocker.getNetToughness() - blocker.getDamage())) + if (flankingMagnitude >= blocker.getNetToughness() - blocker.getDamage() && !blocker.hasKeyword(Keyword.INDESTRUCTIBLE)) { return 0; } @@ -914,13 +914,6 @@ public class ComputerUtilCombat { public static int predictPowerBonusOfBlocker(final Card attacker, final Card blocker, boolean withoutAbilities) { int power = 0; - // Apparently, Flanking is predicted below from a trigger, so using the code below results in double - // application of power bonus. A bit more testing may be needed though, so commenting out for now. - /* - if (attacker.hasKeyword("Flanking") && !blocker.hasKeyword("Flanking")) { - power -= attacker.getAmountOfKeyword("Flanking"); - }*/ - // Serene Master switches power with attacker if (blocker.getName().equals("Serene Master")) { power += attacker.getNetPower() - blocker.getNetPower(); @@ -992,7 +985,7 @@ public class ComputerUtilCombat { String defined = sa.getParam("Defined"); final List list = AbilityUtils.getDefinedCards(source, defined, sa); - if ("TriggeredBlocker".equals(defined)) { + if (defined != null && defined.startsWith("TriggeredBlocker")) { list.add(blocker); } if (!list.contains(blocker)) { @@ -1067,10 +1060,6 @@ public class ComputerUtilCombat { public static int predictToughnessBonusOfBlocker(final Card attacker, final Card blocker, boolean withoutAbilities) { int toughness = 0; - if (attacker.hasKeyword(Keyword.FLANKING) && !blocker.hasKeyword(Keyword.FLANKING)) { - toughness -= attacker.getAmountOfKeyword(Keyword.FLANKING); - } - if (blocker.getName().equals("Shape Stealer")) { toughness += attacker.getNetToughness() - blocker.getNetToughness(); } @@ -1096,9 +1085,11 @@ public class ComputerUtilCombat { continue; } + final String defined = sa.getParam("Defined"); + // DealDamage triggers if (ApiType.DealDamage.equals(sa.getApi())) { - if (!"TriggeredBlocker".equals(sa.getParam("Defined"))) { + if (defined == null || !defined.startsWith("TriggeredBlocker")) { continue; } int damage = AbilityUtils.calculateAmount(source, sa.getParam("NumDmg"), sa); @@ -1107,7 +1098,7 @@ public class ComputerUtilCombat { // -1/-1 PutCounter triggers if (ApiType.PutCounter.equals(sa.getApi())) { - if (!"TriggeredBlocker".equals(sa.getParam("Defined"))) { + if (defined == null || !defined.startsWith("TriggeredBlocker")) { continue; } if (!"M1M1".equals(sa.getParam("CounterType"))) { @@ -1121,8 +1112,8 @@ public class ComputerUtilCombat { if (sa.usesTargeting()) { continue; // targeted pumping not supported } - final List list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), null); - if ("TriggeredBlocker".equals(sa.getParam("Defined"))) { + final List list = AbilityUtils.getDefinedCards(source, defined, null); + if (defined != null && defined.startsWith("TriggeredBlocker")) { list.add(blocker); } if (list.isEmpty() || !list.contains(blocker)) { @@ -1292,7 +1283,7 @@ public class ComputerUtilCombat { if (!sa.hasParam("ValidCards")) { list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), null); } - if (sa.hasParam("Defined") && sa.getParam("Defined").equals("TriggeredAttacker")) { + if (sa.hasParam("Defined") && sa.getParam("Defined").startsWith("TriggeredAttacker")) { list.add(attacker); } if (sa.hasParam("ValidCards")) { @@ -1496,8 +1487,9 @@ public class ComputerUtilCombat { if (!sa.hasParam("NumDef")) { continue; } - CardCollection list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa); - if ("TriggeredAttacker".equals(sa.getParam("Defined"))) { + final String defined = sa.getParam("Defined"); + CardCollection list = AbilityUtils.getDefinedCards(source, defined, sa); + if (defined != null && defined.startsWith("TriggeredAttacker")) { list.add(attacker); } if (!list.contains(attacker)) { @@ -1637,7 +1629,7 @@ public class ComputerUtilCombat { if (!sa.hasParam("Defined")) { continue; } - if (sa.getParam("Defined").equals("TriggeredAttacker")) { + if (sa.getParam("Defined").startsWith("TriggeredAttacker")) { return true; } if (sa.getParam("Defined").equals("Self") && source.equals(attacker)) { @@ -1891,7 +1883,7 @@ public class ComputerUtilCombat { if (!sa.hasParam("Defined")) { continue; } - if (sa.getParam("Defined").equals("TriggeredBlocker")) { + if (sa.getParam("Defined").startsWith("TriggeredBlocker")) { return true; } if (sa.getParam("Defined").equals("Self") && source.equals(blocker)) { @@ -1940,10 +1932,10 @@ public class ComputerUtilCombat { if (((blocker.hasKeyword(Keyword.INDESTRUCTIBLE) || (ComputerUtil.canRegenerate(ai, blocker) && !withoutAbilities)) && !(attacker .hasKeyword(Keyword.WITHER) || attacker.hasKeyword(Keyword.INFECT))) - || (blocker.hasKeyword(Keyword.PERSIST) && !blocker.canReceiveCounters(CounterEnumType.M1M1) && (blocker - .getCounters(CounterEnumType.M1M1) == 0)) - || (blocker.hasKeyword(Keyword.UNDYING) && !blocker.canReceiveCounters(CounterEnumType.P1P1) && (blocker - .getCounters(CounterEnumType.P1P1) == 0))) { + || (blocker.hasKeyword(Keyword.PERSIST) && !blocker.canReceiveCounters(CounterEnumType.M1M1) && blocker + .getCounters(CounterEnumType.M1M1) == 0) + || (blocker.hasKeyword(Keyword.UNDYING) && !blocker.canReceiveCounters(CounterEnumType.P1P1) && blocker + .getCounters(CounterEnumType.P1P1) == 0)) { return false; } @@ -2396,9 +2388,9 @@ public class ComputerUtilCombat { for (Card atk : attackers) { if (atk.hasKeyword(Keyword.FLYING) || atk.hasKeyword(Keyword.SHADOW) - || atk.hasKeyword(Keyword.HORSEMANSHIP) || (atk.hasKeyword(Keyword.FEAR) + || atk.hasKeyword(Keyword.HORSEMANSHIP) || atk.hasKeyword(Keyword.FEAR) || atk.hasKeyword(Keyword.INTIMIDATE) || atk.hasKeyword(Keyword.SKULK) - || atk.hasKeyword(Keyword.PROTECTION))) { + || atk.hasKeyword(Keyword.PROTECTION)) { withEvasion.add(atk); } else { withoutEvasion.add(atk); diff --git a/forge-ai/src/main/java/forge/ai/ability/AttachAi.java b/forge-ai/src/main/java/forge/ai/ability/AttachAi.java index 7eb100d2c00..489a66553fe 100644 --- a/forge-ai/src/main/java/forge/ai/ability/AttachAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/AttachAi.java @@ -1554,11 +1554,11 @@ public class AttachAi extends SpellAbilityAi { } } - final boolean evasive = (keyword.equals("Unblockable") || keyword.equals("Fear") + final boolean evasive = keyword.equals("Unblockable") || keyword.equals("Fear") || keyword.equals("Intimidate") || keyword.equals("Shadow") || keyword.equals("Flying") || keyword.equals("Horsemanship") || keyword.endsWith("walk") || keyword.startsWith("CantBeBlockedBy") - || keyword.equals("All creatures able to block CARDNAME do so.")); + || keyword.equals("All creatures able to block CARDNAME do so."); // give evasive keywords to creatures that can attack and deal damage boolean canBeBlocked = false; diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 3ccca83f1e3..4ff465ae098 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -3473,11 +3473,7 @@ public class AbilityUtils { } if (value.contains("DamageToOppsThisTurn")) { - int oppDmg = 0; - for (Player opp : player.getOpponents()) { - oppDmg += opp.getAssignedDamage(); - } - return doXMath(oppDmg, m, source, ctb); + return doXMath(player.getOpponentsAssignedDamage(), m, source, ctb); } if (value.contains("NonCombatDamageDealtThisTurn")) { diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 181b334dae1..f8cbd45b0a6 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -5240,9 +5240,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } else { assignedDamageMap.put(sourceCard, assignedDamageMap.get(sourceCard) + assignedDamage0); } - if (assignedDamage0 > 0) { - view.updateAssignedDamage(this); - } + view.updateAssignedDamage(this); } public final void clearAssignedDamage() { if (assignedDamageMap.isEmpty()) { return; } diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index e1756118730..80a19e91847 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -141,8 +141,7 @@ public final class CardUtil { for (Player p : game.getPlayers()) { res.addAll(p.getZone(to).getCardsAddedLastTurn(from)); } - } - else { + } else { res.addAll(game.getStackZone().getCardsAddedLastTurn(from)); } return CardLists.getValidCardsAsList(res, valid, src.getController(), src, ctb); diff --git a/forge-gui/res/cardsfolder/f/far_away.txt b/forge-gui/res/cardsfolder/f/far_away.txt index e99841c153b..0a593893ea7 100644 --- a/forge-gui/res/cardsfolder/f/far_away.txt +++ b/forge-gui/res/cardsfolder/f/far_away.txt @@ -12,5 +12,5 @@ ALTERNATE Name:Away ManaCost:2 B Types:Instant -A:SP$ Sacrifice | Cost$ 2 B | ValidTgts$ Player | SacValid$ Creature | SacMessage$ Creature | SpellDescription$ Target Player sacrifices a creature. +A:SP$ Sacrifice | Cost$ 2 B | ValidTgts$ Player | SacValid$ Creature | SacMessage$ Creature | SpellDescription$ Target player sacrifices a creature. Oracle:Target player sacrifices a creature.\nFuse (You may cast one or both halves of this card from your hand.)