From e95d34840212b3df7687fe78b5f1d87e25123ae3 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Sat, 23 Apr 2022 21:57:12 +0200 Subject: [PATCH 1/3] Fix attacking property LKI check --- .../java/forge/game/ability/AbilityUtils.java | 22 +++++++++++++------ .../java/forge/game/card/CardProperty.java | 6 +++-- .../cardsfolder/m/mangara_the_diplomat.txt | 4 ++-- 3 files changed, 21 insertions(+), 11 deletions(-) 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 02e5d097ee7..f2f002f9298 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -2762,14 +2762,22 @@ public class AbilityUtils { String[] paidparts = l[0].split("\\$", 2); String[] lparts = paidparts[0].split(" ", 2); - final CardCollectionView cardsInZones = lparts[0].length() > 5 - ? game.getCardsIn(ZoneType.listValueOf(lparts[0].substring(5))) - : game.getCardsIn(ZoneType.Battlefield); - - if (paidparts.length > 1) { - return doXMath(handlePaid(CardLists.getValidCards(cardsInZones, lparts[1], player, c, ctb), paidparts[1], c, ctb), expr, c, ctb); + final CardCollectionView cardsInZones; + if (lparts[0].contains("All")) { + cardsInZones = game.getCardsInGame(); + } else { + cardsInZones = lparts[0].length() > 5 + ? game.getCardsIn(ZoneType.listValueOf(lparts[0].substring(5))) + : game.getCardsIn(ZoneType.Battlefield); } - return doXMath(CardLists.getValidCardCount(cardsInZones, lparts[1], player, c, ctb), expr, c, ctb); + + int cnt; + if (paidparts.length > 1) { + cnt = handlePaid(CardLists.getValidCards(cardsInZones, lparts[1], player, c, ctb), paidparts[1], c, ctb); + } else { + cnt = CardLists.getValidCardCount(cardsInZones, lparts[1], player, c, ctb); + } + return doXMath(cnt, expr, c, ctb); } if (sq[0].startsWith("MostCardName")) { diff --git a/forge-game/src/main/java/forge/game/card/CardProperty.java b/forge-game/src/main/java/forge/game/card/CardProperty.java index dc12dba4a94..bb35a4e0e97 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -1485,7 +1485,9 @@ public class CardProperty { // These predicated refer to ongoing combat. If no combat happens, they'll return false (meaning not attacking/blocking ATM) else if (property.startsWith("attacking")) { if (null == combat) return false; - if (property.equals("attacking")) return card.isAttacking(); + // check this always first to make sure lki is only used when the card provides it + if (!(property.contains("LKI") ? lki : card).isAttacking()) return false; + if (property.equals("attacking")) return true; if (property.equals("attackingYou")) return combat.isAttacking(card, sourceController); if (property.equals("attackingSame")) { final GameEntity attacked = combat.getDefenderByAttacker(source); @@ -1493,7 +1495,7 @@ public class CardProperty { return false; } } - if (property.equals("attackingYouOrYourPW")) { + if (property.startsWith("attackingYouOrYourPW")) { GameEntity defender = combat.getDefenderByAttacker(card); if (defender instanceof Card) { // attack on a planeswalker that was removed from combat diff --git a/forge-gui/res/cardsfolder/m/mangara_the_diplomat.txt b/forge-gui/res/cardsfolder/m/mangara_the_diplomat.txt index 1c09541b6fe..c79a4b6ca7c 100644 --- a/forge-gui/res/cardsfolder/m/mangara_the_diplomat.txt +++ b/forge-gui/res/cardsfolder/m/mangara_the_diplomat.txt @@ -3,8 +3,8 @@ ManaCost:3 W Types:Legendary Creature Human Cleric PT:2/4 K:Lifelink -T:Mode$ AttackersDeclared | AttackingPlayer$ Player.Opponent | CheckSVar$ X | SVarCompare$ GE2 | Execute$ TrigDraw | TriggerZones$ Battlefield | NoResolvingCheck$ True | TriggerDescription$ Whenever an opponent attacks with creatures, if two or more of those creatures are attacking you and/or planeswalkers you control, draw a card. -SVar:X:Count$Valid Creature.attackingYouOrYourPW +T:Mode$ AttackersDeclared | AttackingPlayer$ Player.Opponent | CheckSVar$ X | SVarCompare$ GE2 | Execute$ TrigDraw | TriggerZones$ Battlefield | TriggerDescription$ Whenever an opponent attacks with creatures, if two or more of those creatures are attacking you and/or planeswalkers you control, draw a card. +SVar:X:Count$ValidAll Creature.attackingYouOrYourPWLKI SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 T:Mode$ SpellCast | ValidActivatingPlayer$ Opponent | ActivatorThisTurnCast$ EQ2 | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever an opponent casts their second spell each turn, draw a card. Oracle:Lifelink\nWhenever an opponent attacks with creatures, if two or more of those creatures are attacking you and/or planeswalkers you control, draw a card.\nWhenever an opponent casts their second spell each turn, draw a card. From 1356d05f6b87f8a7963603150dd734befb6c44b4 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Sat, 23 Apr 2022 21:57:40 +0200 Subject: [PATCH 2/3] Performance reorder --- forge-ai/src/main/java/forge/ai/AiController.java | 12 +++++------- forge-ai/src/main/java/forge/ai/ComputerUtil.java | 4 ++-- .../src/main/java/forge/ai/ability/EffectAi.java | 5 ++--- .../src/main/java/forge/ai/ability/PermanentAi.java | 2 +- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index a90820dc2dc..6768165d939 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -642,21 +642,19 @@ public class AiController { // Ideally this should cast canPlaySa to determine that the AI is truly able/willing to cast a spell, // but that is currently difficult to implement due to various side effects leading to stack overflow. Card host = sa.getHostCard(); - if (!ComputerUtil.castPermanentInMain1(player, sa) && host != null && !host.isLand() && ComputerUtilCost.canPayCost(sa, player, false)) { - if (sa instanceof SpellPermanent) { - return sa; - } + if (sa instanceof SpellPermanent && host != null && !host.isLand() && !ComputerUtil.castPermanentInMain1(player, sa) && ComputerUtilCost.canPayCost(sa, player, false)) { + return sa; } } return null; } - public boolean reserveManaSources(SpellAbility sa) { - return reserveManaSources(sa, PhaseType.MAIN2, false, false, null); - } public boolean reserveManaSourcesForNextSpell(SpellAbility sa, SpellAbility exceptForSa) { return reserveManaSources(sa, null, false, true, exceptForSa); } + public boolean reserveManaSources(SpellAbility sa) { + return reserveManaSources(sa, PhaseType.MAIN2, false, false, null); + } public boolean reserveManaSources(SpellAbility sa, PhaseType phaseType, boolean enemy) { return reserveManaSources(sa, phaseType, enemy, true, null); } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index b972b3b8fa8..353b690cf68 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -1676,7 +1676,7 @@ public class ComputerUtil { // Lethal Damage => prevent damage/regeneration/bounce/shroud if (threatApi == ApiType.DealDamage || threatApi == ApiType.DamageAll) { // If PredictDamage is >= Lethal Damage - final int dmg = AbilityUtils.calculateAmount(topStack.getHostCard(), + final int dmg = AbilityUtils.calculateAmount(source, topStack.getParam("NumDmg"), topStack); final SpellAbility sub = topStack.getSubAbility(); boolean noRegen = false; @@ -1756,7 +1756,7 @@ public class ComputerUtil { && (saviourApi == ApiType.ChangeZone || saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll || saviourApi == ApiType.Protection || saviourApi == ApiType.PutCounter || saviourApi == ApiType.PutCounterAll || saviourApi == null)) { - final int dmg = -AbilityUtils.calculateAmount(topStack.getHostCard(), + final int dmg = -AbilityUtils.calculateAmount(source, topStack.getParam("NumDef"), topStack); for (final Object o : objects) { if (o instanceof Card) { diff --git a/forge-ai/src/main/java/forge/ai/ability/EffectAi.java b/forge-ai/src/main/java/forge/ai/ability/EffectAi.java index 03257930982..df52d56b582 100644 --- a/forge-ai/src/main/java/forge/ai/ability/EffectAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/EffectAi.java @@ -11,7 +11,6 @@ import forge.ai.AiController; import forge.ai.ComputerUtil; import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCombat; -import forge.ai.ComputerUtilMana; import forge.ai.PlayerControllerAi; import forge.ai.SpecialCardAi; import forge.ai.SpellAbilityAi; @@ -122,8 +121,8 @@ public class EffectAi extends SpellAbilityAi { randomReturn = true; } else if (logic.equals("WillCastCreature") && ai.isAI()) { AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); - SpellAbility saCreature = aic.predictSpellToCastInMain2(ApiType.PermanentCreature); - randomReturn = saCreature != null && ComputerUtilMana.canPayManaCost(saCreature, ai, 0, false); + SpellAbility saCreature = aic.predictSpellToCastInMain2(ApiType.PermanentNoncreature); + randomReturn = saCreature != null; } else if (logic.equals("Always")) { randomReturn = true; } else if (logic.equals("Main1")) { diff --git a/forge-ai/src/main/java/forge/ai/ability/PermanentAi.java b/forge-ai/src/main/java/forge/ai/ability/PermanentAi.java index b13afdea52a..bbcfac625d2 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PermanentAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PermanentAi.java @@ -42,7 +42,7 @@ public class PermanentAi extends SpellAbilityAi { } // Wait for Main2 if possible - return !ph.is(PhaseType.MAIN1) || !ph.isPlayerTurn(ai) || ComputerUtil.castPermanentInMain1(ai, sa) || sa.hasParam("WithoutManaCost"); + return !ph.is(PhaseType.MAIN1) || !ph.isPlayerTurn(ai) || sa.hasParam("WithoutManaCost") || ComputerUtil.castPermanentInMain1(ai, sa); } /** From 56e9c9f364557b2ae1174ff513fe7f5e37559420 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Sat, 23 Apr 2022 21:57:48 +0200 Subject: [PATCH 3/3] Timing fix --- .../main/java/forge/game/ability/effects/RepeatEachEffect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java index 0853ba03dbc..5ee18f4f061 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java @@ -156,7 +156,7 @@ public class RepeatEachEffect extends SpellAbilityEffect { continue; } if (nextTurn) { - game.getUntap().addUntil(p, new GameCommand() { + game.getCleanup().addUntil(p, new GameCommand() { @Override public void run() { List tempRemembered = Lists.newArrayList(Iterables.filter(source.getRemembered(), Player.class));