Implement cost reduction to apply for most cases of reducing hybrid/split/phyrexian cost.
Extend unit test with those cases.master
parent
aaf678b517
commit
28732e250a
|
@ -41,6 +41,7 @@ public enum MagicCostManaType {
|
|||
public static final int NR_OF_TYPES=values().length;
|
||||
public static final EnumSet<MagicCostManaType> MONO = EnumSet.range(White, Green);
|
||||
public static final EnumSet<MagicCostManaType> HYBRID = EnumSet.range(WhiteBlue, GreenBlue);
|
||||
public static final EnumSet<MagicCostManaType> CHOICE = EnumSet.range(WhiteBlue, HybridGreen);
|
||||
public static final EnumSet<MagicCostManaType> NON_MONO = EnumSet.complementOf(MONO);
|
||||
|
||||
private final String name;
|
||||
|
|
|
@ -145,6 +145,10 @@ public class MagicManaCost implements MagicCopyable {
|
|||
return XCount > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x value for {X} in the mana cost (if it is present)
|
||||
* @return list of mana costs, with each element representing exactly 1 mana of some kind
|
||||
*/
|
||||
public List<MagicCostManaType> getCostManaTypes(final int x) {
|
||||
final List<MagicCostManaType> types = new ArrayList<>();
|
||||
int generic=x * XCount;
|
||||
|
@ -409,6 +413,7 @@ public class MagicManaCost implements MagicCopyable {
|
|||
final int idx = type.ordinal();
|
||||
reducedAmounts[idx] += amt;
|
||||
if (XCount > 0 && type == MagicCostManaType.Generic && reducedAmounts[idx] < 0) {
|
||||
// If cost contains {X}, we store even negative value for colorless as possible "discount"
|
||||
return new MagicManaCost(reducedAmounts, XCount);
|
||||
} else if (amounts[idx] == 0 && reducedAmounts[idx] < 0) {
|
||||
return this;
|
||||
|
@ -429,12 +434,58 @@ public class MagicManaCost implements MagicCopyable {
|
|||
/**
|
||||
* Return cost decreased by some other cost. Only identical mana is removed from the cost.
|
||||
* For example, cost {R}{B} reduced by {B}{B}{1} will become {R}
|
||||
*
|
||||
* When removing colored mana ({R}, {G}, {B}, {U}, {W}), primarily remove the specified mana.
|
||||
* If that is not present, look for mana with choice (hybrid, phyrexian, or colorless-hybrid in that order)
|
||||
* and see if the reduction can be deducted from some of that cost.
|
||||
*
|
||||
* First possible encountered cost is used for reduction.
|
||||
* That may not necessarily be optimal choice if more hybrid costs are present.
|
||||
*
|
||||
* (i.e. removing {R}{G} from {R/G}{R/U} may remove first {R/G} via {R} even if the result would not be optimal)
|
||||
*/
|
||||
public MagicManaCost reducedBy(MagicManaCost extraCost) {
|
||||
MagicManaCost res = this;
|
||||
for (final MagicCostManaType cmt : extraCost.getCostManaTypes(0)) {
|
||||
res = res.reduce(cmt, 1);
|
||||
final int[] reducedAmounts = Arrays.copyOf(amounts, amounts.length);
|
||||
|
||||
boolean changed = false;
|
||||
List<MagicCostManaType> remaining = new ArrayList<>();
|
||||
for (final MagicCostManaType type : extraCost.getCostManaTypes(0)) {
|
||||
final int idx = type.ordinal();
|
||||
if (reducedAmounts[idx] >= 1) {
|
||||
reducedAmounts[idx] -= 1;
|
||||
changed = true;
|
||||
} else {
|
||||
if (XCount > 0 && type == MagicCostManaType.Generic) {
|
||||
// For Generic: if X present, store even negative
|
||||
reducedAmounts[idx] -= 1;
|
||||
changed = true;
|
||||
} else {
|
||||
// Try in second round
|
||||
if (MagicCostManaType.MONO.contains(type)) {
|
||||
remaining.add(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
// Try to remove monocolored costs from hybrid costs
|
||||
for (final MagicCostManaType type : remaining) {
|
||||
MagicManaType thisColor = type.getTypes().get(0);
|
||||
for (MagicCostManaType candidate : MagicCostManaType.CHOICE) {
|
||||
final int idx = candidate.ordinal();
|
||||
if (reducedAmounts[idx] >= 1) {
|
||||
if (candidate.getTypes().contains(thisColor)) {
|
||||
reducedAmounts[idx] -= 1;
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
return new MagicManaCost(reducedAmounts, XCount);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,36 @@ public class MagicManaCostTest {
|
|||
|
||||
assertEquals("{X}{2}{R}", rx.increasedBy(MagicManaCost.create("{2}")).toString());
|
||||
assertEquals("{X}{X}{2}{U}", uxx.increasedBy(MagicManaCost.create("{2}")).toString());
|
||||
|
||||
// Following two are not 100% correct, but as close to the wanted result as possible
|
||||
// (as the X should be replaced by something like "X-2", or rather the discount should be fully resolved at cast time)
|
||||
// Note that -2 is stored internally in the amount, but not used for discount when casting.
|
||||
assertEquals("{X}{R}", rx.reducedBy(MagicManaCost.create("{2}")).toString());
|
||||
assertEquals("{X}{X}{U}", uxx.reducedBy(MagicManaCost.create("{2}")).toString());
|
||||
|
||||
assertEquals("{X}{R}", rx.increasedBy(MagicManaCost.create("{2}")).reducedBy(MagicManaCost.create("{2}")).toString());
|
||||
assertEquals("{X}{R}", rx.increasedBy(MagicManaCost.create("{2}")).reducedBy(
|
||||
MagicManaCost.create("{2}")).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitCostModification() {
|
||||
MagicManaCost rw3 = MagicManaCost.create("{R/W}{R/W}{R/W}");
|
||||
assertEquals("{R/W}{R/W}", rw3.reducedBy(MagicManaCost.create("{R}{G}")).toString());
|
||||
assertEquals("{R/W}", rw3.reducedBy(MagicManaCost.create("{R}{G}{R/W}")).toString());
|
||||
MagicManaCost rw2gw = MagicManaCost.create("{R/W}{R/W}{G/W}");
|
||||
|
||||
assertEquals("{0}", rw2gw.reducedBy(MagicManaCost.create("{R}{G}{R/W}")).toString());
|
||||
assertEquals("{0}", rw2gw.reducedBy(MagicManaCost.create("{R}{G}{W}")).toString());
|
||||
|
||||
MagicManaCost hybrid = MagicManaCost.create("{2/R}{2/G}{2/W}");
|
||||
assertEquals("{2/W}", hybrid.reducedBy(MagicManaCost.create("{R}{G}{U}")).toString());
|
||||
|
||||
MagicManaCost phyR = MagicManaCost.create("{R}{R/P}{G/P}{W/P}");
|
||||
assertEquals("{W/P}", phyR.reducedBy(MagicManaCost.create("{R}{R}{G}{U}")).toString());
|
||||
|
||||
MagicManaCost phy = MagicManaCost.create("{R/P}{G/P}{W/P}");
|
||||
assertEquals("{W/P}", phy.reducedBy(MagicManaCost.create("{R}{G}{U}")).toString());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue