From f529bc1c7a1a044a544380c607d936151f6592f8 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 15 Jan 2022 13:11:03 +0100 Subject: [PATCH] AbilityManaPart: support 'Combo X Chosen' Mana Part for Thriving Lands --- .../main/java/forge/ai/ComputerUtilMana.java | 22 +++---- .../main/java/forge/game/GameActionUtil.java | 2 +- .../game/ability/effects/ManaEffect.java | 2 +- .../main/java/forge/game/card/CardView.java | 61 ++++--------------- .../game/spellability/AbilityManaPart.java | 51 +++++++++------- .../forge/game/spellability/SpellAbility.java | 4 +- .../res/cardsfolder/t/thriving_bluff.txt | 3 +- .../res/cardsfolder/t/thriving_grove.txt | 3 +- .../res/cardsfolder/t/thriving_heath.txt | 3 +- forge-gui/res/cardsfolder/t/thriving_isle.txt | 3 +- forge-gui/res/cardsfolder/t/thriving_moor.txt | 3 +- 11 files changed, 61 insertions(+), 96 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java index ef5a43bd731..a7ff6bc44a7 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java @@ -156,8 +156,8 @@ public class ComputerUtilMana { // Mana abilities on the same card String shardMana = shard.toString().replaceAll("\\{", "").replaceAll("\\}", ""); - boolean payWithAb1 = ability1.getManaPart().mana().contains(shardMana); - boolean payWithAb2 = ability2.getManaPart().mana().contains(shardMana); + boolean payWithAb1 = ability1.getManaPart().mana(ability1).contains(shardMana); + boolean payWithAb2 = ability2.getManaPart().mana(ability2).contains(shardMana); if (payWithAb1 && !payWithAb2) { return -1; @@ -196,9 +196,9 @@ public class ComputerUtilMana { Collections.sort(prefSortedAbilities, new Comparator() { @Override public int compare(final SpellAbility ability1, final SpellAbility ability2) { - if (ability1.getManaPart().mana().contains(preferredShard)) + if (ability1.getManaPart().mana(ability1).contains(preferredShard)) return -1; - else if (ability2.getManaPart().mana().contains(preferredShard)) + else if (ability2.getManaPart().mana(ability2).contains(preferredShard)) return 1; return 0; @@ -207,9 +207,9 @@ public class ComputerUtilMana { Collections.sort(otherSortedAbilities, new Comparator() { @Override public int compare(final SpellAbility ability1, final SpellAbility ability2) { - if (ability1.getManaPart().mana().contains(preferredShard)) + if (ability1.getManaPart().mana(ability1).contains(preferredShard)) return 1; - else if (ability2.getManaPart().mana().contains(preferredShard)) + else if (ability2.getManaPart().mana(ability2).contains(preferredShard)) return -1; return 0; @@ -1021,7 +1021,7 @@ public class ComputerUtilMana { } if (m.isComboMana()) { - for (String s : m.getComboColors().split(" ")) { + for (String s : m.getComboColors(ma).split(" ")) { if (toPay == ManaCostShard.COLORED_X && !ManaCostBeingPaid.canColoredXShardBePaidByColor(s, xManaCostPaidByColor)) { continue; } @@ -1048,7 +1048,7 @@ public class ComputerUtilMana { } if (toPay == ManaCostShard.COLORED_X) { - for (String s : m.mana().split(" ")) { + for (String s : m.mana(ma).split(" ")) { if (ManaCostBeingPaid.canColoredXShardBePaidByColor(s, xManaCostPaidByColor)) { return true; } @@ -1164,7 +1164,7 @@ public class ComputerUtilMana { if (abMana.isComboMana()) { int amount = manaAb.hasParam("Amount") ? AbilityUtils.calculateAmount(source, manaAb.getParam("Amount"), manaAb) : 1; final ManaCostBeingPaid testCost = new ManaCostBeingPaid(cost); - final String[] comboColors = abMana.getComboColors().split(" "); + final String[] comboColors = abMana.getComboColors(manaAb).split(" "); for (int nMana = 1; nMana <= amount; nMana++) { String choice = ""; // Use expressChoice first @@ -1198,7 +1198,7 @@ public class ComputerUtilMana { } // check if combo mana can produce most common color in hand String commonColor = ComputerUtilCard.getMostProminentColor(ai.getCardsIn(ZoneType.Hand)); - if (!commonColor.isEmpty() && satisfiesColorChoice(abMana, choiceString, MagicColor.toShortString(commonColor)) && abMana.getComboColors().contains(MagicColor.toShortString(commonColor))) { + if (!commonColor.isEmpty() && satisfiesColorChoice(abMana, choiceString, MagicColor.toShortString(commonColor)) && abMana.getComboColors(manaAb).contains(MagicColor.toShortString(commonColor))) { choice = MagicColor.toShortString(commonColor); } else { // default to first available color @@ -1536,7 +1536,7 @@ public class ComputerUtilMana { } else if (producesAnyColor) { anyColorManaSources.add(card); } else if (usableManaAbilities == 1) { - if (manaAbilities.get(0).getManaPart().mana().equals("C")) { + if (manaAbilities.get(0).getManaPart().mana(manaAbilities.get(0)).equals("C")) { colorlessManaSources.add(card); } else { oneManaSources.add(card); diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index 367e1a0d975..81fbbc77dfd 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -733,7 +733,7 @@ public final class GameActionUtil { } else if (abMana.isSpecialMana()) { baseMana = abMana.getExpressChoice(); } else { - baseMana = abMana.mana(); + baseMana = abMana.mana(sa); } if (sa.getSubAbility() != null) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java index d4cf7ceb48f..85f94302707 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java @@ -54,7 +54,7 @@ public class ManaEffect extends SpellAbilityEffect { int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(card, sa.getParam("Amount"), sa) : 1; String express = abMana.getExpressChoice(); - String[] colorsProduced = abMana.getComboColors().split(" "); + String[] colorsProduced = abMana.getComboColors(sa).split(" "); final StringBuilder choiceString = new StringBuilder(); ColorSet colorOptions = ColorSet.fromNames(colorsProduced); diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index 42258ba0b12..86ae1bd1953 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import forge.game.spellability.AbilityManaPart; import forge.game.spellability.SpellAbility; import forge.util.*; import org.apache.commons.lang3.StringUtils; @@ -1429,57 +1430,19 @@ public class CardView extends GameEntityView { boolean cMana = false; int count = 0; int basicLandTypes = 0; - if (!state.getManaAbilities().isEmpty()) { - for (SpellAbility sa : state.getManaAbilities()) { - if (sa == null || sa.getManaPart() == null) - continue; - if (sa.getManaPart().isAnyMana()) { + for (SpellAbility sa : state.getManaAbilities()) { + if (sa == null) + continue; + for (AbilityManaPart mp : sa.getAllManaParts()) { + if (mp.isAnyMana()) { anyMana = true; } - if (sa.getManaPart().isComboMana()) { - String[] colorsProduced = sa.getManaPart().getComboColors().split(" "); - //todo improve this - for (final String s : colorsProduced) { - switch (s.toUpperCase()) { - case "R": - if (!rMana) { - count += 1; - rMana = true; - } - break; - case "G": - if (!gMana) { - count += 1; - gMana = true; - } - break; - case "B": - if (!bMana) { - count += 1; - bMana = true; - } - break; - case "U": - if (!uMana) { - count += 1; - uMana = true; - } - break; - case "W": - if (!wMana) { - count += 1; - wMana = true; - } - break; - case "C": - if (!cMana) { - cMana = true; - } - break; - } - } - } else { - switch (sa.getManaPart().getOrigProduced()) { + + String[] colorsProduced = mp.mana(sa).split(" "); + + //todo improve this + for (final String s : colorsProduced) { + switch (s.toUpperCase()) { case "R": if (!rMana) { count += 1; diff --git a/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java b/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java index 8f597db60b6..c23c44cf0a5 100644 --- a/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java +++ b/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java @@ -416,14 +416,15 @@ public class AbilityManaPart implements java.io.Serializable { * * @return a {@link java.lang.String} object. */ - public final String mana() { - if (this.getOrigProduced().contains("Chosen")) { - if (this.getSourceCard() != null && this.getSourceCard().hasChosenColor()) { - return MagicColor.toShortString(this.getSourceCard().getChosenColor()); - } - return ""; + public final String mana(SpellAbility sa) { + if (isComboMana()) { // when asking combo, just go there + return getComboColors(sa); } - return this.getOrigProduced(); + String produced = this.getOrigProduced(); + if (produced.contains("Chosen")) { + produced = produced.replace("Chosen", this.getChosenColor(sa)); + } + return produced; } /** @@ -488,7 +489,7 @@ public class AbilityManaPart implements java.io.Serializable { } public boolean isComboMana() { - return this.getOrigProduced().contains("Combo"); + return this.getOrigProduced().startsWith("Combo"); } public boolean isSpecialMana() { @@ -506,22 +507,13 @@ public class AbilityManaPart implements java.io.Serializable { */ public final boolean canProduce(final String s, final SpellAbility sa) { // TODO: need to handle replacement effects like 106.7 - + // Any mana never means Colorless? if (isAnyMana() && !s.equals("C")) { return true; } - String origProduced = getOrigProduced(); - if (origProduced.contains("Chosen") && sourceCard != null ) { - if (getSourceCard().hasChosenColor() && MagicColor.toShortString(getSourceCard().getChosenColor()).contains(s)) { - return true; - } - } - if (isComboMana()) { - return getComboColors().contains(s); - } - return origProduced.contains(s); + return mana(sa).contains(s); } /** {@inheritDoc} */ @@ -553,14 +545,18 @@ public class AbilityManaPart implements java.io.Serializable { /** * @return the color available in combination mana */ - public String getComboColors() { + public String getComboColors(SpellAbility sa) { String origProduced = getOrigProduced(); - if (!origProduced.contains("Combo")) { + if (!origProduced.startsWith("Combo")) { return ""; } if (origProduced.contains("Any")) { return "W U B R G"; } + // replace Chosen for Combo colors + if (origProduced.contains("Chosen")) { + origProduced = origProduced.replace("Chosen", getChosenColor(sa)); + } if (!origProduced.contains("ColorIdentity")) { return TextUtil.fastReplace(origProduced, "Combo ", ""); } @@ -582,6 +578,17 @@ public class AbilityManaPart implements java.io.Serializable { return sb.length() == 0 ? "" : sb.substring(0, sb.length() - 1); } + public String getChosenColor(SpellAbility sa) { + if (sa == null) { + return ""; + } + Card card = sa.getHostCard(); + if (card != null && card.hasChosenColor()) { + return MagicColor.toShortString(card.getChosenColor()); + } + return ""; + } + public Card getSourceCard() { return sourceCard; } @@ -644,7 +651,7 @@ public class AbilityManaPart implements java.io.Serializable { if (isSpecialMana()) { return true; } - String colorsProduced = isComboMana() ? getComboColors() : mana(); + String colorsProduced = mana(am); for (final String color : colorsProduced.split(" ")) { if (0 != (neededColor & ManaAtom.fromName(color))) { return true; diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 5f5cb789f2d..0769df7d7b2 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -311,7 +311,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit result += amount; } else { // For cards that produce like {C}{R} vs cards that produce {R}{R}. - result += mp.mana().split(" ").length * amount; + result += mp.mana(this).split(" ").length * amount; } } return result; @@ -2246,7 +2246,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit if (manaPart == null) { score++; //Assume a mana ability can generate at least 1 mana if the amount of mana can't be determined now. } else { - String mana = manaPart.mana(); + String mana = manaPart.mana(this); if (!mana.equals("Any")) { score += mana.length(); if (!canProduce("C")) { diff --git a/forge-gui/res/cardsfolder/t/thriving_bluff.txt b/forge-gui/res/cardsfolder/t/thriving_bluff.txt index d4d2cc9290e..d43d9c286a7 100644 --- a/forge-gui/res/cardsfolder/t/thriving_bluff.txt +++ b/forge-gui/res/cardsfolder/t/thriving_bluff.txt @@ -4,6 +4,5 @@ Types:Land K:CARDNAME enters the battlefield tapped. K:ETBReplacement:Other:ChooseColor SVar:ChooseColor:DB$ ChooseColor | Defined$ You | Exclude$ red | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a color other than red. -A:AB$ Mana | Cost$ T | Produced$ R | SpellDescription$ Add {R}. -A:AB$ Mana | Cost$ T | Produced$ Chosen | SpellDescription$ Add one mana of the chosen color. +A:AB$ Mana | Cost$ T | Produced$ Combo R Chosen | SpellDescription$ Add {R} or one mana of the chosen color. Oracle:Thriving Bluff enters the battlefield tapped.\nAs Thriving Bluff enters the battlefield, choose a color other than red.\n{T}: Add {R} or one mana of the chosen color. diff --git a/forge-gui/res/cardsfolder/t/thriving_grove.txt b/forge-gui/res/cardsfolder/t/thriving_grove.txt index 3b6317c2d88..8b31aa2a3e1 100644 --- a/forge-gui/res/cardsfolder/t/thriving_grove.txt +++ b/forge-gui/res/cardsfolder/t/thriving_grove.txt @@ -4,6 +4,5 @@ Types:Land K:CARDNAME enters the battlefield tapped. K:ETBReplacement:Other:ChooseColor SVar:ChooseColor:DB$ ChooseColor | Defined$ You | Exclude$ green | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a color other than green. -A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G}. -A:AB$ Mana | Cost$ T | Produced$ Chosen | SpellDescription$ Add one mana of the chosen color. +A:AB$ Mana | Cost$ T | Produced$ Combo G Chosen | SpellDescription$ Add {G} or one mana of the chosen color. Oracle:Thriving Grove enters the battlefield tapped.\nAs Thriving Grove enters the battlefield, choose a color other than green.\n{T}: Add {G} or one mana of the chosen color. diff --git a/forge-gui/res/cardsfolder/t/thriving_heath.txt b/forge-gui/res/cardsfolder/t/thriving_heath.txt index 17e791c10ec..178616bb629 100644 --- a/forge-gui/res/cardsfolder/t/thriving_heath.txt +++ b/forge-gui/res/cardsfolder/t/thriving_heath.txt @@ -4,6 +4,5 @@ Types:Land K:CARDNAME enters the battlefield tapped. K:ETBReplacement:Other:ChooseColor SVar:ChooseColor:DB$ ChooseColor | Defined$ You | Exclude$ white | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a color other than white. -A:AB$ Mana | Cost$ T | Produced$ W | SpellDescription$ Add {W}. -A:AB$ Mana | Cost$ T | Produced$ Chosen | SpellDescription$ Add one mana of the chosen color. +A:AB$ Mana | Cost$ T | Produced$ Combo W Chosen | SpellDescription$ Add {W} or one mana of the chosen color. Oracle:Thriving Heath enters the battlefield tapped.\nAs Thriving Heath enters the battlefield, choose a color other than white.\n{T}: Add {W} or one mana of the chosen color. diff --git a/forge-gui/res/cardsfolder/t/thriving_isle.txt b/forge-gui/res/cardsfolder/t/thriving_isle.txt index 31018a87a72..0fe970fb1a8 100644 --- a/forge-gui/res/cardsfolder/t/thriving_isle.txt +++ b/forge-gui/res/cardsfolder/t/thriving_isle.txt @@ -4,6 +4,5 @@ Types:Land K:CARDNAME enters the battlefield tapped. K:ETBReplacement:Other:ChooseColor SVar:ChooseColor:DB$ ChooseColor | Defined$ You | Exclude$ blue | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a color other than blue. -A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U}. -A:AB$ Mana | Cost$ T | Produced$ Chosen | SpellDescription$ Add one mana of the chosen color. +A:AB$ Mana | Cost$ T | Produced$ Combo U Chosen | SpellDescription$ Add {U} or one mana of the chosen color. Oracle:Thriving Isle enters the battlefield tapped.\nAs Thriving Isle enters the battlefield, choose a color other than blue.\n{T}: Add {U} or one mana of the chosen color. diff --git a/forge-gui/res/cardsfolder/t/thriving_moor.txt b/forge-gui/res/cardsfolder/t/thriving_moor.txt index 43fb93544b8..f5bf75c3d23 100644 --- a/forge-gui/res/cardsfolder/t/thriving_moor.txt +++ b/forge-gui/res/cardsfolder/t/thriving_moor.txt @@ -4,6 +4,5 @@ Types:Land K:CARDNAME enters the battlefield tapped. K:ETBReplacement:Other:ChooseColor SVar:ChooseColor:DB$ ChooseColor | Defined$ You | Exclude$ black | AILogic$ MostProminentInComputerDeck | SpellDescription$ As CARDNAME enters the battlefield, choose a color other than black. -A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B}. -A:AB$ Mana | Cost$ T | Produced$ Chosen | SpellDescription$ Add one mana of the chosen color. +A:AB$ Mana | Cost$ T | Produced$ Combo B Chosen | SpellDescription$ Add {B} or one mana of the chosen color. Oracle:Thriving Moor enters the battlefield tapped.\nAs Thriving Moor enters the battlefield, choose a color other than black.\n{T}: Add {B} or one mana of the chosen color.