From 27bea843a3a31eefbaccb08684ec42b51cc23589 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 6 Jun 2024 15:43:45 -0400 Subject: [PATCH] [M3C] Implement Ulalek, Fused Atrocity and new colorless hybrid mana (#12273) * improved by (#12415) * Added symbol downloads for new colorless hybrid --------- Co-authored-by: Alexander Novotny Co-authored-by: Oleg Agafonov --- .../org/mage/card/arcane/ManaSymbols.java | 10 +- .../card/dl/sources/GathererSymbols.java | 1 + .../dl/sources/ScryfallSymbolsSource.java | 1 + .../java/mage/player/ai/ComputerPlayer.java | 28 ++++- .../src/mage/cards/c/CharmedPendant.java | 2 + .../src/mage/cards/u/UlalekFusedAtrocity.java | 101 +++++++++++++++++ .../mage/sets/ModernHorizons3Commander.java | 1 + Mage/src/main/java/mage/ManaSymbol.java | 24 +++- .../costs/mana/ColorlessHybridManaCost.java | 106 ++++++++++++++++++ .../abilities/costs/mana/HybridManaCost.java | 8 +- .../abilities/costs/mana/ManaCostImpl.java | 25 +++-- .../abilities/costs/mana/ManaCostsImpl.java | 12 ++ Mage/src/main/java/mage/util/ManaUtil.java | 15 +++ 13 files changed, 306 insertions(+), 28 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/u/UlalekFusedAtrocity.java create mode 100644 Mage/src/main/java/mage/abilities/costs/mana/ColorlessHybridManaCost.java diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java index c026519f22c..19c0435a3e4 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java @@ -73,12 +73,12 @@ public final class ManaSymbols { private static final String[] symbols = new String[]{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", - "B", "BG", "BR", "BP", "2B", - "G", "GU", "GW", "GP", "2G", - "R", "RG", "RW", "RP", "2R", + "B", "BG", "BR", "BP", "2B", "CB", + "G", "GU", "GW", "GP", "2G", "CG", + "R", "RG", "RW", "RP", "2R", "CR", "S", "T", "Q", - "U", "UB", "UR", "UP", "2U", - "W", "WB", "WU", "WP", "2W", + "U", "UB", "UR", "UP", "2U", "CU", + "W", "WB", "WU", "WP", "2W", "CW", "X", "C", "E", "P", "BGP", "BRP", "GUP", "GWP", "RGP", "RWP", "UBP", "URP", "WBP", "WUP"}; diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSymbols.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSymbols.java index fa073dda3eb..23f28458cdc 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSymbols.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSymbols.java @@ -33,6 +33,7 @@ public class GathererSymbols implements Iterable { "W/U", "U/B", "B/R", "R/G", "G/W", "W/B", "U/R", "B/G", "R/W", "G/U", "W/U/P", "U/B/P", "B/R/P", "R/G/P", "G/W/P", "W/B/P", "U/R/P", "B/G/P", "R/W/P", "G/U/P", "2/W", "2/U", "2/B", "2/R", "2/G", + "C/W", "C/U", "C/B", "C/R", "C/G", "WP", "UP", "BP", "RP", "GP", "X", "S", "T", "Q", "C", "E", "P"}; private static final int minNumeric = 0, maxNumeric = 16; diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallSymbolsSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallSymbolsSource.java index 5ad0dbffd2f..e16892e3eb3 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallSymbolsSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallSymbolsSource.java @@ -45,6 +45,7 @@ public class ScryfallSymbolsSource implements Iterable { "W/U", "U/B", "B/R", "R/G", "G/W", "W/B", "U/R", "B/G", "R/W", "G/U", "W/U/P", "U/B/P", "B/R/P", "R/G/P", "G/W/P", "W/B/P", "U/R/P", "B/G/P", "R/W/P", "G/U/P", "2/W", "2/U", "2/B", "2/R", "2/G", + "C/W", "C/U", "C/B", "C/R", "C/G", "WP", "UP", "BP", "RP", "GP", "X", "S", "T", "Q", "C", "E", "P"}; diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index ba5a89bec46..442ee622bed 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -1652,6 +1652,26 @@ public class ComputerPlayer extends PlayerImpl { } } } + // pay colorless - more restrictive than hybrid (think of it like colored) + for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) { + if (cost instanceof ColorlessManaCost) { + for (Mana netMana : manaAbility.getNetMana(game)) { + if (cost.testPay(netMana) || hasApprovingObject) { + if (netMana instanceof ConditionalMana + && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { + continue; + } + if (hasApprovingObject && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, + manaAbility, mageObject, game)) { + continue; + } + if (activateAbility(manaAbility, game)) { + return true; + } + } + } + } + } // then pay hybrid for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) { if (cost instanceof HybridManaCost) { @@ -1670,9 +1690,9 @@ public class ComputerPlayer extends PlayerImpl { } } } - // then pay mono hybrid + // then pay colorless hybrid - more restrictive than mono hybrid for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) { - if (cost instanceof MonoHybridManaCost) { + if (cost instanceof ColorlessHybridManaCost) { for (Mana netMana : manaAbility.getNetMana(game)) { if (cost.testPay(netMana) || hasApprovingObject) { if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { @@ -1688,9 +1708,9 @@ public class ComputerPlayer extends PlayerImpl { } } } - // pay colorless + // then pay mono hybrid for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) { - if (cost instanceof ColorlessManaCost) { + if (cost instanceof MonoHybridManaCost) { for (Mana netMana : manaAbility.getNetMana(game)) { if (cost.testPay(netMana) || hasApprovingObject) { if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { diff --git a/Mage.Sets/src/mage/cards/c/CharmedPendant.java b/Mage.Sets/src/mage/cards/c/CharmedPendant.java index 247ce039283..5bd34c9bcb9 100644 --- a/Mage.Sets/src/mage/cards/c/CharmedPendant.java +++ b/Mage.Sets/src/mage/cards/c/CharmedPendant.java @@ -143,6 +143,8 @@ class CharmedPendantManaEffect extends ManaEffect { } if (manaCost instanceof MonoHybridManaCost) { newManaCosts.add(new ColoredManaCost(((MonoHybridManaCost) manaCost).getManaColor())); + } else if (manaCost instanceof ColorlessHybridManaCost) { + newManaCosts.add(new ColoredManaCost(((ColorlessHybridManaCost) manaCost).getManaColor())); } else { newManaCosts.add(manaCost.copy()); } diff --git a/Mage.Sets/src/mage/cards/u/UlalekFusedAtrocity.java b/Mage.Sets/src/mage/cards/u/UlalekFusedAtrocity.java new file mode 100644 index 00000000000..48f81bb2be3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UlalekFusedAtrocity.java @@ -0,0 +1,101 @@ +package mage.cards.u; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.costs.mana.ColorlessManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.keyword.DevoidAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterSpell; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; +import mage.util.CardUtil; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public final class UlalekFusedAtrocity extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("an Eldrazi spell"); + + static { + filter.add(SubType.ELDRAZI.getPredicate()); + } + + public UlalekFusedAtrocity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{C/W}{C/U}{C/B}{C/R}{C/G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.ELDRAZI); + this.power = new MageInt(2); + this.toughness = new MageInt(5); + + // Devoid + this.addAbility(new DevoidAbility(this.color)); + + // Whenever you cast an Eldrazi spell, you may pay {C}{C}. If you do, copy all spells you control, then copy all other activated and triggered abilities you control. You may choose new targets for the copies. + this.addAbility(new SpellCastControllerTriggeredAbility( + new DoIfCostPaid(new UlalekFusedAtrocityEffect(), new ColorlessManaCost(2)), filter, false + )); + } + + private UlalekFusedAtrocity(final UlalekFusedAtrocity card) { + super(card); + } + + @Override + public UlalekFusedAtrocity copy() { + return new UlalekFusedAtrocity(this); + } +} + +class UlalekFusedAtrocityEffect extends OneShotEffect { + + UlalekFusedAtrocityEffect() { + super(Outcome.Benefit); + staticText = "copy all spells you control, then copy all other activated " + + "and triggered abilities you control. You may choose new targets for the copies"; + } + + private UlalekFusedAtrocityEffect(final UlalekFusedAtrocityEffect effect) { + super(effect); + } + + @Override + public UlalekFusedAtrocityEffect copy() { + return new UlalekFusedAtrocityEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + List spells = CardUtil.castStream(game.getStack().stream(), Spell.class) + .filter(spell -> spell.isControlledBy(source.getControllerId())) + .collect(Collectors.toList()); + for (Spell spell : spells) { + spell.createCopyOnStack(game, source, source.getControllerId(), true); + } + List abilities = game + .getStack() + .stream() + .filter(obj -> !(obj instanceof Spell)) + .filter(obj -> obj.isControlledBy(source.getControllerId())) + .filter(obj -> !obj.getId().equals(source.getId())) + .collect(Collectors.toList()); + for (StackObject obj : abilities) { + obj.createCopyOnStack(game, source, source.getControllerId(), true); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java b/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java index 3814c53b33f..a80f9160c59 100644 --- a/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java +++ b/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java @@ -224,6 +224,7 @@ public final class ModernHorizons3Commander extends ExpansionSet { cards.add(new SetCardInfo("Shivan Reef", 375, Rarity.RARE, mage.cards.s.ShivanReef.class)); cards.add(new SetCardInfo("Shrine of the Forsaken Gods", 376, Rarity.RARE, mage.cards.s.ShrineOfTheForsakenGods.class)); cards.add(new SetCardInfo("Siege-Gang Lieutenant", 61, Rarity.RARE, mage.cards.s.SiegeGangLieutenant.class)); + cards.add(new SetCardInfo("Ulalek, Fused Atrocity", 4, Rarity.MYTHIC, mage.cards.u.UlalekFusedAtrocity.class)); cards.add(new SetCardInfo("Sifter of Skulls", 203, Rarity.RARE, mage.cards.s.SifterOfSkulls.class)); cards.add(new SetCardInfo("Simic Growth Chamber", 377, Rarity.COMMON, mage.cards.s.SimicGrowthChamber.class)); cards.add(new SetCardInfo("Simic Guildgate", 378, Rarity.COMMON, mage.cards.s.SimicGuildgate.class)); diff --git a/Mage/src/main/java/mage/ManaSymbol.java b/Mage/src/main/java/mage/ManaSymbol.java index ca46df5cb13..41b05e61970 100644 --- a/Mage/src/main/java/mage/ManaSymbol.java +++ b/Mage/src/main/java/mage/ManaSymbol.java @@ -1,15 +1,16 @@ package mage; - /** * Enum representing the mana symbols. *

- * 107.4. The mana symbols are {W}, {U}, {B}, {R}, {G}, and {X}; the numerals - * {0}, {1}, {2}, {3}, {4}, and so on; the hybrid symbols {W/U}, {W/B}, {U/B}, - * {U/R}, {B/R}, {B/G}, {R/G}, {R/W}, {G/W}, and {G/U}; the monocolored hybrid - * symbols {2/W}, {2/U}, {2/B}, {2/R}, and {2/G}; the Phyrexian mana symbols - * {W/P}, {U/P}, {B/P}, {R/P}, and {G/P}; and the snow symbol {S}. + * 107.4. The mana symbols are {W}, {U}, {B}, {R}, {G}, and {C}; the numerical symbols + * {0}, {1}, {2}, {3}, {4}, and so on; the variable symbol {X}; the hybrid symbols + * {W/U}, {W/B}, {U/B}, {U/R}, {B/R}, {B/G}, {R/G}, {R/W}, {G/W}, and {G/U}; + * the monocolored hybrid symbols {2/W}, {2/U}, {2/B}, {2/R}, and {2/G}; + * the Phyrexian mana symbols {W/P}, {U/P}, {B/P}, {R/P}, and {G/P}; + * the hybrid Phyrexian symbols {W/U/P}, {W/B/P}, {U/B/P}, {U/R/P}, + * {B/R/P}, {B/G/P}, {R/G/P}, {R/W/P}, {G/W/P}, and {G/U/P}; and the snow mana symbol {S}. *

* 107.4a. There are five primary colored mana symbols: {W} is white, {U} blue, * {B} black, {R} red, and {G} green. These symbols are used to represent colored @@ -61,6 +62,7 @@ public enum ManaSymbol { B("{B}", Type.PRIMARY, Type.COLORED, Type.MONOCOLORED), R("{R}", Type.PRIMARY, Type.COLORED, Type.MONOCOLORED), G("{G}", Type.PRIMARY, Type.COLORED, Type.MONOCOLORED), + C("{C}", Type.COLORLESS), X("{X}", Type.GENERIC, Type.COLORLESS), NUMERIC("{N/A}", Type.GENERIC, Type.COLORLESS), HYBRID_WU("{W/U}", W, U, Type.HYBRID, Type.COLORED), @@ -73,11 +75,21 @@ public enum ManaSymbol { HYBRID_RW("{R/W}", R, W, Type.HYBRID, Type.COLORED), HYBRID_GW("{G/W}", G, W, Type.HYBRID, Type.COLORED), HYBRID_GU("{G/U}", G, U, Type.HYBRID, Type.COLORED), + HYBRID_CW("{W/U}", W, U, Type.HYBRID, Type.COLORED), + HYBRID_CU("{W/U}", W, U, Type.HYBRID, Type.COLORED), + HYBRID_CB("{W/B}", W, B, Type.HYBRID, Type.COLORED), + HYBRID_CR("{U/R}", U, R, Type.HYBRID, Type.COLORED), + HYBRID_CG("{B/G}", B, G, Type.HYBRID, Type.COLORED), MONOCOLORED_HYBRID_W("{2/W}", W, Type.HYBRID, Type.MONOCOLORED, Type.COLORED), MONOCOLORED_HYBRID_U("{2/U}", U, Type.HYBRID, Type.MONOCOLORED, Type.COLORED), MONOCOLORED_HYBRID_B("{2/B}", B, Type.HYBRID, Type.MONOCOLORED, Type.COLORED), MONOCOLORED_HYBRID_R("{2/R}", R, Type.HYBRID, Type.MONOCOLORED, Type.COLORED), MONOCOLORED_HYBRID_G("{2/G}", G, Type.HYBRID, Type.MONOCOLORED, Type.COLORED), + COLORLESS_HYBRID_W("{C/W}", C, W, Type.HYBRID, Type.MONOCOLORED, Type.COLORED), + COLORLESS_HYBRID_U("{C/U}", C, U, Type.HYBRID, Type.MONOCOLORED, Type.COLORED), + COLORLESS_HYBRID_B("{C/B}", C, B, Type.HYBRID, Type.MONOCOLORED, Type.COLORED), + COLORLESS_HYBRID_R("{C/R}", C, R, Type.HYBRID, Type.MONOCOLORED, Type.COLORED), + COLORLESS_HYBRID_G("{C/G}", C, G, Type.HYBRID, Type.MONOCOLORED, Type.COLORED), PHYREXIAN_W("{W/P}", W, Type.PHYREXIAN, Type.COLORED, Type.MONOCOLORED), PHYREXIAN_G("{G/P}", G, Type.PHYREXIAN, Type.COLORED, Type.MONOCOLORED), PHYREXIAN_R("{R/P}", R, Type.PHYREXIAN, Type.COLORED, Type.MONOCOLORED), diff --git a/Mage/src/main/java/mage/abilities/costs/mana/ColorlessHybridManaCost.java b/Mage/src/main/java/mage/abilities/costs/mana/ColorlessHybridManaCost.java new file mode 100644 index 00000000000..ff5e6e300bb --- /dev/null +++ b/Mage/src/main/java/mage/abilities/costs/mana/ColorlessHybridManaCost.java @@ -0,0 +1,106 @@ +package mage.abilities.costs.mana; + +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.constants.ColoredManaSymbol; +import mage.game.Game; +import mage.players.ManaPool; + +import java.util.ArrayList; +import java.util.List; + +public class ColorlessHybridManaCost extends ManaCostImpl { + + private final ColoredManaSymbol manaColor; + + public ColorlessHybridManaCost(ColoredManaSymbol manaColor) { + this.manaColor = manaColor; + this.cost = new Mana(manaColor); + this.cost.add(Mana.ColorlessMana(1)); + addColoredOption(manaColor); + options.add(Mana.ColorlessMana(1)); + } + + public ColorlessHybridManaCost(ColorlessHybridManaCost manaCost) { + super(manaCost); + this.manaColor = manaCost.manaColor; + } + + @Override + public int manaValue() { + return 1; + } + + @Override + public boolean isPaid() { + return paid || isColoredPaid(this.manaColor) || isColorlessPaid(1); + } + + @Override + public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) { + // Assign colorless first in an attempt to avoid things like pain lands and talismans causing damage + if (!assignColorless(ability, game, pool, 1, costToPay)) { + assignColored(ability, game, pool, manaColor, costToPay); + } + } + + @Override + public String getText() { + return "{C/" + manaColor.toString() + '}'; + } + + @Override + public ColorlessHybridManaCost getUnpaid() { + return this; + } + + @Override + public boolean testPay(Mana testMana) { + switch (manaColor) { + case B: + if (testMana.getBlack() > 0) { + return true; + } + case U: + if (testMana.getBlue() > 0) { + return true; + } + case R: + if (testMana.getRed() > 0) { + return true; + } + case W: + if (testMana.getWhite() > 0) { + return true; + } + case G: + if (testMana.getGreen() > 0) { + return true; + } + } + return testMana.getColorless() > 0; + } + + @Override + public ColorlessHybridManaCost copy() { + return new ColorlessHybridManaCost(this); + } + + @Override + public boolean containsColor(ColoredManaSymbol coloredManaSymbol) { + return manaColor == coloredManaSymbol; + } + + public ColoredManaSymbol getManaColor() { + return manaColor; + } + + @Override + public List getManaOptions() { + List manaList = new ArrayList<>(); + manaList.add(new Mana(manaColor)); + manaList.add(Mana.ColorlessMana(1)); + return manaList; + } +} diff --git a/Mage/src/main/java/mage/abilities/costs/mana/HybridManaCost.java b/Mage/src/main/java/mage/abilities/costs/mana/HybridManaCost.java index 67d6c145b06..b84929e1a55 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/HybridManaCost.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/HybridManaCost.java @@ -18,7 +18,7 @@ public class HybridManaCost extends ManaCostImpl { public HybridManaCost(ColoredManaSymbol mana1, ColoredManaSymbol mana2) { this.mana1 = mana1; this.mana2 = mana2; - this.cost = new Mana(mana1); + this.cost = mana1 == null ? Mana.ColorlessMana(1) : new Mana(mana1); this.cost.add(new Mana(mana2)); addColoredOption(mana1); addColoredOption(mana2); @@ -42,7 +42,7 @@ public class HybridManaCost extends ManaCostImpl { @Override public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) { - if (assignColored(ability, game, pool, this.mana1, costToPay)) { + if (this.mana1 != null && assignColored(ability, game, pool, this.mana1, costToPay)) { return; } assignColored(ability, game, pool, this.mana2, costToPay); @@ -81,6 +81,10 @@ public class HybridManaCost extends ManaCostImpl { if (testMana.getGreen() > 0 || testMana.getAny() > 0) { return true; } + default: + if (testMana.getColorless() > 0) { + return true; + } } switch (mana2) { case B: diff --git a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java index cde1c26715c..3b2d1aa87b1 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java @@ -151,14 +151,15 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { return false; } - protected void assignColorless(Ability ability, Game game, ManaPool pool, int mana, Cost costToPay) { + protected boolean assignColorless(Ability ability, Game game, ManaPool pool, int mana, Cost costToPay) { int conditionalCount = pool.getConditionalCount(ability, game, null, costToPay); - while (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0)) { - if (pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay, usedManaToPay)) { - this.payment.increaseColorless(); - } - break; + if (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0) + && pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay, usedManaToPay)) { + this.payment.increaseColorless(); + return true; } + + return false; } protected boolean assignGeneric(Ability ability, Game game, ManaPool pool, int mana, FilterMana filterMana, Cost costToPay) { @@ -284,19 +285,21 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { switch (symbol) { case B: this.options.add(Mana.BlackMana(1)); - break; + return; case U: this.options.add(Mana.BlueMana(1)); - break; + return; case W: this.options.add(Mana.WhiteMana(1)); - break; + return; case R: this.options.add(Mana.RedMana(1)); - break; + return; case G: this.options.add(Mana.GreenMana(1)); - break; + return; + default: + this.options.add(Mana.ColorlessMana(1)); } } diff --git a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java index ba7e5b03995..849596e9d49 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java @@ -348,6 +348,16 @@ public class ManaCostsImpl extends ArrayList implements M } } + // Colorless hybrid + for (ManaCost cost : this) { + if (!cost.isPaid() && cost instanceof ColorlessHybridManaCost) { + cost.assignPayment(game, ability, pool, costToPay); + if (pool.isEmpty()) { + return; + } + } + } + // monohybrid // try to pay colored part for (ManaCost cost : this) { @@ -492,6 +502,8 @@ public class ManaCostsImpl extends ArrayList implements M ManaCost cost; if (without.length() == 1) { cost = new ColoredManaCost(ColoredManaSymbol.lookup(without.charAt(0))); + } else if (without.charAt(0) == 'C') { + cost = new ColorlessHybridManaCost(ColoredManaSymbol.lookup(without.charAt(2))); } else { cost = new HybridManaCost(ColoredManaSymbol.lookup(without.charAt(0)), ColoredManaSymbol.lookup(without.charAt(2))); } diff --git a/Mage/src/main/java/mage/util/ManaUtil.java b/Mage/src/main/java/mage/util/ManaUtil.java index 6752e6c426f..21b1f9fb01b 100644 --- a/Mage/src/main/java/mage/util/ManaUtil.java +++ b/Mage/src/main/java/mage/util/ManaUtil.java @@ -261,6 +261,9 @@ public final class ManaUtil { } else if (symbols.contains(ManaSymbol.HYBRID_WB)) { chosenManaAbilityForHybrid = ability; countColored.add(ManaSymbol.HYBRID_WB); + } else if (symbols.contains(ManaSymbol.HYBRID_CB)) { + chosenManaAbilityForHybrid = ability; + countColored.add(ManaSymbol.HYBRID_CB); } } @@ -282,6 +285,9 @@ public final class ManaUtil { } else if (symbols.contains(ManaSymbol.HYBRID_UR)) { chosenManaAbilityForHybrid = ability; countColored.add(ManaSymbol.HYBRID_UR); + } else if (symbols.contains(ManaSymbol.HYBRID_CR)) { + chosenManaAbilityForHybrid = ability; + countColored.add(ManaSymbol.HYBRID_CR); } } return chosenManaAbilityForHybrid; @@ -302,6 +308,9 @@ public final class ManaUtil { } else if (symbols.contains(ManaSymbol.HYBRID_GU)) { chosenManaAbilityForHybrid = ability; countColored.add(ManaSymbol.HYBRID_GU); + } else if (symbols.contains(ManaSymbol.HYBRID_CU)) { + chosenManaAbilityForHybrid = ability; + countColored.add(ManaSymbol.HYBRID_CU); } } return chosenManaAbilityForHybrid; @@ -322,6 +331,9 @@ public final class ManaUtil { } else if (symbols.contains(ManaSymbol.HYBRID_RW)) { chosenManaAbilityForHybrid = ability; countColored.add(ManaSymbol.HYBRID_RW); + } else if (symbols.contains(ManaSymbol.HYBRID_CW)) { + chosenManaAbilityForHybrid = ability; + countColored.add(ManaSymbol.HYBRID_CW); } } return chosenManaAbilityForHybrid; @@ -342,6 +354,9 @@ public final class ManaUtil { } else if (symbols.contains(ManaSymbol.HYBRID_RG)) { chosenManaAbilityForHybrid = ability; countColored.add(ManaSymbol.HYBRID_RG); + } else if (symbols.contains(ManaSymbol.HYBRID_CG)) { + chosenManaAbilityForHybrid = ability; + countColored.add(ManaSymbol.HYBRID_CG); } } return chosenManaAbilityForHybrid;