Fix some bad params in AI combat trigger prediction

This commit is contained in:
tool4EvEr
2022-01-07 23:12:45 +01:00
parent 0e58a54834
commit 8d1049beac
6 changed files with 26 additions and 41 deletions

View File

@@ -691,7 +691,7 @@ public class ComputerUtilCombat {
if (flankingMagnitude >= blocker.getNetToughness()) { if (flankingMagnitude >= blocker.getNetToughness()) {
return 0; return 0;
} }
if ((flankingMagnitude >= (blocker.getNetToughness() - blocker.getDamage())) if (flankingMagnitude >= blocker.getNetToughness() - blocker.getDamage()
&& !blocker.hasKeyword(Keyword.INDESTRUCTIBLE)) { && !blocker.hasKeyword(Keyword.INDESTRUCTIBLE)) {
return 0; return 0;
} }
@@ -914,13 +914,6 @@ public class ComputerUtilCombat {
public static int predictPowerBonusOfBlocker(final Card attacker, final Card blocker, boolean withoutAbilities) { public static int predictPowerBonusOfBlocker(final Card attacker, final Card blocker, boolean withoutAbilities) {
int power = 0; 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 // Serene Master switches power with attacker
if (blocker.getName().equals("Serene Master")) { if (blocker.getName().equals("Serene Master")) {
power += attacker.getNetPower() - blocker.getNetPower(); power += attacker.getNetPower() - blocker.getNetPower();
@@ -992,7 +985,7 @@ public class ComputerUtilCombat {
String defined = sa.getParam("Defined"); String defined = sa.getParam("Defined");
final List<Card> list = AbilityUtils.getDefinedCards(source, defined, sa); final List<Card> list = AbilityUtils.getDefinedCards(source, defined, sa);
if ("TriggeredBlocker".equals(defined)) { if (defined != null && defined.startsWith("TriggeredBlocker")) {
list.add(blocker); list.add(blocker);
} }
if (!list.contains(blocker)) { if (!list.contains(blocker)) {
@@ -1067,10 +1060,6 @@ public class ComputerUtilCombat {
public static int predictToughnessBonusOfBlocker(final Card attacker, final Card blocker, boolean withoutAbilities) { public static int predictToughnessBonusOfBlocker(final Card attacker, final Card blocker, boolean withoutAbilities) {
int toughness = 0; int toughness = 0;
if (attacker.hasKeyword(Keyword.FLANKING) && !blocker.hasKeyword(Keyword.FLANKING)) {
toughness -= attacker.getAmountOfKeyword(Keyword.FLANKING);
}
if (blocker.getName().equals("Shape Stealer")) { if (blocker.getName().equals("Shape Stealer")) {
toughness += attacker.getNetToughness() - blocker.getNetToughness(); toughness += attacker.getNetToughness() - blocker.getNetToughness();
} }
@@ -1096,9 +1085,11 @@ public class ComputerUtilCombat {
continue; continue;
} }
final String defined = sa.getParam("Defined");
// DealDamage triggers // DealDamage triggers
if (ApiType.DealDamage.equals(sa.getApi())) { if (ApiType.DealDamage.equals(sa.getApi())) {
if (!"TriggeredBlocker".equals(sa.getParam("Defined"))) { if (defined == null || !defined.startsWith("TriggeredBlocker")) {
continue; continue;
} }
int damage = AbilityUtils.calculateAmount(source, sa.getParam("NumDmg"), sa); int damage = AbilityUtils.calculateAmount(source, sa.getParam("NumDmg"), sa);
@@ -1107,7 +1098,7 @@ public class ComputerUtilCombat {
// -1/-1 PutCounter triggers // -1/-1 PutCounter triggers
if (ApiType.PutCounter.equals(sa.getApi())) { if (ApiType.PutCounter.equals(sa.getApi())) {
if (!"TriggeredBlocker".equals(sa.getParam("Defined"))) { if (defined == null || !defined.startsWith("TriggeredBlocker")) {
continue; continue;
} }
if (!"M1M1".equals(sa.getParam("CounterType"))) { if (!"M1M1".equals(sa.getParam("CounterType"))) {
@@ -1121,8 +1112,8 @@ public class ComputerUtilCombat {
if (sa.usesTargeting()) { if (sa.usesTargeting()) {
continue; // targeted pumping not supported continue; // targeted pumping not supported
} }
final List<Card> list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), null); final List<Card> list = AbilityUtils.getDefinedCards(source, defined, null);
if ("TriggeredBlocker".equals(sa.getParam("Defined"))) { if (defined != null && defined.startsWith("TriggeredBlocker")) {
list.add(blocker); list.add(blocker);
} }
if (list.isEmpty() || !list.contains(blocker)) { if (list.isEmpty() || !list.contains(blocker)) {
@@ -1292,7 +1283,7 @@ public class ComputerUtilCombat {
if (!sa.hasParam("ValidCards")) { if (!sa.hasParam("ValidCards")) {
list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), null); 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); list.add(attacker);
} }
if (sa.hasParam("ValidCards")) { if (sa.hasParam("ValidCards")) {
@@ -1496,8 +1487,9 @@ public class ComputerUtilCombat {
if (!sa.hasParam("NumDef")) { if (!sa.hasParam("NumDef")) {
continue; continue;
} }
CardCollection list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa); final String defined = sa.getParam("Defined");
if ("TriggeredAttacker".equals(sa.getParam("Defined"))) { CardCollection list = AbilityUtils.getDefinedCards(source, defined, sa);
if (defined != null && defined.startsWith("TriggeredAttacker")) {
list.add(attacker); list.add(attacker);
} }
if (!list.contains(attacker)) { if (!list.contains(attacker)) {
@@ -1637,7 +1629,7 @@ public class ComputerUtilCombat {
if (!sa.hasParam("Defined")) { if (!sa.hasParam("Defined")) {
continue; continue;
} }
if (sa.getParam("Defined").equals("TriggeredAttacker")) { if (sa.getParam("Defined").startsWith("TriggeredAttacker")) {
return true; return true;
} }
if (sa.getParam("Defined").equals("Self") && source.equals(attacker)) { if (sa.getParam("Defined").equals("Self") && source.equals(attacker)) {
@@ -1891,7 +1883,7 @@ public class ComputerUtilCombat {
if (!sa.hasParam("Defined")) { if (!sa.hasParam("Defined")) {
continue; continue;
} }
if (sa.getParam("Defined").equals("TriggeredBlocker")) { if (sa.getParam("Defined").startsWith("TriggeredBlocker")) {
return true; return true;
} }
if (sa.getParam("Defined").equals("Self") && source.equals(blocker)) { 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 if (((blocker.hasKeyword(Keyword.INDESTRUCTIBLE) || (ComputerUtil.canRegenerate(ai, blocker) && !withoutAbilities)) && !(attacker
.hasKeyword(Keyword.WITHER) || attacker.hasKeyword(Keyword.INFECT))) .hasKeyword(Keyword.WITHER) || attacker.hasKeyword(Keyword.INFECT)))
|| (blocker.hasKeyword(Keyword.PERSIST) && !blocker.canReceiveCounters(CounterEnumType.M1M1) && (blocker || (blocker.hasKeyword(Keyword.PERSIST) && !blocker.canReceiveCounters(CounterEnumType.M1M1) && blocker
.getCounters(CounterEnumType.M1M1) == 0)) .getCounters(CounterEnumType.M1M1) == 0)
|| (blocker.hasKeyword(Keyword.UNDYING) && !blocker.canReceiveCounters(CounterEnumType.P1P1) && (blocker || (blocker.hasKeyword(Keyword.UNDYING) && !blocker.canReceiveCounters(CounterEnumType.P1P1) && blocker
.getCounters(CounterEnumType.P1P1) == 0))) { .getCounters(CounterEnumType.P1P1) == 0)) {
return false; return false;
} }
@@ -2396,9 +2388,9 @@ public class ComputerUtilCombat {
for (Card atk : attackers) { for (Card atk : attackers) {
if (atk.hasKeyword(Keyword.FLYING) || atk.hasKeyword(Keyword.SHADOW) 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.INTIMIDATE) || atk.hasKeyword(Keyword.SKULK)
|| atk.hasKeyword(Keyword.PROTECTION))) { || atk.hasKeyword(Keyword.PROTECTION)) {
withEvasion.add(atk); withEvasion.add(atk);
} else { } else {
withoutEvasion.add(atk); withoutEvasion.add(atk);

View File

@@ -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("Intimidate") || keyword.equals("Shadow")
|| keyword.equals("Flying") || keyword.equals("Horsemanship") || keyword.equals("Flying") || keyword.equals("Horsemanship")
|| keyword.endsWith("walk") || keyword.startsWith("CantBeBlockedBy") || 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 // give evasive keywords to creatures that can attack and deal damage
boolean canBeBlocked = false; boolean canBeBlocked = false;

View File

@@ -3473,11 +3473,7 @@ public class AbilityUtils {
} }
if (value.contains("DamageToOppsThisTurn")) { if (value.contains("DamageToOppsThisTurn")) {
int oppDmg = 0; return doXMath(player.getOpponentsAssignedDamage(), m, source, ctb);
for (Player opp : player.getOpponents()) {
oppDmg += opp.getAssignedDamage();
}
return doXMath(oppDmg, m, source, ctb);
} }
if (value.contains("NonCombatDamageDealtThisTurn")) { if (value.contains("NonCombatDamageDealtThisTurn")) {

View File

@@ -5240,9 +5240,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
} else { } else {
assignedDamageMap.put(sourceCard, assignedDamageMap.get(sourceCard) + assignedDamage0); assignedDamageMap.put(sourceCard, assignedDamageMap.get(sourceCard) + assignedDamage0);
} }
if (assignedDamage0 > 0) { view.updateAssignedDamage(this);
view.updateAssignedDamage(this);
}
} }
public final void clearAssignedDamage() { public final void clearAssignedDamage() {
if (assignedDamageMap.isEmpty()) { return; } if (assignedDamageMap.isEmpty()) { return; }

View File

@@ -141,8 +141,7 @@ public final class CardUtil {
for (Player p : game.getPlayers()) { for (Player p : game.getPlayers()) {
res.addAll(p.getZone(to).getCardsAddedLastTurn(from)); res.addAll(p.getZone(to).getCardsAddedLastTurn(from));
} }
} } else {
else {
res.addAll(game.getStackZone().getCardsAddedLastTurn(from)); res.addAll(game.getStackZone().getCardsAddedLastTurn(from));
} }
return CardLists.getValidCardsAsList(res, valid, src.getController(), src, ctb); return CardLists.getValidCardsAsList(res, valid, src.getController(), src, ctb);

View File

@@ -12,5 +12,5 @@ ALTERNATE
Name:Away Name:Away
ManaCost:2 B ManaCost:2 B
Types:Instant 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.) Oracle:Target player sacrifices a creature.\nFuse (You may cast one or both halves of this card from your hand.)