[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 <alexander_novo@mail.tmcc.edu>
Co-authored-by: Oleg Agafonov <jaydi85@gmail.com>
This commit is contained in:
Evan Kranzler 2024-06-06 15:43:45 -04:00 committed by GitHub
parent 1b2de47e78
commit 27bea843a3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 306 additions and 28 deletions

View file

@ -73,12 +73,12 @@ public final class ManaSymbols {
private static final String[] symbols = new String[]{ private static final String[] symbols = new String[]{
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
"B", "BG", "BR", "BP", "2B", "B", "BG", "BR", "BP", "2B", "CB",
"G", "GU", "GW", "GP", "2G", "G", "GU", "GW", "GP", "2G", "CG",
"R", "RG", "RW", "RP", "2R", "R", "RG", "RW", "RP", "2R", "CR",
"S", "T", "Q", "S", "T", "Q",
"U", "UB", "UR", "UP", "2U", "U", "UB", "UR", "UP", "2U", "CU",
"W", "WB", "WU", "WP", "2W", "W", "WB", "WU", "WP", "2W", "CW",
"X", "C", "E", "P", "X", "C", "E", "P",
"BGP", "BRP", "GUP", "GWP", "RGP", "RWP", "UBP", "URP", "WBP", "WUP"}; "BGP", "BRP", "GUP", "GWP", "RGP", "RWP", "UBP", "URP", "WBP", "WUP"};

View file

@ -33,6 +33,7 @@ public class GathererSymbols implements Iterable<DownloadJob> {
"W/U", "U/B", "B/R", "R/G", "G/W", "W/B", "U/R", "B/G", "R/W", "G/U", "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", "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", "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", "WP", "UP", "BP", "RP", "GP",
"X", "S", "T", "Q", "C", "E", "P"}; "X", "S", "T", "Q", "C", "E", "P"};
private static final int minNumeric = 0, maxNumeric = 16; private static final int minNumeric = 0, maxNumeric = 16;

View file

@ -45,6 +45,7 @@ public class ScryfallSymbolsSource implements Iterable<DownloadJob> {
"W/U", "U/B", "B/R", "R/G", "G/W", "W/B", "U/R", "B/G", "R/W", "G/U", "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", "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", "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", "WP", "UP", "BP", "RP", "GP",
"X", "S", "T", "Q", "C", "E", "P"}; "X", "S", "T", "Q", "C", "E", "P"};

View file

