forked from External/mage
* refactored mana methods to WUBRG order * more WUBRG refactoring * added new mana tracking object * fixed code error * fixed missing mana count * fixed null pointer exception in tests * fixed issue with equality * more equality fixes * some cosmetic changes to ManaTest * added copy method to setToMana * fixed some initialization issues * fixed serialization issue * [KHM] Implemented Search for Glory * updated mana handling to track snow * added tests for snow mana tracking * updated implementation of setter methods * updated paramater to use copy methods * fixed snow mana test to ensure proper mana tapping * replaced instances of getPayment with getUsedManaToPay * updated tracking of snow mana * reverted snow mana tracking removal * finished reverting change
1377 lines
43 KiB
Java
1377 lines
43 KiB
Java
package mage;
|
|
|
|
import mage.constants.ColoredManaSymbol;
|
|
import mage.constants.ManaType;
|
|
import mage.filter.FilterMana;
|
|
import mage.util.Copyable;
|
|
import org.apache.log4j.Logger;
|
|
|
|
import java.io.Serializable;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* @author BetaSteward_at_googlemail.com
|
|
*/
|
|
public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
|
|
|
|
protected static final class ManaColor implements Serializable {
|
|
private int amount = 0;
|
|
private int snowAmount = 0;
|
|
|
|
private ManaColor() {
|
|
}
|
|
|
|
private ManaColor(int amount) {
|
|
this.amount = amount;
|
|
}
|
|
|
|
protected int getAmount() {
|
|
return amount;
|
|
}
|
|
|
|
protected int getSnowAmount() {
|
|
return snowAmount;
|
|
}
|
|
|
|
protected void incrementAmount() {
|
|
incrementAmount(1, false);
|
|
}
|
|
|
|
protected void incrementAmount(ManaColor manaColor) {
|
|
this.amount += manaColor.amount;
|
|
this.snowAmount += manaColor.snowAmount;
|
|
}
|
|
|
|
protected void incrementAmount(int amount, boolean snow) {
|
|
this.amount += amount;
|
|
if (snow) {
|
|
this.snowAmount += amount;
|
|
}
|
|
}
|
|
|
|
protected void removeAmount(ManaColor manaColor) {
|
|
this.amount -= manaColor.amount;
|
|
this.snowAmount -= manaColor.snowAmount;
|
|
}
|
|
|
|
protected void clear() {
|
|
amount = 0;
|
|
snowAmount = 0;
|
|
}
|
|
|
|
protected boolean removeOne(ManaColor manaColor) {
|
|
if (manaColor.getAmount() < 1) {
|
|
return false;
|
|
}
|
|
if (manaColor.getSnowAmount() > 0) {
|
|
manaColor.snowAmount -= 1;
|
|
snowAmount += 1;
|
|
}
|
|
manaColor.amount -= 1;
|
|
amount += 1;
|
|
return true;
|
|
}
|
|
|
|
protected ManaColor copy() {
|
|
ManaColor copy = new ManaColor();
|
|
copy.incrementAmount(this);
|
|
return copy;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) return true;
|
|
if (o == null || getClass() != o.getClass()) return false;
|
|
ManaColor manaColor = (ManaColor) o;
|
|
return amount == manaColor.amount && snowAmount == manaColor.snowAmount;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(amount, snowAmount);
|
|
}
|
|
}
|
|
|
|
private static final transient Logger logger = Logger.getLogger(Mana.class);
|
|
|
|
protected ManaColor white;
|
|
protected ManaColor blue;
|
|
protected ManaColor black;
|
|
protected ManaColor red;
|
|
protected ManaColor green;
|
|
protected ManaColor generic;
|
|
protected ManaColor colorless;
|
|
protected ManaColor any;
|
|
protected boolean flag;
|
|
|
|
/**
|
|
* Default constructor. Creates a {@link Mana} object with 0 values.
|
|
*/
|
|
public Mana() {
|
|
white = new ManaColor();
|
|
blue = new ManaColor();
|
|
black = new ManaColor();
|
|
red = new ManaColor();
|
|
green = new ManaColor();
|
|
generic = new ManaColor();
|
|
colorless = new ManaColor();
|
|
any = new ManaColor();
|
|
flag = false;
|
|
}
|
|
|
|
/**
|
|
* Creates a {@link Mana} object with the passed in values. Values can not
|
|
* be less than 0. Any values less than 0 will be logged and set to 0.
|
|
*
|
|
* @param white total White mana to have.
|
|
* @param blue total Blue mana to have.
|
|
* @param black total Black mana to have.
|
|
* @param red total Red mana to have.
|
|
* @param green total Green mana to have.
|
|
* @param generic total Generic mana to have.
|
|
* @param any total Any mana to have.
|
|
* @param colorless total Colorless mana to have.
|
|
*/
|
|
public Mana(final int white, final int blue, final int black, final int red, final int green, final int generic, final int any, final int colorless) {
|
|
this.white = new ManaColor(notNegative(white, "White"));
|
|
this.blue = new ManaColor(notNegative(blue, "Blue"));
|
|
this.black = new ManaColor(notNegative(black, "Black"));
|
|
this.red = new ManaColor(notNegative(red, "Red"));
|
|
this.green = new ManaColor(notNegative(green, "Green"));
|
|
this.generic = new ManaColor(notNegative(generic, "Generic"));
|
|
this.colorless = new ManaColor(notNegative(colorless, "Colorless"));
|
|
this.any = new ManaColor(notNegative(any, "Any"));
|
|
this.flag = false;
|
|
}
|
|
|
|
/**
|
|
* Copy constructor. Creates a {@link Mana} object from existing
|
|
* {@link Mana}
|
|
*
|
|
* @param mana object to create copy from
|
|
*/
|
|
public Mana(final Mana mana) {
|
|
Objects.requireNonNull(mana, "The passed in mana can not be null");
|
|
this.white = mana.white.copy();
|
|
this.blue = mana.blue.copy();
|
|
this.black = mana.black.copy();
|
|
this.red = mana.red.copy();
|
|
this.green = mana.green.copy();
|
|
this.generic = mana.generic.copy();
|
|
this.colorless = mana.colorless.copy();
|
|
this.any = mana.any.copy();
|
|
this.flag = mana.flag;
|
|
}
|
|
|
|
/**
|
|
* Creates {@link Mana} object from {@link ColoredManaSymbol}. Created
|
|
* {@link Mana} will have a single mana of the passed in
|
|
* {@link ColoredManaSymbol} color.
|
|
*
|
|
* @param color The color to create the {@link Mana} object with.
|
|
*/
|
|
public Mana(final ColoredManaSymbol color) {
|
|
this();
|
|
Objects.requireNonNull(color, "The passed in ColoredManaSymbol can not be null");
|
|
switch (color) {
|
|
case W:
|
|
white.incrementAmount();
|
|
break;
|
|
case U:
|
|
blue.incrementAmount();
|
|
break;
|
|
case B:
|
|
black.incrementAmount();
|
|
break;
|
|
case R:
|
|
red.incrementAmount();
|
|
break;
|
|
case G:
|
|
green.incrementAmount();
|
|
break;
|
|
default:
|
|
throw new IllegalArgumentException("Unknown mana color: " + color);
|
|
}
|
|
}
|
|
|
|
public Mana(final ManaType manaType) {
|
|
this();
|
|
Objects.requireNonNull(manaType, "The passed in ManaType can not be null");
|
|
switch (manaType) {
|
|
case WHITE:
|
|
white.incrementAmount();
|
|
break;
|
|
case BLUE:
|
|
blue.incrementAmount();
|
|
break;
|
|
case BLACK:
|
|
black.incrementAmount();
|
|
break;
|
|
case RED:
|
|
red.incrementAmount();
|
|
break;
|
|
case GREEN:
|
|
green.incrementAmount();
|
|
break;
|
|
case COLORLESS:
|
|
colorless.incrementAmount();
|
|
break;
|
|
case GENERIC:
|
|
generic.incrementAmount();
|
|
break;
|
|
default:
|
|
throw new IllegalArgumentException("Unknown manaType: " + manaType);
|
|
}
|
|
}
|
|
|
|
public Mana(final ManaType manaType, int num) {
|
|
this();
|
|
Objects.requireNonNull(manaType, "The passed in ManaType can not be null");
|
|
switch (manaType) {
|
|
case WHITE:
|
|
white.incrementAmount(num, false);
|
|
break;
|
|
case BLUE:
|
|
blue.incrementAmount(num, false);
|
|
break;
|
|
case BLACK:
|
|
black.incrementAmount(num, false);
|
|
break;
|
|
case RED:
|
|
red.incrementAmount(num, false);
|
|
break;
|
|
case GREEN:
|
|
green.incrementAmount(num, false);
|
|
break;
|
|
case COLORLESS:
|
|
colorless.incrementAmount(num, false);
|
|
break;
|
|
case GENERIC:
|
|
generic.incrementAmount(num, false);
|
|
break;
|
|
default:
|
|
throw new IllegalArgumentException("Unknown manaType: " + manaType);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a {@link Mana} object with the passed in {@code num} of White
|
|
* mana. {@code num} can not be a negative value. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param num value of White mana to create.
|
|
* @return a {@link Mana} object with the passed in {@code num} of White
|
|
* mana.
|
|
*/
|
|
public static Mana WhiteMana(int num) {
|
|
return new Mana(notNegative(num, "White"), 0, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
|
|
/**
|
|
* Creates a {@link Mana} object with the passed in {@code num} of Blue
|
|
* mana. {@code num} can not be a negative value. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param num value of Blue mana to create.
|
|
* @return a {@link Mana} object with the passed in {@code num} of Blue
|
|
* mana.
|
|
*/
|
|
public static Mana BlueMana(int num) {
|
|
return new Mana(0, notNegative(num, "Blue"), 0, 0, 0, 0, 0, 0);
|
|
}
|
|
|
|
/**
|
|
* Creates a {@link Mana} object with the passed in {@code num} of Black
|
|
* mana. {@code num} can not be a negative value. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param num value of Black mana to create.
|
|
* @return a {@link Mana} object with the passed in {@code num} of Black
|
|
* mana.
|
|
*/
|
|
public static Mana BlackMana(int num) {
|
|
return new Mana(0, 0, notNegative(num, "Black"), 0, 0, 0, 0, 0);
|
|
}
|
|
|
|
/**
|
|
* Creates a {@link Mana} object with the passed in {@code num} of Red mana.
|
|
* {@code num} can not be a negative value. Negative values will be logged
|
|
* and set to 0.
|
|
*
|
|
* @param num value of Red mana to create.
|
|
* @return a {@link Mana} object with the passed in {@code num} of Red mana.
|
|
*/
|
|
public static Mana RedMana(int num) {
|
|
return new Mana(0, 0, 0, notNegative(num, "Red"), 0, 0, 0, 0);
|
|
}
|
|
|
|
/**
|
|
* Creates a {@link Mana} object with the passed in {@code num} of Green
|
|
* mana. {@code num} can not be a negative value. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param num value of Green mana to create.
|
|
* @return a {@link Mana} object with the passed in {@code num} of Green
|
|
* mana.
|
|
*/
|
|
public static Mana GreenMana(int num) {
|
|
return new Mana(0, 0, 0, 0, notNegative(num, "Green"), 0, 0, 0);
|
|
}
|
|
|
|
/**
|
|
* Creates a {@link Mana} object with the passed in {@code num} of Generic
|
|
* mana. {@code num} can not be a negative value. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param num value of Generic mana to create.
|
|
* @return a {@link Mana} object with the passed in {@code num} of Generic
|
|
* mana.
|
|
*/
|
|
public static Mana GenericMana(int num) {
|
|
return new Mana(0, 0, 0, 0, 0, notNegative(num, "Generic"), 0, 0);
|
|
}
|
|
|
|
/**
|
|
* Creates a {@link Mana} object with the passed in {@code num} of Colorless
|
|
* mana. {@code num} can not be a negative value. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param num value of Colorless mana to create.
|
|
* @return a {@link Mana} object with the passed in {@code num} of Colorless
|
|
* mana.
|
|
*/
|
|
public static Mana ColorlessMana(int num) {
|
|
return new Mana(0, 0, 0, 0, 0, 0, 0, notNegative(num, "Colorless"));
|
|
}
|
|
|
|
/**
|
|
* Creates a {@link Mana} object with the passed in {@code num} of Any mana.
|
|
* {@code num} can not be a negative value. Negative values will be logged
|
|
* and set to 0.
|
|
*
|
|
* @param num value of Any mana to create.
|
|
* @return a {@link Mana} object with the passed in {@code num} of Any mana.
|
|
*/
|
|
public static Mana AnyMana(int num) {
|
|
return new Mana(0, 0, 0, 0, 0, 0, notNegative(num, "Any"), 0);
|
|
}
|
|
|
|
/**
|
|
* Adds mana from the passed in {@link Mana} object to this object.
|
|
* Ignores conditions from conditional mana
|
|
*
|
|
* @param mana mana to add to this object.
|
|
*/
|
|
public void add(final Mana mana) {
|
|
white.incrementAmount(mana.white);
|
|
blue.incrementAmount(mana.blue);
|
|
black.incrementAmount(mana.black);
|
|
red.incrementAmount(mana.red);
|
|
green.incrementAmount(mana.green);
|
|
generic.incrementAmount(mana.generic);
|
|
colorless.incrementAmount(mana.colorless);
|
|
any.incrementAmount(mana.any);
|
|
}
|
|
|
|
/**
|
|
* Increases the given mana by one.
|
|
*
|
|
* @param manaType
|
|
*/
|
|
public void increase(ManaType manaType) {
|
|
increase(manaType, false);
|
|
}
|
|
|
|
public void increase(ManaType manaType, boolean isSnow) {
|
|
switch (manaType) {
|
|
case WHITE:
|
|
white.incrementAmount(1, isSnow);
|
|
break;
|
|
case BLUE:
|
|
blue.incrementAmount(1, isSnow);
|
|
break;
|
|
case BLACK:
|
|
black.incrementAmount(1, isSnow);
|
|
break;
|
|
case RED:
|
|
red.incrementAmount(1, isSnow);
|
|
break;
|
|
case GREEN:
|
|
green.incrementAmount(1, isSnow);
|
|
break;
|
|
case COLORLESS:
|
|
colorless.incrementAmount(1, isSnow);
|
|
break;
|
|
case GENERIC:
|
|
generic.incrementAmount(1, isSnow);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Increases the White mana by one.
|
|
*/
|
|
public void increaseWhite() {
|
|
increaseWhite(1, false);
|
|
}
|
|
|
|
public void increaseWhite(int amount, boolean snow) {
|
|
white.incrementAmount(amount, snow);
|
|
}
|
|
|
|
/**
|
|
* Increases the Blue mana by one.
|
|
*/
|
|
public void increaseBlue() {
|
|
increaseBlue(1, false);
|
|
}
|
|
|
|
public void increaseBlue(int amount, boolean snow) {
|
|
blue.incrementAmount(amount, snow);
|
|
}
|
|
|
|
/**
|
|
* Increases the Black mana by one.
|
|
*/
|
|
public void increaseBlack() {
|
|
increaseBlack(1, false);
|
|
}
|
|
|
|
public void increaseBlack(int amount, boolean snow) {
|
|
black.incrementAmount(amount, snow);
|
|
}
|
|
|
|
/**
|
|
* Increases the Red mana by one.
|
|
*/
|
|
public void increaseRed() {
|
|
increaseRed(1, false);
|
|
}
|
|
|
|
public void increaseRed(int amount, boolean snow) {
|
|
red.incrementAmount(amount, snow);
|
|
}
|
|
|
|
/**
|
|
* Increases the Green mana by one.
|
|
*/
|
|
public void increaseGreen() {
|
|
increaseGreen(1, false);
|
|
}
|
|
|
|
public void increaseGreen(int amount, boolean snow) {
|
|
green.incrementAmount(amount, snow);
|
|
}
|
|
|
|
/**
|
|
* Increases the Generic mana by one.
|
|
*/
|
|
public void increaseGeneric() {
|
|
increaseGeneric(1, false);
|
|
}
|
|
|
|
public void increaseGeneric(int amount, boolean snow) {
|
|
generic.incrementAmount(amount, snow);
|
|
}
|
|
|
|
/**
|
|
* Increases the Colorless mana by one.
|
|
*/
|
|
public void increaseColorless() {
|
|
increaseColorless(1, false);
|
|
}
|
|
|
|
public void increaseColorless(int amount, boolean snow) {
|
|
colorless.incrementAmount(amount, snow);
|
|
}
|
|
|
|
/**
|
|
* Subtracts the passed in mana values from this instance.
|
|
*
|
|
* @param mana mana values to subtract
|
|
*/
|
|
public void subtract(final Mana mana) {
|
|
white.removeAmount(mana.white);
|
|
blue.removeAmount(mana.blue);
|
|
black.removeAmount(mana.black);
|
|
red.removeAmount(mana.red);
|
|
green.removeAmount(mana.green);
|
|
generic.removeAmount(mana.generic);
|
|
colorless.removeAmount(mana.colorless);
|
|
any.removeAmount(mana.any);
|
|
}
|
|
|
|
/**
|
|
* Subtracts the passed in mana values from this instance. The difference
|
|
* between this and {@code subtract()} is that if we do not have the
|
|
* available generic mana to pay, we take mana from our colored mana pools.
|
|
*
|
|
* @param mana mana values to subtract
|
|
* @throws ArithmeticException thrown if there is not enough available
|
|
* colored mana to pay the generic cost
|
|
*/
|
|
public void subtractCost(final Mana mana) throws ArithmeticException {
|
|
white.removeAmount(mana.white);
|
|
blue.removeAmount(mana.blue);
|
|
black.removeAmount(mana.black);
|
|
red.removeAmount(mana.red);
|
|
green.removeAmount(mana.green);
|
|
generic.removeAmount(mana.generic);
|
|
colorless.removeAmount(mana.colorless);
|
|
any.removeAmount(mana.any);
|
|
|
|
while (generic.getAmount() < 0) {
|
|
ManaColor oldColorless = generic.copy();
|
|
if (generic.removeOne(white)) {
|
|
continue;
|
|
}
|
|
if (generic.removeOne(blue)) {
|
|
continue;
|
|
}
|
|
if (generic.removeOne(black)) {
|
|
continue;
|
|
}
|
|
if (generic.removeOne(red)) {
|
|
continue;
|
|
}
|
|
if (generic.removeOne(green)) {
|
|
continue;
|
|
}
|
|
if (generic.removeOne(colorless)) {
|
|
continue;
|
|
}
|
|
if (generic.removeOne(any)) {
|
|
continue;
|
|
}
|
|
if (oldColorless.getAmount() == generic.getAmount()) {
|
|
throw new ArithmeticException("Not enough mana to pay colorless");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the total count of all combined mana.
|
|
*
|
|
* @return the total count of all combined mana.
|
|
*/
|
|
public int count() {
|
|
return white.getAmount()
|
|
+ blue.getAmount()
|
|
+ black.getAmount()
|
|
+ red.getAmount()
|
|
+ green.getAmount()
|
|
+ generic.getAmount()
|
|
+ colorless.getAmount()
|
|
+ any.getAmount();
|
|
}
|
|
|
|
/**
|
|
* Returns the total count of all colored mana.
|
|
*
|
|
* @return the total count of all colored mana.
|
|
*/
|
|
public int countColored() {
|
|
return white.getAmount()
|
|
+ blue.getAmount()
|
|
+ black.getAmount()
|
|
+ red.getAmount()
|
|
+ green.getAmount()
|
|
+ any.getAmount();
|
|
}
|
|
|
|
/**
|
|
* Returns the count of filtered mana provided by the passed in
|
|
* {@link FilterMana}. If {@link FilterMana} is null, the total mana count
|
|
* is returned via {@link #count() count}.
|
|
*
|
|
* @param filter the colors of mana to return the count for.
|
|
* @return the count of filtered mana provided by the passed in
|
|
* {@link FilterMana}.
|
|
*/
|
|
public int count(final FilterMana filter) {
|
|
if (filter == null) {
|
|
return count();
|
|
}
|
|
int count = 0;
|
|
if (filter.isWhite()) {
|
|
count += white.getAmount();
|
|
}
|
|
if (filter.isBlue()) {
|
|
count += blue.getAmount();
|
|
}
|
|
if (filter.isBlack()) {
|
|
count += black.getAmount();
|
|
}
|
|
if (filter.isRed()) {
|
|
count += red.getAmount();
|
|
}
|
|
if (filter.isGreen()) {
|
|
count += green.getAmount();
|
|
}
|
|
if (filter.isGeneric()) {
|
|
count += generic.getAmount();
|
|
}
|
|
if (filter.isColorless()) {
|
|
count += colorless.getAmount();
|
|
}
|
|
return count;
|
|
}
|
|
|
|
/**
|
|
* Sets all mana to 0.
|
|
*/
|
|
public void clear() {
|
|
white.clear();
|
|
blue.clear();
|
|
black.clear();
|
|
red.clear();
|
|
green.clear();
|
|
generic.clear();
|
|
colorless.clear();
|
|
any.clear();
|
|
}
|
|
|
|
/**
|
|
* Returns this objects values as a {@link String}.
|
|
*
|
|
* @return this objects values as a {@link String}.
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
StringBuilder sbMana = new StringBuilder();
|
|
if (generic.getAmount() > 0) {
|
|
sbMana.append('{').append(Integer.toString(generic.getAmount())).append('}');
|
|
}
|
|
if (colorless.getAmount() >= 20) {
|
|
sbMana.append(Integer.toString(colorless.getAmount())).append("{C}");
|
|
}
|
|
if (white.getAmount() >= 20) {
|
|
sbMana.append(Integer.toString(white.getAmount())).append("{W}");
|
|
}
|
|
if (blue.getAmount() >= 20) {
|
|
sbMana.append(Integer.toString(blue.getAmount())).append("{U}");
|
|
}
|
|
if (black.getAmount() >= 20) {
|
|
sbMana.append(Integer.toString(black.getAmount())).append("{B}");
|
|
}
|
|
if (red.getAmount() >= 20) {
|
|
sbMana.append(Integer.toString(red.getAmount())).append("{R}");
|
|
}
|
|
if (green.getAmount() >= 20) {
|
|
sbMana.append(Integer.toString(green.getAmount())).append("{G}");
|
|
}
|
|
if (any.getAmount() >= 20) {
|
|
sbMana.append(Integer.toString(any.getAmount())).append("{Any}");
|
|
}
|
|
for (int i = 0; i < colorless.getAmount() && colorless.getAmount() < 20; i++) {
|
|
sbMana.append("{C}");
|
|
}
|
|
for (int i = 0; i < white.getAmount() && white.getAmount() < 20; i++) {
|
|
sbMana.append("{W}");
|
|
}
|
|
for (int i = 0; i < blue.getAmount() && blue.getAmount() < 20; i++) {
|
|
sbMana.append("{U}");
|
|
}
|
|
for (int i = 0; i < black.getAmount() && black.getAmount() < 20; i++) {
|
|
sbMana.append("{B}");
|
|
}
|
|
for (int i = 0; i < red.getAmount() && red.getAmount() < 20; i++) {
|
|
sbMana.append("{R}");
|
|
}
|
|
for (int i = 0; i < green.getAmount() && green.getAmount() < 20; i++) {
|
|
sbMana.append("{G}");
|
|
}
|
|
for (int i = 0; i < any.getAmount() && any.getAmount() < 20; i++) {
|
|
sbMana.append("{Any}");
|
|
}
|
|
return sbMana.toString();
|
|
}
|
|
|
|
/**
|
|
* Returns a deep copy of this object.
|
|
*
|
|
* @return a deep copy of this object.
|
|
*/
|
|
@Override
|
|
public Mana copy() {
|
|
return new Mana(this);
|
|
}
|
|
|
|
/**
|
|
* Returns if there is enough available mana to pay the mana provided by the
|
|
* passed in {@link Mana} object.
|
|
*
|
|
* @param cost the cost to compare too.
|
|
* @return if there is enough available mana to pay.
|
|
*/
|
|
public boolean enough(final Mana cost) {
|
|
Mana compare = cost.copy();
|
|
compare.subtract(this);
|
|
if (compare.white.getAmount() < 0) {
|
|
compare.any.incrementAmount(compare.white);
|
|
if (compare.any.getAmount() < 0) {
|
|
return false;
|
|
}
|
|
compare.white.clear();
|
|
}
|
|
if (compare.blue.getAmount() < 0) {
|
|
compare.any.incrementAmount(compare.blue);
|
|
if (compare.any.getAmount() < 0) {
|
|
return false;
|
|
}
|
|
compare.blue.clear();
|
|
}
|
|
if (compare.black.getAmount() < 0) {
|
|
compare.any.incrementAmount(compare.black);
|
|
if (compare.any.getAmount() < 0) {
|
|
return false;
|
|
}
|
|
compare.black.clear();
|
|
}
|
|
if (compare.red.getAmount() < 0) {
|
|
compare.any.incrementAmount(compare.red);
|
|
if (compare.any.getAmount() < 0) {
|
|
return false;
|
|
}
|
|
compare.red.clear();
|
|
}
|
|
if (compare.green.getAmount() < 0) {
|
|
compare.any.incrementAmount(compare.green);
|
|
if (compare.any.getAmount() < 0) {
|
|
return false;
|
|
}
|
|
compare.green.clear();
|
|
}
|
|
if (compare.colorless.getAmount() < 0) {
|
|
compare.any.incrementAmount(compare.colorless);
|
|
if (compare.any.getAmount() < 0) {
|
|
return false;
|
|
}
|
|
compare.colorless.clear();
|
|
}
|
|
if (compare.generic.getAmount() < 0) {
|
|
compare.generic.incrementAmount(compare.white);
|
|
compare.generic.incrementAmount(compare.blue);
|
|
compare.generic.incrementAmount(compare.black);
|
|
compare.generic.incrementAmount(compare.red);
|
|
compare.generic.incrementAmount(compare.green);
|
|
compare.generic.incrementAmount(compare.colorless);
|
|
compare.generic.incrementAmount(compare.any);
|
|
if (compare.generic.getAmount() < 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns the total mana needed to meet the passed in {@link Mana} object.
|
|
*
|
|
* @param cost the mana cost
|
|
* @return the total mana needed to meet the passes in {@link Mana} object.
|
|
*/
|
|
public Mana needed(final Mana cost) {
|
|
Mana compare = cost.copy();
|
|
compare.subtract(this);
|
|
if (compare.white.getAmount() < 0 && compare.any.getAmount() > 0) {
|
|
int diff = Math.min(compare.any.getAmount(), Math.abs(compare.white.getAmount()));
|
|
compare.any.incrementAmount(-diff, false);
|
|
compare.white.incrementAmount(diff, false);
|
|
}
|
|
if (compare.blue.getAmount() < 0 && compare.any.getAmount() > 0) {
|
|
int diff = Math.min(compare.any.getAmount(), Math.abs(compare.blue.getAmount()));
|
|
compare.any.incrementAmount(-diff, false);
|
|
compare.blue.incrementAmount(diff, false);
|
|
}
|
|
if (compare.black.getAmount() < 0 && compare.any.getAmount() > 0) {
|
|
int diff = Math.min(compare.any.getAmount(), Math.abs(compare.black.getAmount()));
|
|
compare.any.incrementAmount(-diff, false);
|
|
compare.black.incrementAmount(diff, false);
|
|
}
|
|
if (compare.red.getAmount() < 0 && compare.any.getAmount() > 0) {
|
|
int diff = Math.min(compare.any.getAmount(), Math.abs(compare.red.getAmount()));
|
|
compare.any.incrementAmount(-diff, false);
|
|
compare.red.incrementAmount(diff, false);
|
|
}
|
|
if (compare.green.getAmount() < 0 && compare.any.getAmount() > 0) {
|
|
int diff = Math.min(compare.any.getAmount(), Math.abs(compare.green.getAmount()));
|
|
compare.any.incrementAmount(-diff, false);
|
|
compare.green.incrementAmount(diff, false);
|
|
}
|
|
if (compare.colorless.getAmount() < 0 && compare.any.getAmount() > 0) {
|
|
int diff = Math.min(compare.any.getAmount(), Math.abs(compare.colorless.getAmount()));
|
|
compare.any.incrementAmount(-diff, false);
|
|
compare.colorless.incrementAmount(diff, false);
|
|
}
|
|
if (compare.generic.getAmount() < 0) {
|
|
int remaining = 0;
|
|
remaining += Math.min(0, compare.white.getAmount());
|
|
remaining += Math.min(0, compare.blue.getAmount());
|
|
remaining += Math.min(0, compare.black.getAmount());
|
|
remaining += Math.min(0, compare.red.getAmount());
|
|
remaining += Math.min(0, compare.green.getAmount());
|
|
remaining += Math.min(0, compare.colorless.getAmount());
|
|
remaining += Math.min(0, compare.any.getAmount());
|
|
if (remaining > 0) {
|
|
int diff = Math.min(remaining, Math.abs(compare.generic.getAmount()));
|
|
compare.generic.incrementAmount(diff, false);
|
|
}
|
|
}
|
|
Mana needed = new Mana();
|
|
if (compare.white.getAmount() < 0) {
|
|
needed.white.removeAmount(compare.white);
|
|
}
|
|
if (compare.blue.getAmount() < 0) {
|
|
needed.blue.removeAmount(compare.blue);
|
|
}
|
|
if (compare.black.getAmount() < 0) {
|
|
needed.black.removeAmount(compare.black);
|
|
}
|
|
if (compare.red.getAmount() < 0) {
|
|
needed.red.removeAmount(compare.red);
|
|
}
|
|
if (compare.green.getAmount() < 0) {
|
|
needed.green.removeAmount(compare.green);
|
|
}
|
|
if (compare.colorless.getAmount() < 0) {
|
|
needed.colorless.removeAmount(compare.colorless);
|
|
}
|
|
if (compare.generic.getAmount() < 0) {
|
|
needed.generic.removeAmount(compare.generic);
|
|
}
|
|
return needed;
|
|
}
|
|
|
|
/**
|
|
* Returns total White mana.
|
|
*
|
|
* @return total White mana.
|
|
*/
|
|
public int getWhite() {
|
|
return white.getAmount();
|
|
}
|
|
|
|
/**
|
|
* Sets the total White mana. Can not be negative. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param white total White mana.
|
|
*/
|
|
public void setWhite(int white) {
|
|
this.white.clear();
|
|
this.white.incrementAmount(notNegative(white, "White"), false);
|
|
}
|
|
|
|
/**
|
|
* Returns total Blue mana.
|
|
*
|
|
* @return total Blue mana.
|
|
*/
|
|
public int getBlue() {
|
|
return blue.getAmount();
|
|
}
|
|
|
|
/**
|
|
* Sets the total Blue mana. Can not be negative. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param blue total Blue mana.
|
|
*/
|
|
public void setBlue(int blue) {
|
|
this.blue.clear();
|
|
this.blue.incrementAmount(notNegative(blue, "Blue"), false);
|
|
}
|
|
|
|
/**
|
|
* Returns total Black mana.
|
|
*
|
|
* @return total Black mana.
|
|
*/
|
|
public int getBlack() {
|
|
return black.getAmount();
|
|
}
|
|
|
|
/**
|
|
* Sets the total Black mana. Can not be negative. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param black total Black mana.
|
|
*/
|
|
public void setBlack(int black) {
|
|
this.black.clear();
|
|
this.black.incrementAmount(notNegative(black, "Black"), false);
|
|
}
|
|
|
|
/**
|
|
* Returns total Red mana.
|
|
*
|
|
* @return total Red mana.
|
|
*/
|
|
public int getRed() {
|
|
return red.getAmount();
|
|
}
|
|
|
|
/**
|
|
* Sets the total Red mana. Can not be negative. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param red total Red mana.
|
|
*/
|
|
public void setRed(int red) {
|
|
this.red.clear();
|
|
this.red.incrementAmount(notNegative(red, "Red"), false);
|
|
}
|
|
|
|
/**
|
|
* Returns total Green mana.
|
|
*
|
|
* @return total Green mana.
|
|
*/
|
|
public int getGreen() {
|
|
return green.getAmount();
|
|
}
|
|
|
|
/**
|
|
* Sets the total Green mana. Can not be negative. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param green total Green mana.
|
|
*/
|
|
public void setGreen(int green) {
|
|
this.green.clear();
|
|
this.green.incrementAmount(notNegative(green, "Green"), false);
|
|
}
|
|
|
|
/**
|
|
* Returns total Generic mana.
|
|
*
|
|
* @return total Generic mana.
|
|
*/
|
|
public int getGeneric() {
|
|
return generic.getAmount();
|
|
}
|
|
|
|
/**
|
|
* Sets the total Generic mana. Can not be negative. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param generic total Generic mana.
|
|
*/
|
|
public void setGeneric(int generic) {
|
|
this.generic.clear();
|
|
this.generic.incrementAmount(notNegative(generic, "Generic"), false);
|
|
}
|
|
|
|
/**
|
|
* Returns total Colorless mana.
|
|
*
|
|
* @return total Colorless mana.
|
|
*/
|
|
public int getColorless() {
|
|
return colorless.getAmount();
|
|
}
|
|
|
|
/**
|
|
* Sets the total Colorless mana. Can not be negative. Negative values will
|
|
* be logged and set to 0.
|
|
*
|
|
* @param colorless total Colorless mana.
|
|
*/
|
|
public void setColorless(int colorless) {
|
|
this.colorless.clear();
|
|
this.colorless.incrementAmount(notNegative(colorless, "Colorless"), false);
|
|
}
|
|
|
|
/**
|
|
* Returns total Any mana.
|
|
*
|
|
* @return total Any mana.
|
|
*/
|
|
public int getAny() {
|
|
return any.getAmount();
|
|
}
|
|
|
|
/**
|
|
* Sets the total Any mana. Can not be negative. Negative values will be
|
|
* logged and set to 0.
|
|
*
|
|
* @param any total Any mana.
|
|
*/
|
|
public void setAny(int any) {
|
|
this.any.clear();
|
|
this.any.incrementAmount(notNegative(any, "Any"), false);
|
|
}
|
|
|
|
public int getSnow() {
|
|
return white.getSnowAmount()
|
|
+ blue.getSnowAmount()
|
|
+ black.getSnowAmount()
|
|
+ red.getSnowAmount()
|
|
+ green.getSnowAmount()
|
|
+ colorless.getSnowAmount()
|
|
+ generic.getSnowAmount()
|
|
+ any.getSnowAmount();
|
|
}
|
|
|
|
/**
|
|
* Returns this objects total mana minus the passed in {@link Mana}'s mana.
|
|
*
|
|
* @param o the object to compare to.
|
|
* @return this objects total mana minus the passed in {@link Mana}'s mana.
|
|
*/
|
|
@Override
|
|
public int compareTo(final Mana o) {
|
|
return this.count() - o.count();
|
|
}
|
|
|
|
/**
|
|
* Returns if this objects mana contains any number of the passed in
|
|
* {@link Mana}'s mana.
|
|
*
|
|
* @param mana the mana to check for
|
|
* @return true if this contains any values that mana has
|
|
*/
|
|
public boolean contains(final Mana mana) {
|
|
if (mana.white.getAmount() > 0 && this.white.getAmount() > 0) {
|
|
return true;
|
|
}
|
|
if (mana.blue.getAmount() > 0 && this.blue.getAmount() > 0) {
|
|
return true;
|
|
}
|
|
if (mana.black.getAmount() > 0 && this.black.getAmount() > 0) {
|
|
return true;
|
|
}
|
|
if (mana.red.getAmount() > 0 && this.red.getAmount() > 0) {
|
|
return true;
|
|
}
|
|
if (mana.green.getAmount() > 0 && this.green.getAmount() > 0) {
|
|
return true;
|
|
}
|
|
if (mana.colorless.getAmount() > 0 && this.colorless.getAmount() > 0) {
|
|
return true;
|
|
}
|
|
if (mana.generic.getAmount() > 0 && this.count() > 0) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public boolean containsAny(final Mana mana) {
|
|
return containsAny(mana, false);
|
|
}
|
|
|
|
/**
|
|
* Returns if this objects mana contains any coloured mana the same as the
|
|
* passed in {@link Mana}'s mana.
|
|
*
|
|
* @param mana the mana to check for
|
|
* @param includeColorless also check for colorless
|
|
* @return true if this contains any of the same type of coloured mana that
|
|
* this has
|
|
*/
|
|
public boolean containsAny(final Mana mana, boolean includeColorless) {
|
|
if (mana.white.getAmount() > 0 && this.white.getAmount() > 0) {
|
|
return true;
|
|
} else if (mana.blue.getAmount() > 0 && this.blue.getAmount() > 0) {
|
|
return true;
|
|
} else if (mana.black.getAmount() > 0 && this.black.getAmount() > 0) {
|
|
return true;
|
|
} else if (mana.red.getAmount() > 0 && this.red.getAmount() > 0) {
|
|
return true;
|
|
} else if (mana.green.getAmount() > 0 && this.green.getAmount() > 0) {
|
|
return true;
|
|
} else if (mana.colorless.getAmount() > 0 && this.colorless.getAmount() > 0 && includeColorless) {
|
|
return true;
|
|
} else if (mana.any.getAmount() > 0 && this.count() > 0) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns the total count of mana in this object as specified by the passed
|
|
* in {@link ColoredManaSymbol}.
|
|
*
|
|
* @param color the color to return the count for.
|
|
* @return the total count of mana in this object as specified by the passed
|
|
* in {@link ColoredManaSymbol}.
|
|
*/
|
|
public int getColor(final ColoredManaSymbol color) {
|
|
if (color == ColoredManaSymbol.W) {
|
|
return white.getAmount();
|
|
}
|
|
if (color == ColoredManaSymbol.U) {
|
|
return blue.getAmount();
|
|
}
|
|
if (color == ColoredManaSymbol.B) {
|
|
return black.getAmount();
|
|
}
|
|
if (color == ColoredManaSymbol.R) {
|
|
return red.getAmount();
|
|
}
|
|
if (color == ColoredManaSymbol.G) {
|
|
return green.getAmount();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Returns the total count of mana in this object as specified by the passed
|
|
* in {@link ManaType}.
|
|
*
|
|
* @param manaType the type to return the count for.
|
|
* @return the total count of mana in this object as specified by the passed
|
|
* in {@link ManaType}.
|
|
*/
|
|
public int get(final ManaType manaType) {
|
|
switch (manaType) {
|
|
case WHITE:
|
|
return white.getAmount();
|
|
case BLUE:
|
|
return blue.getAmount();
|
|
case BLACK:
|
|
return black.getAmount();
|
|
case RED:
|
|
return red.getAmount();
|
|
case GREEN:
|
|
return green.getAmount();
|
|
case COLORLESS:
|
|
return generic.getAmount() + colorless.getAmount();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Set the color of mana specified by the passed in {@link ManaType} to
|
|
* {@code amount} .
|
|
*
|
|
* @param manaType the color of the mana to set
|
|
* @param amount the value to set the mana too
|
|
*/
|
|
public void set(final ManaType manaType, final int amount) {
|
|
switch (manaType) {
|
|
case WHITE:
|
|
setWhite(amount);
|
|
break;
|
|
case BLUE:
|
|
setBlue(amount);
|
|
break;
|
|
case BLACK:
|
|
setBlack(amount);
|
|
break;
|
|
case RED:
|
|
setRed(amount);
|
|
break;
|
|
case GREEN:
|
|
setGreen(amount);
|
|
break;
|
|
case COLORLESS:
|
|
setColorless(amount);
|
|
break;
|
|
default:
|
|
throw new IllegalArgumentException("Unknown color: " + manaType);
|
|
}
|
|
}
|
|
|
|
public void setFlag(boolean flag) {
|
|
this.flag = flag;
|
|
}
|
|
|
|
public boolean getFlag() {
|
|
return flag;
|
|
}
|
|
|
|
/**
|
|
* Sets this objects mana to that of the passed in {@link Mana}
|
|
*
|
|
* @param mana the mana to set this object to.
|
|
*/
|
|
public void setToMana(final Mana mana) {
|
|
this.any = mana.any.copy();
|
|
this.white = mana.white.copy();
|
|
this.blue = mana.blue.copy();
|
|
this.black = mana.black.copy();
|
|
this.red = mana.red.copy();
|
|
this.green = mana.green.copy();
|
|
this.colorless = mana.colorless.copy();
|
|
this.generic = mana.generic.copy();
|
|
}
|
|
|
|
/**
|
|
* Returns if the passed in {@link Mana} values are equal to this objects.
|
|
*
|
|
* @param mana the {@link Mana} to compare to.
|
|
* @return if the passed in {@link Mana} values are equal to this object.
|
|
*/
|
|
public boolean equalManaValue(final Mana mana) {
|
|
return this.any.equals(mana.any)
|
|
&& this.white.equals(mana.white)
|
|
&& this.blue.equals(mana.blue)
|
|
&& this.black.equals(mana.black)
|
|
&& this.red.equals(mana.red)
|
|
&& this.green.equals(mana.green)
|
|
&& this.colorless.equals(mana.colorless)
|
|
&& this.generic.equals(mana.generic);
|
|
}
|
|
|
|
/**
|
|
* Returns if this {@link Mana} object has more than or equal values of mana
|
|
* as the passed in {@link Mana} object. Ignores {Any} mana to prevent
|
|
* endless iterations.
|
|
*
|
|
* @param mana the mana to compare with
|
|
* @return if this object has more than or equal mana to the passed in
|
|
* {@link Mana}.
|
|
*/
|
|
public boolean includesMana(Mana mana) {
|
|
return this.white.getAmount() >= mana.white.getAmount()
|
|
&& this.blue.getAmount() >= mana.blue.getAmount()
|
|
&& this.black.getAmount() >= mana.black.getAmount()
|
|
&& this.red.getAmount() >= mana.red.getAmount()
|
|
&& this.green.getAmount() >= mana.green.getAmount()
|
|
&& this.colorless.getAmount() >= mana.colorless.getAmount()
|
|
&& (this.generic.getAmount() >= mana.generic.getAmount()
|
|
|| this.countColored() + this.colorless.getAmount() >= mana.count());
|
|
|
|
}
|
|
|
|
/**
|
|
* Returns the mana that is more colored or has a greater amount but does
|
|
* not contain one less mana in any color but generic if you call with
|
|
* {1}{W}{R} and {G}{W}{R} you get back {G}{W}{R} if you call with {G}{W}{R}
|
|
* and {G}{W}{R} you get back {G}{W}{R} if you call with {G}{W}{B} and
|
|
* {G}{W}{R} you get back null
|
|
*
|
|
* @param mana1
|
|
* @param mana2
|
|
* @return
|
|
*/
|
|
public static Mana getMoreValuableMana(final Mana mana1, final Mana mana2) {
|
|
String conditionString1 = "";
|
|
String conditionString2 = "";
|
|
if (mana1 instanceof ConditionalMana) {
|
|
conditionString1 = ((ConditionalMana) mana1).getConditionString();
|
|
}
|
|
if (mana2 instanceof ConditionalMana) {
|
|
conditionString2 = ((ConditionalMana) mana2).getConditionString();
|
|
}
|
|
if (!conditionString1.equals(conditionString2)) {
|
|
return null;
|
|
}
|
|
Mana moreMana;
|
|
Mana lessMana;
|
|
if (mana2.countColored() > mana1.countColored() || mana2.getAny() > mana1.getAny() || mana2.count() > mana1.count()) {
|
|
moreMana = mana2;
|
|
lessMana = mana1;
|
|
} else {
|
|
moreMana = mana1;
|
|
lessMana = mana2;
|
|
}
|
|
int anyDiff = mana2.getAny() - mana1.getAny();
|
|
if (lessMana.getWhite() > moreMana.getWhite()) {
|
|
anyDiff -= lessMana.getWhite() - moreMana.getWhite();
|
|
if (anyDiff < 0) {
|
|
return null;
|
|
}
|
|
}
|
|
if (lessMana.getRed() > moreMana.getRed()) {
|
|
anyDiff -= lessMana.getRed() - moreMana.getRed();
|
|
if (anyDiff < 0) {
|
|
return null;
|
|
}
|
|
}
|
|
if (lessMana.getGreen() > moreMana.getGreen()) {
|
|
anyDiff -= lessMana.getGreen() - moreMana.getGreen();
|
|
if (anyDiff < 0) {
|
|
return null;
|
|
}
|
|
}
|
|
if (lessMana.getBlue() > moreMana.getBlue()) {
|
|
anyDiff -= lessMana.getBlue() - moreMana.getBlue();
|
|
if (anyDiff < 0) {
|
|
return null;
|
|
}
|
|
}
|
|
if (lessMana.getBlack() > moreMana.getBlack()) {
|
|
anyDiff -= lessMana.getBlack() - moreMana.getBlack();
|
|
if (anyDiff < 0) {
|
|
return null;
|
|
}
|
|
}
|
|
if (lessMana.getColorless() > moreMana.getColorless()) {
|
|
return null; // Any (color) can't produce colorless mana
|
|
}
|
|
if (lessMana.getAny() > moreMana.getAny()) {
|
|
return null;
|
|
}
|
|
return moreMana;
|
|
}
|
|
|
|
/**
|
|
* Returns the total count of mana colors that have at least one.
|
|
*
|
|
* @return the total count of mana colors that have at least one.
|
|
*/
|
|
public int getDifferentColors() {
|
|
int count = 0;
|
|
if (white.getAmount() > 0) {
|
|
count++;
|
|
}
|
|
if (blue.getAmount() > 0) {
|
|
count++;
|
|
}
|
|
if (black.getAmount() > 0) {
|
|
count++;
|
|
}
|
|
if (red.getAmount() > 0) {
|
|
count++;
|
|
}
|
|
if (green.getAmount() > 0) {
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) return true;
|
|
if (o == null || getClass() != o.getClass()) {
|
|
return false;
|
|
}
|
|
Mana mana = (Mana) o;
|
|
return flag == mana.flag
|
|
&& Objects.equals(white, mana.white)
|
|
&& Objects.equals(blue, mana.blue)
|
|
&& Objects.equals(black, mana.black)
|
|
&& Objects.equals(red, mana.red)
|
|
&& Objects.equals(green, mana.green)
|
|
&& Objects.equals(generic, mana.generic)
|
|
&& Objects.equals(colorless, mana.colorless)
|
|
&& Objects.equals(any, mana.any);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(white, blue, black, red, green, generic, colorless, any, flag);
|
|
}
|
|
|
|
/**
|
|
* Checks that the {@code value} passed in is not less than 0. If the value
|
|
* is negative, it is logged and 0 is returned.
|
|
*
|
|
* @param value the value to check.
|
|
* @param name the name of the value to check. Used to make logging of the
|
|
* {@code value} easier
|
|
* @return the {@code value} passed in, unless it is minus, in which case 0
|
|
* is returned.
|
|
*/
|
|
private static int notNegative(int value, final String name) {
|
|
if (value < 0) {
|
|
logger.info(name + " can not be less than 0. Passed in: " + value + " Defaulting to 0.");
|
|
value = 0;
|
|
}
|
|
return value;
|
|
}
|
|
}
|