From 38d2b95000f8506caa9c43e29e1588ac854289e1 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 12 Jun 2023 17:09:02 +0300 Subject: [PATCH 1/6] - Fix a card name in the MOM printsheet. --- forge-gui/res/blockdata/printsheets.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/blockdata/printsheets.txt b/forge-gui/res/blockdata/printsheets.txt index 471c19d3397..0386cd35b02 100644 --- a/forge-gui/res/blockdata/printsheets.txt +++ b/forge-gui/res/blockdata/printsheets.txt @@ -6190,7 +6190,7 @@ Kaya, Ghost Assassin|CN2|2 1 City on Fire|MOM 1 Etali, Primal Conquerer|MOM 1 Into the Fire|MOM -1 Invasion of Kaladheim|MOM +1 Invasion of Kaldheim|MOM 1 Invasion of Karsus|MOM 1 Nahiri's Warcrafting|MOM 1 Orthion, Hero of Lavabrink|MOM From 67e0610d38aeb013d72c7221e2faebec9d24bf42 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 12 Jun 2023 18:21:00 +0300 Subject: [PATCH 2/6] - Add logic for RevealOrChoose cost for the AI (Dragon's Fire) --- forge-ai/src/main/java/forge/ai/AiCostDecision.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java index c23d24e7299..63e15d53268 100644 --- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java +++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java @@ -2,10 +2,7 @@ package forge.ai; import static forge.ai.ComputerUtilCard.getBestCreatureAI; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import forge.card.MagicColor; import forge.game.cost.*; @@ -481,6 +478,14 @@ public class AiCostDecision extends CostDecisionMakerBase { return PaymentDecision.card(hand); } + if (cost.getRevealFrom().containsAll(Arrays.asList(ZoneType.Hand, ZoneType.Battlefield))) { // RevealOrChoose + CardCollection battlefieldOrHand = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), + type.split(";"), player, source, ability); + hand = CardLists.getValidCards(hand, type.split(";"), player, source, ability); + battlefieldOrHand.addAll(hand); + return PaymentDecision.card(getBestCreatureAI(battlefieldOrHand)); + } + if (cost.getType().equals("SameColor")) { return null; } From 59e8c5aab329793ddad8ad889ca51760e4a3b90c Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 12 Jun 2023 18:23:05 +0300 Subject: [PATCH 3/6] - Fix imports + avoid using variable assignment --- .../main/java/forge/ai/AiCostDecision.java | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java index 63e15d53268..125a45340c9 100644 --- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java +++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java @@ -1,27 +1,14 @@ package forge.ai; -import static forge.ai.ComputerUtilCard.getBestCreatureAI; - -import java.util.*; - -import forge.card.MagicColor; -import forge.game.cost.*; -import org.apache.commons.lang3.ObjectUtils; - import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Lists; - import forge.card.CardType; +import forge.card.MagicColor; import forge.game.Game; import forge.game.GameEntityCounterTable; -import forge.game.card.Card; -import forge.game.card.CardCollection; -import forge.game.card.CardCollectionView; -import forge.game.card.CardLists; -import forge.game.card.CardPredicates; -import forge.game.card.CounterEnumType; -import forge.game.card.CounterType; +import forge.game.card.*; +import forge.game.cost.*; import forge.game.keyword.Keyword; import forge.game.player.Player; import forge.game.spellability.SpellAbility; @@ -30,6 +17,11 @@ import forge.game.zone.ZoneType; import forge.util.Aggregates; import forge.util.TextUtil; import forge.util.collect.FCollectionView; +import org.apache.commons.lang3.ObjectUtils; + +import java.util.*; + +import static forge.ai.ComputerUtilCard.getBestCreatureAI; public class AiCostDecision extends CostDecisionMakerBase { private final CardCollection discarded; @@ -481,8 +473,7 @@ public class AiCostDecision extends CostDecisionMakerBase { if (cost.getRevealFrom().containsAll(Arrays.asList(ZoneType.Hand, ZoneType.Battlefield))) { // RevealOrChoose CardCollection battlefieldOrHand = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), type.split(";"), player, source, ability); - hand = CardLists.getValidCards(hand, type.split(";"), player, source, ability); - battlefieldOrHand.addAll(hand); + battlefieldOrHand.addAll(CardLists.getValidCards(hand, type.split(";"), player, source, ability)); return PaymentDecision.card(getBestCreatureAI(battlefieldOrHand)); } From 83b8cacdd4c40f97285940a79fce74a37d35d7c0 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 12 Jun 2023 18:24:29 +0300 Subject: [PATCH 4/6] - More robust RevealOrChoose detection --- forge-ai/src/main/java/forge/ai/AiCostDecision.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java index 125a45340c9..2f66ffa5698 100644 --- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java +++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java @@ -470,7 +470,7 @@ public class AiCostDecision extends CostDecisionMakerBase { return PaymentDecision.card(hand); } - if (cost.getRevealFrom().containsAll(Arrays.asList(ZoneType.Hand, ZoneType.Battlefield))) { // RevealOrChoose + if (cost.getRevealFrom().size() == 2 && cost.getRevealFrom().containsAll(Arrays.asList(ZoneType.Hand, ZoneType.Battlefield))) { // RevealOrChoose CardCollection battlefieldOrHand = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), type.split(";"), player, source, ability); battlefieldOrHand.addAll(CardLists.getValidCards(hand, type.split(";"), player, source, ability)); From 4b9ff0d23f892d59a1bcc89c27dc0df124cbacc1 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 12 Jun 2023 18:39:33 +0300 Subject: [PATCH 5/6] - For Dragon's Fire, only reveal stuff if power is 4 or greater. --- forge-ai/src/main/java/forge/ai/AiCostDecision.java | 9 ++++++++- forge-gui/res/cardsfolder/d/dragons_fire.txt | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java index 2f66ffa5698..960d39aa9e8 100644 --- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java +++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java @@ -471,10 +471,17 @@ public class AiCostDecision extends CostDecisionMakerBase { } if (cost.getRevealFrom().size() == 2 && cost.getRevealFrom().containsAll(Arrays.asList(ZoneType.Hand, ZoneType.Battlefield))) { // RevealOrChoose + String aiLogic = ability.getParamOrDefault("AILogic", ""); CardCollection battlefieldOrHand = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), type.split(";"), player, source, ability); battlefieldOrHand.addAll(CardLists.getValidCards(hand, type.split(";"), player, source, ability)); - return PaymentDecision.card(getBestCreatureAI(battlefieldOrHand)); + + if (aiLogic.startsWith("PowerAtLeast.")) { + int minPower = Integer.parseInt(aiLogic.substring(aiLogic.indexOf(".") + 1)); + battlefieldOrHand = CardLists.filterPower(battlefieldOrHand, minPower); + } + + return battlefieldOrHand.isEmpty() ? null : PaymentDecision.card(getBestCreatureAI(battlefieldOrHand)); } if (cost.getType().equals("SameColor")) { diff --git a/forge-gui/res/cardsfolder/d/dragons_fire.txt b/forge-gui/res/cardsfolder/d/dragons_fire.txt index bb01c2684ea..49ed1de448d 100644 --- a/forge-gui/res/cardsfolder/d/dragons_fire.txt +++ b/forge-gui/res/cardsfolder/d/dragons_fire.txt @@ -2,7 +2,7 @@ Name:Dragon's Fire ManaCost:1 R Types:Instant K:Kicker:RevealOrChoose<1/Dragon>:Generic -A:SP$ DealDamage | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker | NumDmg$ Y | SpellDescription$ CARDNAME deals 3 damage to target creature or planeswalker. If you revealed a Dragon card or chose a Dragon as you cast this spell, CARDNAME deals damage equal to the power of that card or creature instead. +A:SP$ DealDamage | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker | NumDmg$ Y | AILogic$ PowerAtLeast.4 | SpellDescription$ CARDNAME deals 3 damage to target creature or planeswalker. If you revealed a Dragon card or chose a Dragon as you cast this spell, CARDNAME deals damage equal to the power of that card or creature instead. SVar:Y:Count$OptionalGenericCostPaid.X.3 SVar:X:Revealed$CardPower Oracle:As an additional cost to cast this spell, you may reveal a Dragon card from your hand or choose a Dragon you control.\nDragon's Fire deals 3 damage to target creature or planeswalker. If you revealed a Dragon card or chose a Dragon as you cast this spell, Dragon's Fire deals damage equal to the power of that card or creature instead. From 582f9497913ce37f5ade39b63f5e3867e80d15e4 Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 12 Jun 2023 18:56:18 +0300 Subject: [PATCH 6/6] - Simplify source lookup --- forge-ai/src/main/java/forge/ai/AiCostDecision.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java index 960d39aa9e8..fa708e1b5f7 100644 --- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java +++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java @@ -472,16 +472,14 @@ public class AiCostDecision extends CostDecisionMakerBase { if (cost.getRevealFrom().size() == 2 && cost.getRevealFrom().containsAll(Arrays.asList(ZoneType.Hand, ZoneType.Battlefield))) { // RevealOrChoose String aiLogic = ability.getParamOrDefault("AILogic", ""); - CardCollection battlefieldOrHand = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), - type.split(";"), player, source, ability); - battlefieldOrHand.addAll(CardLists.getValidCards(hand, type.split(";"), player, source, ability)); + hand = CardLists.getValidCards(hand, type.split(";"), player, source, ability); if (aiLogic.startsWith("PowerAtLeast.")) { int minPower = Integer.parseInt(aiLogic.substring(aiLogic.indexOf(".") + 1)); - battlefieldOrHand = CardLists.filterPower(battlefieldOrHand, minPower); + hand = CardLists.filterPower(hand, minPower); } - return battlefieldOrHand.isEmpty() ? null : PaymentDecision.card(getBestCreatureAI(battlefieldOrHand)); + return hand.isEmpty() ? null : PaymentDecision.card(getBestCreatureAI(hand)); } if (cost.getType().equals("SameColor")) {