@ -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 // then pay hybrid
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) { for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
if (cost instanceof HybridManaCost) { 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)) { for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
if (cost instanceof MonoHybridManaCost) { if (cost instanceof ColorlessHybridManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) { for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || hasApprovingObject) { if (cost.testPay(netMana) || hasApprovingObject) {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { 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)) { for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
if (cost instanceof ColorlessManaCost) { if (cost instanceof MonoHybridManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) { for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || hasApprovingObject) { if (cost.testPay(netMana) || hasApprovingObject) {
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {

View file

@ -143,6 +143,8 @@ class CharmedPendantManaEffect extends ManaEffect {
} }
if (manaCost instanceof MonoHybridManaCost) { if (manaCost instanceof MonoHybridManaCost) {
newManaCosts.add(new ColoredManaCost(((MonoHybridManaCost) manaCost).getManaColor())); newManaCosts.add(new ColoredManaCost(((MonoHybridManaCost) manaCost).getManaColor()));
} else if (manaCost instanceof ColorlessHybridManaCost) {
newManaCosts.add(new ColoredManaCost(((ColorlessHybridManaCost) manaCost).getManaColor()));
} else { } else {
newManaCosts.add(manaCost.copy()); newManaCosts.add(manaCost.copy());
} }

View file

@ -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<Spell> 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<StackObject> 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;
}
}

View file

@ -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("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("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("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("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 Growth Chamber", 377, Rarity.COMMON, mage.cards.s.SimicGrowthChamber.class));
cards.add(new SetCardInfo("Simic Guildgate", 378, Rarity.COMMON, mage.cards.s.SimicGuildgate.class)); cards.add(new SetCardInfo("Simic Guildgate", 378, Rarity.COMMON, mage.cards.s.SimicGuildgate.class));

View file

@ -1,15 +1,16 @@
package mage; package mage;
/** /**
* Enum representing the mana symbols. * Enum representing the mana symbols.
* <p> * <p>
* 107.4. The mana symbols are {W}, {U}, {B}, {R}, {G}, and {X}; the numerals * 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 hybrid symbols {W/U}, {W/B}, {U/B}, * {0}, {1}, {2}, {3}, {4}, and so on; the variable symbol {X}; the hybrid symbols
* {U/R}, {B/R}, {B/G}, {R/G}, {R/W}, {G/W}, and {G/U}; the monocolored hybrid * {W/U}, {W/B}, {U/B}, {U/R}, {B/R}, {B/G}, {R/G}, {R/W}, {G/W}, and {G/U};
* symbols {2/W}, {2/U}, {2/B}, {2/R}, and {2/G}; the Phyrexian mana symbols * the monocolored hybrid symbols {2/W}, {2/U}, {2/B}, {2/R}, and {2/G};
* {W/P}, {U/P}, {B/P}, {R/P}, and {G/P}; and the snow symbol {S}. * 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}.
* <p> * <p>
* 107.4a. There are five primary colored mana symbols: {W} is white, {U} blue, * 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 * {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), B("{B}", Type.PRIMARY, Type.COLORED, Type.MONOCOLORED),
R("{R}", Type.PRIMARY, Type.COLORED, Type.MONOCOLORED), R("{R}", Type.PRIMARY, Type.COLORED, Type.MONOCOLORED),
G("{G}", Type.PRIMARY, Type.COLORED, Type.MONOCOLORED), G("{G}", Type.PRIMARY, Type.COLORED, Type.MONOCOLORED),
C("{C}", Type.COLORLESS),
X("{X}", Type.GENERIC, Type.COLORLESS), X("{X}", Type.GENERIC, Type.COLORLESS),
NUMERIC("{N/A}", Type.GENERIC, Type.COLORLESS), NUMERIC("{N/A}", Type.GENERIC, Type.COLORLESS),
HYBRID_WU("{W/U}", W, U, Type.HYBRID, Type.COLORED), 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_RW("{R/W}", R, W, Type.HYBRID, Type.COLORED),
HYBRID_GW("{G/W}", G, 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_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_W("{2/W}", W, Type.HYBRID, Type.MONOCOLORED, Type.COLORED),
MONOCOLORED_HYBRID_U("{2/U}", U, 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_B("{2/B}", B, Type.HYBRID, Type.MONOCOLORED, Type.COLORED),
MONOCOLORED_HYBRID_R("{2/R}", R, 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), 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_W("{W/P}", W, Type.PHYREXIAN, Type.COLORED, Type.MONOCOLORED),
PHYREXIAN_G("{G/P}", G, 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), PHYREXIAN_R("{R/P}", R, Type.PHYREXIAN, Type.COLORED, Type.MONOCOLORED),

View file

@ -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<Mana> getManaOptions() {
List<Mana> manaList = new ArrayList<>();
manaList.add(new Mana(manaColor));
manaList.add(Mana.ColorlessMana(1));
return manaList;
}
}

View file

@ -18,7 +18,7 @@ public class HybridManaCost extends ManaCostImpl {
public HybridManaCost(ColoredManaSymbol mana1, ColoredManaSymbol mana2) { public HybridManaCost(ColoredManaSymbol mana1, ColoredManaSymbol mana2) {
this.mana1 = mana1; this.mana1 = mana1;
this.mana2 = mana2; this.mana2 = mana2;
this.cost = new Mana(mana1); this.cost = mana1 == null ? Mana.ColorlessMana(1) : new Mana(mana1);
this.cost.add(new Mana(mana2)); this.cost.add(new Mana(mana2));
addColoredOption(mana1); addColoredOption(mana1);
addColoredOption(mana2); addColoredOption(mana2);
@ -42,7 +42,7 @@ public class HybridManaCost extends ManaCostImpl {
@Override @Override
public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) { 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; return;
} }
assignColored(ability, game, pool, this.mana2, costToPay); assignColored(ability, game, pool, this.mana2, costToPay);
@ -81,6 +81,10 @@ public class HybridManaCost extends ManaCostImpl {
if (testMana.getGreen() > 0 || testMana.getAny() > 0) { if (testMana.getGreen() > 0 || testMana.getAny() > 0) {
return true; return true;
} }
default:
if (testMana.getColorless() > 0) {
return true;
}
} }
switch (mana2) { switch (mana2) {
case B: case B:

View file

@ -151,14 +151,15 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost {
return false; 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); int conditionalCount = pool.getConditionalCount(ability, game, null, costToPay);
while (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0)) { if (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0)
if (pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay, usedManaToPay)) { && pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay, usedManaToPay)) {
this.payment.increaseColorless(); this.payment.increaseColorless();
return true;
} }
break;
} return false;
} }
protected boolean assignGeneric(Ability ability, Game game, ManaPool pool, int mana, FilterMana filterMana, Cost costToPay) { 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) { switch (symbol) {
case B: case B:
this.options.add(Mana.BlackMana(1)); this.options.add(Mana.BlackMana(1));
break; return;
case U: case U:
this.options.add(Mana.BlueMana(1)); this.options.add(Mana.BlueMana(1));
break; return;
case W: case W:
this.options.add(Mana.WhiteMana(1)); this.options.add(Mana.WhiteMana(1));
break; return;
case R: case R:
this.options.add(Mana.RedMana(1)); this.options.add(Mana.RedMana(1));
break; return;
case G: case G:
this.options.add(Mana.GreenMana(1)); this.options.add(Mana.GreenMana(1));
break; return;
default:
this.options.add(Mana.ColorlessMana(1));
} }
} }

View file

@ -348,6 +348,16 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> 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 // monohybrid
// try to pay colored part // try to pay colored part
for (ManaCost cost : this) { for (ManaCost cost : this) {
@ -492,6 +502,8 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
ManaCost cost; ManaCost cost;
if (without.length() == 1) { if (without.length() == 1) {
cost = new ColoredManaCost(ColoredManaSymbol.lookup(without.charAt(0))); cost = new ColoredManaCost(ColoredManaSymbol.lookup(without.charAt(0)));
} else if (without.charAt(0) == 'C') {
cost = new ColorlessHybridManaCost(ColoredManaSymbol.lookup(without.charAt(2)));
} else { } else {
cost = new HybridManaCost(ColoredManaSymbol.lookup(without.charAt(0)), ColoredManaSymbol.lookup(without.charAt(2))); cost = new HybridManaCost(ColoredManaSymbol.lookup(without.charAt(0)), ColoredManaSymbol.lookup(without.charAt(2)));
} }

View file

@ -261,6 +261,9 @@ public final class ManaUtil {
} else if (symbols.contains(ManaSymbol.HYBRID_WB)) { } else if (symbols.contains(ManaSymbol.HYBRID_WB)) {
chosenManaAbilityForHybrid = ability; chosenManaAbilityForHybrid = ability;
countColored.add(ManaSymbol.HYBRID_WB); 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)) { } else if (symbols.contains(ManaSymbol.HYBRID_UR)) {
chosenManaAbilityForHybrid = ability; chosenManaAbilityForHybrid = ability;
countColored.add(ManaSymbol.HYBRID_UR); countColored.add(ManaSymbol.HYBRID_UR);
} else if (symbols.contains(ManaSymbol.HYBRID_CR)) {
chosenManaAbilityForHybrid = ability;
countColored.add(ManaSymbol.HYBRID_CR);
} }
} }
return chosenManaAbilityForHybrid; return chosenManaAbilityForHybrid;
@ -302,6 +308,9 @@ public final class ManaUtil {
} else if (symbols.contains(ManaSymbol.HYBRID_GU)) { } else if (symbols.contains(ManaSymbol.HYBRID_GU)) {
chosenManaAbilityForHybrid = ability; chosenManaAbilityForHybrid = ability;
countColored.add(ManaSymbol.HYBRID_GU); countColored.add(ManaSymbol.HYBRID_GU);
} else if (symbols.contains(ManaSymbol.HYBRID_CU)) {
chosenManaAbilityForHybrid = ability;
countColored.add(ManaSymbol.HYBRID_CU);
} }
} }
return chosenManaAbilityForHybrid; return chosenManaAbilityForHybrid;
@ -322,6 +331,9 @@ public final class ManaUtil {
} else if (symbols.contains(ManaSymbol.HYBRID_RW)) { } else if (symbols.contains(ManaSymbol.HYBRID_RW)) {
chosenManaAbilityForHybrid = ability; chosenManaAbilityForHybrid = ability;
countColored.add(ManaSymbol.HYBRID_RW); countColored.add(ManaSymbol.HYBRID_RW);
} else if (symbols.contains(ManaSymbol.HYBRID_CW)) {
chosenManaAbilityForHybrid = ability;
countColored.add(ManaSymbol.HYBRID_CW);
} }
} }
return chosenManaAbilityForHybrid; return chosenManaAbilityForHybrid;
@ -342,6 +354,9 @@ public final class ManaUtil {
} else if (symbols.contains(ManaSymbol.HYBRID_RG)) { } else if (symbols.contains(ManaSymbol.HYBRID_RG)) {
chosenManaAbilityForHybrid = ability; chosenManaAbilityForHybrid = ability;
countColored.add(ManaSymbol.HYBRID_RG); countColored.add(ManaSymbol.HYBRID_RG);
} else if (symbols.contains(ManaSymbol.HYBRID_CG)) {
chosenManaAbilityForHybrid = ability;
countColored.add(ManaSymbol.HYBRID_CG);
} }
} }
return chosenManaAbilityForHybrid; return chosenManaAbilityForHybrid;