From 2f5799f4535d06d97fbdd4260d12adf384a3d7d1 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Thu, 6 Feb 2014 04:55:30 +0000 Subject: [PATCH] routed all checks like 'can pay for this shard with mana of certain color' through either player's manapool, or a method in ManaCostBeingPaid. Will add a color conversion matrix at these 2 points later. This change is a prerequisite to implement cards like Daxos of Meletis --- .../main/java/forge/ai/ComputerUtilMana.java | 52 +++++- .../java/forge/game/card/CardFactoryUtil.java | 4 +- .../forge/game/mana/ManaCostBeingPaid.java | 49 ++--- .../main/java/forge/game/mana/ManaPool.java | 9 +- .../java/forge/card/mana/ManaPartTest.java | 168 +++++++++--------- 5 files changed, 146 insertions(+), 136 deletions(-) diff --git a/forge-game/src/main/java/forge/ai/ComputerUtilMana.java b/forge-game/src/main/java/forge/ai/ComputerUtilMana.java index 6fa19427a31..09ec5c05c32 100644 --- a/forge-game/src/main/java/forge/ai/ComputerUtilMana.java +++ b/forge-game/src/main/java/forge/ai/ComputerUtilMana.java @@ -38,6 +38,7 @@ import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import forge.util.CollectionSuppliers; +import forge.util.TextUtil; import forge.util.maps.EnumMapOfLists; import forge.util.maps.MapOfLists; @@ -144,7 +145,6 @@ public class ComputerUtilMana { List paymentPlan = new ArrayList(); - String originalCost = cost.toString(false); ManaCostShard toPay = null; // Loop over mana needed while (!cost.isPaid()) { @@ -194,7 +194,7 @@ public class ComputerUtilMana { String manaProduced = toPay.isSnow() ? "S" : GameActionUtil.generatedMana(saPayment); manaProduced = AbilityManaPart.applyManaReplacement(saPayment, manaProduced); //System.out.println(manaProduced); - cost.payMultipleMana(manaProduced); + payMultipleMana(cost, manaProduced); // remove from available lists for (Collection kv : sourcesForShards.values()) { @@ -267,7 +267,7 @@ public class ComputerUtilMana { Set reflected = CardUtil.getReflectableManaColors(saPayment); for (byte c : MagicColor.WUBRG) { - if (toPay.canBePaidWithManaOfColor(c) && reflected.contains(MagicColor.toLongString(c))) { + if (ai.getManaPool().canPayForShardWithColor(toPay, c) && reflected.contains(MagicColor.toLongString(c))) { m.setExpressChoice(MagicColor.toShortString(c)); return; } @@ -278,7 +278,7 @@ public class ComputerUtilMana { colorChoice = toPay.getColorMask(); else { for (byte c : MagicColor.WUBRG) { - if (toPay.canBePaidWithManaOfColor(c)) { + if (ai.getManaPool().canPayForShardWithColor(toPay, c)) { colorChoice = c; break; } @@ -312,7 +312,7 @@ public class ComputerUtilMana { if (m.isComboMana()) { for (String s : m.getComboColors().split(" ")) { - if ("Any".equals(s) || toPay.canBePaidWithManaOfColor(MagicColor.fromName(s))) + if ("Any".equals(s) || ai.getManaPool().canPayForShardWithColor(toPay, MagicColor.fromName(s))) return true; } return false; @@ -321,7 +321,7 @@ public class ComputerUtilMana { Set reflected = CardUtil.getReflectableManaColors(ma); for (byte c : MagicColor.WUBRG) { - if (toPay.canBePaidWithManaOfColor(c) && reflected.contains(MagicColor.toLongString(c))) { + if (ai.getManaPool().canPayForShardWithColor(toPay, c) && reflected.contains(MagicColor.toLongString(c))) { m.setExpressChoice(MagicColor.toShortString(c)); return true; } @@ -392,7 +392,7 @@ public class ComputerUtilMana { byte colorMask = MagicColor.fromName(choice); if (abMana.canProduce(choice, manaAb) && testCost.isAnyPartPayableWith(colorMask)) { choiceString.append(choice); - testCost.payMultipleMana(choice); + payMultipleMana(testCost, choice); continue; } } @@ -401,7 +401,7 @@ public class ComputerUtilMana { // Loop over combo colors for (String color : comboColors) { if (testCost.isAnyPartPayableWith(MagicColor.fromName(color))) { - testCost.payMultipleMana(color); + payMultipleMana(testCost, color); if (nMana != 1) { choiceString.append(" "); } @@ -437,6 +437,39 @@ public class ComputerUtilMana { abMana.setExpressChoice(choiceString.toString()); } + /** + *

+ * payMultipleMana. + *

+ * @param testCost + * + * @param mana + * a {@link java.lang.String} object. + * @return a boolean. + */ + private final static String payMultipleMana(ManaCostBeingPaid testCost, String mana) { + List unused = new ArrayList(4); + for (String manaPart : TextUtil.split(mana, ' ')) { + if (StringUtils.isNumeric(manaPart)) { + for (int i = Integer.parseInt(manaPart); i > 0; i--) { + boolean wasNeeded = testCost.ai_payMana("1"); + if (!wasNeeded) { + unused.add(Integer.toString(i)); + break; + } + } + } + else { + String color = MagicColor.toShortString(manaPart); + boolean wasNeeded = testCost.ai_payMana(color); + if (!wasNeeded) { + unused.add(color); + } + } + } + return unused.isEmpty() ? null : StringUtils.join(unused, ' '); + } + /** * Find all mana sources. * @param manaAbilityMap @@ -467,7 +500,8 @@ public class ComputerUtilMana { } for (Entry kv : manaAbilityMap.entries()) { - if (shard.canBePaidWithManaOfColor(kv.getKey().byteValue())) { + // apply mana color change matrix here + if (ai.getManaPool().canPayForShardWithColor(shard, kv.getKey().byteValue())) { res.add(shard, kv.getValue()); } } diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 5e021fad0ef..9b2b7c1a608 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -1100,7 +1100,7 @@ public class CardFactoryUtil { byte colorCode = MagicColor.fromName(colorAbb); for(Card c0 : cards) { for(ManaCostShard sh : c0.getManaCost()){ - if (sh.canBePaidWithManaOfColor(colorCode)) + if ((sh.getColorMask() & colorCode) != 0) colorOcurrencices++; } } @@ -1112,7 +1112,7 @@ public class CardFactoryUtil { byte color2 = MagicColor.fromName(sq[2]); for(Card c0 : cc.getCardsIn(ZoneType.Battlefield)) { for (ManaCostShard sh : c0.getManaCost()) { - if (sh.canBePaidWithManaOfColor(color1) || sh.canBePaidWithManaOfColor(color2)) { + if ((sh.getColorMask() & (color1 | color2)) != 0) { colorOcurrencices++; } } diff --git a/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java b/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java index 145c0f8d3e0..c59683410a1 100644 --- a/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java +++ b/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import org.apache.commons.lang3.StringUtils; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -42,7 +41,6 @@ import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.staticability.StaticAbility; import forge.game.zone.ZoneType; -import forge.util.TextUtil; import forge.util.maps.EnumMapToAmount; import forge.util.maps.MapToAmount; @@ -215,7 +213,7 @@ public class ManaCostBeingPaid { return true; } } - else if (shard.canBePaidWithManaOfColor(colorMask)) { + else if (shardCanBePaidWithColor(shard, colorMask)) { return true; } } @@ -225,7 +223,7 @@ public class ManaCostBeingPaid { // isNeeded(String) still used by the Computer, might have problems activating Snow abilities public final boolean isAnyPartPayableWith(byte colorMask) { for (ManaCostShard shard : unpaidShards.keySet()) { - if (shard.canBePaidWithManaOfColor(colorMask)) { + if (shardCanBePaidWithColor(shard, colorMask)) { return true; } } @@ -245,38 +243,6 @@ public class ManaCostBeingPaid { return unpaidShards.isEmpty(); } - /** - *

- * payMultipleMana. - *

- * - * @param mana - * a {@link java.lang.String} object. - * @return a boolean. - */ - public final String payMultipleMana(String mana) { - List unused = new ArrayList(4); - for (String manaPart : TextUtil.split(mana, ' ')) { - if (StringUtils.isNumeric(manaPart)) { - for (int i = Integer.parseInt(manaPart); i > 0; i--) { - boolean wasNeeded = this.payMana("1"); - if (!wasNeeded) { - unused.add(Integer.toString(i)); - break; - } - } - } - else { - String color = MagicColor.toShortString(manaPart); - boolean wasNeeded = this.payMana(color); - if (!wasNeeded) { - unused.add(color); - } - } - } - return unused.isEmpty() ? null : StringUtils.join(unused, ' '); - } - public final void increaseColorlessMana(final int manaToAdd) { increaseShard(ManaCostShard.COLORLESS, manaToAdd); } @@ -314,7 +280,7 @@ public class ManaCostBeingPaid { * a {@link java.lang.String} object. * @return a boolean. */ - public final boolean payMana(final String mana) { + public final boolean ai_payMana(final String mana) { final byte colorMask = MagicColor.fromName(mana); if (!this.isAnyPartPayableWith(colorMask)) { //System.out.println("ManaCost : addMana() error, mana not needed - " + mana); @@ -325,7 +291,7 @@ public class ManaCostBeingPaid { Predicate predCanBePaid = new Predicate() { @Override public boolean apply(ManaCostShard ms) { - return ms.canBePaidWithManaOfColor(colorMask); + return shardCanBePaidWithColor(ms, colorMask); } }; @@ -408,9 +374,14 @@ public class ManaCostBeingPaid { } byte color = mana.getColorCode(); - return shard.canBePaidWithManaOfColor(color); + return shardCanBePaidWithColor(shard, color); } + private boolean shardCanBePaidWithColor(ManaCostShard shard, byte manaColor) { + // add color changing matrix here to support Daxos of Melethis + return shard.canBePaidWithManaOfColor(manaColor); + } + public final void combineManaCost(final ManaCost extra) { for (ManaCostShard shard : extra) { if (shard == ManaCostShard.X) { diff --git a/forge-game/src/main/java/forge/game/mana/ManaPool.java b/forge-game/src/main/java/forge/game/mana/ManaPool.java index dfa87fdbb8e..68e63e95c78 100644 --- a/forge-game/src/main/java/forge/game/mana/ManaPool.java +++ b/forge-game/src/main/java/forge/game/mana/ManaPool.java @@ -198,7 +198,7 @@ public class ManaPool { private List> selectManaToPayFor(final ManaCostShard shard, final SpellAbility saBeingPaidFor, String restriction) { final List> weightedOptions = new ArrayList>(); for (final Byte manaKey : this.floatingMana.keySet()) { - if (!shard.canBePaidWithManaOfColor(manaKey.byteValue())) { + if (!canPayForShardWithColor(shard, manaKey.byteValue())) { continue; } @@ -207,7 +207,7 @@ public class ManaPool { continue; } - boolean canPay = shard.canBePaidWithManaOfColor(thisMana.getColorCode()); + boolean canPay = canPayForShardWithColor(shard, thisMana.getColorCode()); if (!canPay || (shard.isSnow() && !thisMana.isSnow())) { continue; } @@ -415,4 +415,9 @@ public class ManaPool { Player p = sa.getActivatingPlayer(); p.getGame().fireEvent(new GameEventZone(ZoneType.Battlefield, p, EventValueChangeType.ComplexUpdate, null)); } + + public boolean canPayForShardWithColor(ManaCostShard shard, byte color) { + // add color changing manipulations here + return shard.canBePaidWithManaOfColor(color); + } } diff --git a/forge-gui/src/test/java/forge/card/mana/ManaPartTest.java b/forge-gui/src/test/java/forge/card/mana/ManaPartTest.java index 58d07632bfd..5572591c546 100644 --- a/forge-gui/src/test/java/forge/card/mana/ManaPartTest.java +++ b/forge-gui/src/test/java/forge/card/mana/ManaPartTest.java @@ -75,7 +75,7 @@ public class ManaPartTest { this.check(0.7, p1.isAnyPartPayableWith(MagicColor.RED)); this.check(0.8, p1.isAnyPartPayableWith((byte) 0)); - p1.payMana("U"); + p1.ai_payMana("U"); this.check(0.9, p1.isPaid()); this.check(0.91, !p1.isAnyPartPayableWith(MagicColor.RED)); @@ -89,7 +89,7 @@ public class ManaPartTest { this.check(1.4, !p2.isAnyPartPayableWith(MagicColor.RED)); this.check(1.5, !p2.isAnyPartPayableWith((byte) 0)); - p2.payMana("G"); + p2.ai_payMana("G"); this.check(2, p2.isPaid()); this.check(2.1, !p2.isAnyPartPayableWith(MagicColor.GREEN)); @@ -103,7 +103,7 @@ public class ManaPartTest { this.check(7, p4.isAnyPartPayableWith(MagicColor.RED)); this.check(8, p4.isAnyPartPayableWith((byte) 0)); - p4.payMana("B"); + p4.ai_payMana("B"); this.check(9, p4.isPaid()); this.check(9.1, !p4.isAnyPartPayableWith(MagicColor.RED)); @@ -118,7 +118,7 @@ public class ManaPartTest { this.check(14, !p5.isAnyPartPayableWith(MagicColor.RED)); this.check(15, !p5.isAnyPartPayableWith((byte) 0)); - p5.payMana("W"); + p5.ai_payMana("W"); this.check(16, p5.isPaid()); this.check(17, !p5.isAnyPartPayableWith(MagicColor.WHITE)); @@ -133,14 +133,14 @@ public class ManaPartTest { this.check(17.5, !p6.isAnyPartPayableWith(MagicColor.GREEN)); this.check(17.6, !p6.isAnyPartPayableWith((byte) 0)); - p6.payMana("R"); + p6.ai_payMana("R"); this.check(17.7, p6.isPaid()); this.check(17.8, !p6.isAnyPartPayableWith(MagicColor.RED)); final ManaCostBeingPaid p7 = new ManaCostBeingPaid("1 G G"); - p7.payMana("G"); + p7.ai_payMana("G"); this.check(18.1, p7.isAnyPartPayableWith(MagicColor.GREEN)); this.check(18.2, p7.isAnyPartPayableWith(MagicColor.WHITE)); @@ -149,8 +149,8 @@ public class ManaPartTest { this.check(18.5, p7.isAnyPartPayableWith(MagicColor.RED)); this.check(18.6, p7.isAnyPartPayableWith((byte) 0)); - p7.payMana("1"); - p7.payMana("G"); + p7.ai_payMana("1"); + p7.ai_payMana("G"); this.check(18.7, p7.isPaid()); @@ -173,8 +173,8 @@ public class ManaPartTest { this.check(20.3, !p9.isAnyPartPayableWith(MagicColor.BLUE)); - p9.payMana("G"); - p9.payMana("G"); + p9.ai_payMana("G"); + p9.ai_payMana("G"); this.check(20.4, p9.isPaid()); @@ -187,9 +187,9 @@ public class ManaPartTest { this.check(21.3, !p10.isAnyPartPayableWith(MagicColor.RED)); - p10.payMana("G"); - p10.payMana("G"); - p10.payMana("G"); + p10.ai_payMana("G"); + p10.ai_payMana("G"); + p10.ai_payMana("G"); this.check(21.4, p10.isPaid()); @@ -202,10 +202,10 @@ public class ManaPartTest { this.check(22.3, !p11.isAnyPartPayableWith(MagicColor.RED)); - p11.payMana("G"); - p11.payMana("G"); - p11.payMana("G"); - p11.payMana("G"); + p11.ai_payMana("G"); + p11.ai_payMana("G"); + p11.ai_payMana("G"); + p11.ai_payMana("G"); this.check(22.4, p11.isPaid()); @@ -217,7 +217,7 @@ public class ManaPartTest { this.check(23.2, p12.isAnyPartPayableWith(MagicColor.GREEN)); this.check(23.3, !p12.isAnyPartPayableWith(MagicColor.RED)); - p12.payMana("G"); + p12.ai_payMana("G"); this.check(23.4, p12.isPaid()); @@ -229,7 +229,7 @@ public class ManaPartTest { this.check(24.2, p13.isAnyPartPayableWith(MagicColor.GREEN)); this.check(24.3, !p13.isAnyPartPayableWith(MagicColor.BLUE)); - p13.payMana("W"); + p13.ai_payMana("W"); this.check(24.4, p13.isPaid()); @@ -241,16 +241,16 @@ public class ManaPartTest { this.check(25.2, p14.isAnyPartPayableWith(MagicColor.GREEN)); this.check(25.3, p14.isAnyPartPayableWith(MagicColor.BLUE)); - p14.payMana("1"); - p14.payMana("1"); - p14.payMana("1"); + p14.ai_payMana("1"); + p14.ai_payMana("1"); + p14.ai_payMana("1"); this.check(25.4, p14.isAnyPartPayableWith(MagicColor.WHITE)); this.check(25.5, p14.isAnyPartPayableWith(MagicColor.GREEN)); this.check(25.6, !p14.isAnyPartPayableWith(MagicColor.BLUE)); - p14.payMana("G"); - p14.payMana("W"); + p14.ai_payMana("G"); + p14.ai_payMana("W"); this.check(25.7, p14.isPaid()); @@ -265,80 +265,80 @@ public class ManaPartTest { this.check(26.2, p15.isAnyPartPayableWith(MagicColor.GREEN)); this.check(26.3, p15.isAnyPartPayableWith(MagicColor.BLUE)); - p15.payMana("1"); - p15.payMana("1"); - p15.payMana("1"); - p15.payMana("1"); + p15.ai_payMana("1"); + p15.ai_payMana("1"); + p15.ai_payMana("1"); + p15.ai_payMana("1"); this.check(26.4, p15.isPaid()); final ManaCostBeingPaid p16 = new ManaCostBeingPaid("10"); - p16.payMana("G"); - p16.payMana("W"); - p16.payMana("R"); - p16.payMana("U"); - p16.payMana("B"); + p16.ai_payMana("G"); + p16.ai_payMana("W"); + p16.ai_payMana("R"); + p16.ai_payMana("U"); + p16.ai_payMana("B"); - p16.payMana("1"); + p16.ai_payMana("1"); - p16.payMana("W"); - p16.payMana("R"); - p16.payMana("U"); - p16.payMana("B"); + p16.ai_payMana("W"); + p16.ai_payMana("R"); + p16.ai_payMana("U"); + p16.ai_payMana("B"); this.check(27, p16.isPaid()); final ManaCostBeingPaid p17 = new ManaCostBeingPaid("12 G GW"); for (int i = 0; i < 12; i++) { - p17.payMana("R"); + p17.ai_payMana("R"); } - p17.payMana("G"); - p17.payMana("W"); + p17.ai_payMana("G"); + p17.ai_payMana("W"); this.check(28, p17.isPaid()); final ManaCostBeingPaid p18 = new ManaCostBeingPaid("2 W B U R G"); for (int i = 0; i < 1; i++) { - p18.payMana("R"); + p18.ai_payMana("R"); } for (int i = 0; i < 2; i++) { - p18.payMana("1"); + p18.ai_payMana("1"); } for (int i = 0; i < 1; i++) { - p18.payMana("G"); - p18.payMana("W"); - p18.payMana("B"); - p18.payMana("U"); + p18.ai_payMana("G"); + p18.ai_payMana("W"); + p18.ai_payMana("B"); + p18.ai_payMana("U"); } this.check(29, p18.isPaid()); final ManaCostBeingPaid p19 = new ManaCostBeingPaid("W B U R G W"); - p19.payMana("R"); - p19.payMana("G"); - p19.payMana("B"); - p19.payMana("U"); + p19.ai_payMana("R"); + p19.ai_payMana("G"); + p19.ai_payMana("B"); + p19.ai_payMana("U"); - p19.payMana("W"); - p19.payMana("W"); + p19.ai_payMana("W"); + p19.ai_payMana("W"); this.check(30, p19.isPaid()); final ManaCostBeingPaid p20 = new ManaCostBeingPaid("W B U R G W B U R G"); for (int i = 0; i < 2; i++) { - p20.payMana("W"); - p20.payMana("R"); - p20.payMana("G"); - p20.payMana("B"); - p20.payMana("U"); + p20.ai_payMana("W"); + p20.ai_payMana("R"); + p20.ai_payMana("G"); + p20.ai_payMana("B"); + p20.ai_payMana("U"); } this.check(31, p20.isPaid()); @@ -346,31 +346,31 @@ public class ManaPartTest { final ManaCostBeingPaid p21 = new ManaCostBeingPaid("2 W B U R G W B U R G G"); for (int i = 0; i < 2; i++) { - p21.payMana("W"); - p21.payMana("R"); - p21.payMana("G"); - p21.payMana("B"); - p21.payMana("U"); + p21.ai_payMana("W"); + p21.ai_payMana("R"); + p21.ai_payMana("G"); + p21.ai_payMana("B"); + p21.ai_payMana("U"); } - p21.payMana("1"); - p21.payMana("1"); - p21.payMana("G"); + p21.ai_payMana("1"); + p21.ai_payMana("1"); + p21.ai_payMana("G"); this.check(32, p21.isPaid()); final ManaCostBeingPaid p22 = new ManaCostBeingPaid("1 B R"); - p22.payMana("B"); - p22.payMana("1"); - p22.payMana("R"); + p22.ai_payMana("B"); + p22.ai_payMana("1"); + p22.ai_payMana("R"); this.check(33, p22.isPaid()); final ManaCostBeingPaid p23 = new ManaCostBeingPaid("B R"); - p23.payMana("B"); - p23.payMana("R"); + p23.ai_payMana("B"); + p23.ai_payMana("R"); this.check(34, p23.isPaid()); @@ -378,36 +378,36 @@ public class ManaPartTest { this.check(35, p24.isAnyPartPayableWith(MagicColor.GREEN)); - p24.payMana("B"); + p24.ai_payMana("B"); this.check(36, p24.toString().equals("{2/B}{2/B}")); - p24.payMana("B"); + p24.ai_payMana("B"); this.check(37, p24.toString().equals("{2/B}")); - p24.payMana("B"); + p24.ai_payMana("B"); this.check(38, p24.isPaid()); final ManaCostBeingPaid p25 = new ManaCostBeingPaid("2/G"); - p25.payMana("1"); + p25.ai_payMana("1"); this.check(39, p25.toString().equals("{1}")); - p25.payMana("W"); + p25.ai_payMana("W"); this.check(40, p25.isPaid()); final ManaCostBeingPaid p27 = new ManaCostBeingPaid("{2/R}{2/R}"); - p27.payMana("1"); + p27.ai_payMana("1"); this.check(41, p27.toString().equals("{2/R}{1}")); - p27.payMana("W"); + p27.ai_payMana("W"); this.check(42, p27.toString().equals("{2/R}")); final ManaCostBeingPaid p26 = new ManaCostBeingPaid("2/W 2/W"); for (int i = 0; i < 4; i++) { this.check(43, !p26.isPaid()); - p26.payMana("1"); + p26.ai_payMana("1"); } this.check(44, p26.isPaid()); @@ -415,11 +415,11 @@ public class ManaPartTest { final ManaCostBeingPaid p28 = new ManaCostBeingPaid("2/W 2/B 2/U 2/R 2/G"); this.check(45, !p28.isPaid()); - p28.payMana("B"); - p28.payMana("R"); - p28.payMana("G"); - p28.payMana("W"); - p28.payMana("U"); + p28.ai_payMana("B"); + p28.ai_payMana("R"); + p28.ai_payMana("G"); + p28.ai_payMana("W"); + p28.ai_payMana("U"); this.check(45.1, p28.isPaid(), p28);