Fixed tests with multiple X values

This commit is contained in:
Oleg Agafonov 2019-06-06 21:07:51 +04:00
parent b64a75aa4b
commit 0e2cfb7def
11 changed files with 102 additions and 48 deletions

View file

@ -129,11 +129,12 @@ public class SimulatedPlayer2 extends ComputerPlayer {
}
}
if (variableManaCost != null) {
int multiplier = variableManaCost.getMultiplier();
int xInstancesCount = variableManaCost.getXInstancesCount();
for (int mana = variableManaCost.getMinX(); mana <= numAvailable; mana++) {
if (mana % multiplier == 0) { // use only values dependant from multiplier
int xAmount = mana / multiplier;
if (mana % xInstancesCount == 0) { // use only values dependant from multiplier
// find possible X value to pay
int xAnnounceValue = mana / xInstancesCount;
Ability newAbility = ability.copy();
VariableManaCost varCost = null;
for (ManaCost cost : newAbility.getManaCostsToPay()) {
@ -142,13 +143,13 @@ public class SimulatedPlayer2 extends ComputerPlayer {
break; // only one VariableManCost per spell (or is it possible to have more?)
}
}
// add the specific value for x
// find real X value after replace events
int xMultiplier = 1;
if (newAbility instanceof AbilityImpl) {
xMultiplier = ((AbilityImpl) newAbility).handleManaXMultiplier(game, xMultiplier);
}
newAbility.getManaCostsToPay().add(new ManaCostsImpl(new StringBuilder("{").append(xAmount).append('}').toString()));
newAbility.getManaCostsToPay().setX(xAmount, xMultiplier);
newAbility.getManaCostsToPay().add(new ManaCostsImpl(new StringBuilder("{").append(xAnnounceValue).append('}').toString()));
newAbility.getManaCostsToPay().setX(xAnnounceValue * xMultiplier, xAnnounceValue * xInstancesCount);
if (varCost != null) {
varCost.setPaid();
}

View file

@ -1,8 +1,10 @@
package org.mage.test.cards.continuous;
import mage.abilities.costs.mana.VariableManaCost;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -167,4 +169,42 @@ public class UnboundFlourishingTest extends CardTestPlayerBase {
assertAllCommandsUsed();
}
@Test
public void test_VariableManaCost() {
// VariableManaCost contains:
// - number of {X} instances (1, 2, 3)
// - final X value after all replace events
// - total number of pays
// getAmount() must return final X value
// setAmount() must setup final X value
// test example: {X}{X}, X=3, double X effect from replace event
int xInstancesCount = 2;
int xAnnouncedValue = 3;
int xMultiplier = 2;
VariableManaCost cost = new VariableManaCost(xInstancesCount);
cost.setAmount(xAnnouncedValue * xMultiplier, xAnnouncedValue * xInstancesCount);
Assert.assertEquals("instances count", xInstancesCount, cost.getXInstancesCount());
Assert.assertEquals("boosted X value", xAnnouncedValue * xMultiplier, cost.getAmount());
}
@Test
public void test_MultipleXInstances() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
// Chalice of the Void enters the battlefield with X charge counters on it.
// Whenever a player casts a spell with converted mana cost equal to the number of charge counters on Chalice of the Void, counter that spell.
addCard(Zone.HAND, playerA, "Chalice of the Void", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chalice of the Void");
setChoice(playerA, "X=1");
checkPermanentCounters("after", 1, PhaseStep.BEGIN_COMBAT, playerA, "Chalice of the Void", CounterType.CHARGE, 1);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
}
}

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.single;
import mage.constants.PhaseStep;
@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class ChaliceOfTheVoidTest extends CardTestPlayerBase {
@ -19,6 +17,7 @@ public class ChaliceOfTheVoidTest extends CardTestPlayerBase {
* cmc should be 2 in this case, it shouldnt be countered.
* http://boardgames.stackexchange.com/questions/7327/what-is-the-converted-mana-cost-of-a-spell-with-x-when-cast-with-the-miracle-m
*/
@Test
public void testX1CountsFor2CMC() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
@ -31,8 +30,10 @@ public class ChaliceOfTheVoidTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chalice of the Void");
setChoice(playerA, "X=1");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Chalice of the Void", 2);

View file

@ -256,7 +256,7 @@ public abstract class AbilityImpl implements Ability {
VariableManaCost xCosts = new VariableManaCost();
// no x events - rules from Unbound Flourishing:
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
xCosts.setAmount(xValue);
xCosts.setAmount(xValue, xValue);
this.getManaCostsToPay().add(xCosts);
} else {
this.getManaCostsToPay().clear();
@ -505,7 +505,7 @@ public abstract class AbilityImpl implements Ability {
// set the xcosts to paid
// no x events - rules from Unbound Flourishing:
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
variableCost.setAmount(xValue); //
variableCost.setAmount(xValue, xValue);
((Cost) variableCost).setPaid();
String message = controller.getLogName() + " announces a value of " + xValue + " (" + variableCost.getActionText() + ')';
announceString.append(message);
@ -574,7 +574,7 @@ public abstract class AbilityImpl implements Ability {
if (!noMana) {
xValue = controller.announceXMana(variableManaCost.getMinX(), variableManaCost.getMaxX(), xValueMultiplier,
"Announce the value for " + variableManaCost.getText(), game, this);
int amountMana = xValue * variableManaCost.getMultiplier();
int amountMana = xValue * variableManaCost.getXInstancesCount();
StringBuilder manaString = threadLocalBuilder.get();
if (variableManaCost.getFilter() == null || variableManaCost.getFilter().isGeneric()) {
manaString.append('{').append(amountMana).append('}');
@ -603,7 +603,7 @@ public abstract class AbilityImpl implements Ability {
}
}
manaCostsToPay.add(new ManaCostsImpl(manaString.toString()));
manaCostsToPay.setX(xValue, xValueMultiplier);
manaCostsToPay.setX(xValue * xValueMultiplier, amountMana);
}
variableManaCost.setPaid();
}

View file

@ -162,13 +162,15 @@ public class SpellAbility extends ActivatedAbilityImpl {
return 0;
}
// mana cost instances
for (ManaCost manaCost : card.getManaCost()) {
if (manaCost instanceof VariableManaCost) {
xMultiplier = ((VariableManaCost) manaCost).getMultiplier();
xMultiplier = ((VariableManaCost) manaCost).getXInstancesCount();
break;
}
}
// mana cost final X value
boolean hasNonManaXCost = false;
for (Cost cost : getCosts()) {
if (cost instanceof VariableCost) {

View file

@ -1,27 +1,26 @@
package mage.abilities.costs;
import mage.abilities.Ability;
import mage.game.Game;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public interface VariableCost {
/**
* Returns the variable amount if already set
*
*
* @return
*/
int getAmount();
/**
* Sets the variable amount
*
* @param amount
* @param xValue - value of X
* @param xPay - total value of pays for X (X * xMultiplier * xInstancesCount)
*/
void setAmount(int amount);
void setAmount(int xValue, int xPay);
/**
* returns the action text (e.g. "creature cards to exile from your hand", "life to pay")
@ -29,6 +28,7 @@ public interface VariableCost {
* @return
*/
String getActionText();
/**
* Return a min value to announce
*
@ -37,6 +37,7 @@ public interface VariableCost {
* @return
*/
int getMinValue(Ability source, Game game);
/**
* Returns a max value to announce
*
@ -45,13 +46,16 @@ public interface VariableCost {
* @return
*/
int getMaxValue(Ability source, Game game);
/**
* Asks the controller to announce the variable value
*
* @param source
* @param game
* @return
*/
int announceXValue(Ability source, Game game);
/**
* Returns a fixed cost with the announced variable value
*

View file

@ -1,7 +1,5 @@
package mage.abilities.costs;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.mana.ManaAbility;
import mage.game.Game;
@ -10,8 +8,9 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.Targets;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public abstract class VariableCostImpl implements Cost, VariableCost {
@ -29,10 +28,9 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
}
/**
*
* @param xText string for the defined value
* @param xText string for the defined value
* @param actionText what happens with the value (e.g. "to tap", "to exile
* from your graveyard")
* from your graveyard")
*/
public VariableCostImpl(String xText, String actionText) {
id = UUID.randomUUID();
@ -125,8 +123,8 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
}
@Override
public void setAmount(int amount) {
amountPaid = amount;
public void setAmount(int xValue, int xPay) {
amountPaid = xPay;
}
@Override

View file

@ -69,7 +69,7 @@ public class ExileFromHandCost extends CostImpl {
VariableManaCost vmc = new VariableManaCost();
// no x events - rules from Unbound Flourishing:
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
vmc.setAmount(cmc);
vmc.setAmount(cmc, cmc);
vmc.setPaid();
ability.getManaCostsToPay().add(vmc);
}

View file

@ -24,10 +24,10 @@ public interface ManaCosts<T extends ManaCost> extends List<T>, ManaCost {
int getX();
/**
* @param xValue announced X value
* @param xMultiplier special X multiplier to change announced X value without pay increase, see Unbound Flourishing
* @param xValue final X value -- announced X * xMultiplier, where xMultiplier can be changed by replace events like Unbound Flourishing)
* @param xPay real number of pay amount (x * xMultiplier * xInstances, where xInstances is number of {X} in pay like 1, 2, 3)
*/
void setX(int xValue, int xMultiplier);
void setX(int xValue, int xPay);
void load(String mana);

View file

@ -229,10 +229,10 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
}
@Override
public void setX(int xValue, int xMultiplier) {
public void setX(int xValue, int xPay) {
List<VariableCost> variableCosts = getVariableCosts();
if (!variableCosts.isEmpty()) {
variableCosts.get(0).setAmount(xValue * xMultiplier);
variableCosts.get(0).setAmount(xValue, xPay);
}
}
@ -344,7 +344,12 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
if (player != null) {
game.undo(playerId);
this.clearPaid();
this.setX(referenceCosts.getX(), 1); // TODO: checks Word of Command with Unbound Flourishing's X multiplier
// TODO: checks Word of Command with Unbound Flourishing's X multiplier
// TODO: checks Word of Command with {X}{X} cards
int xValue = referenceCosts.getX();
this.setX(xValue, xValue);
player.getManaPool().restoreMana(pool.getPoolBookmark());
game.bookmarkState();
}

View file

@ -1,4 +1,3 @@
package mage.abilities.costs.mana;
import mage.Mana;
@ -11,12 +10,12 @@ import mage.game.Game;
import mage.players.ManaPool;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class VariableManaCost extends ManaCostImpl implements VariableCost {
protected int multiplier;
protected int xInstancesCount; // number of {X}
protected int xValue = 0; // final X value after announce and replace events
protected FilterMana filter;
protected int minX = 0;
protected int maxX = Integer.MAX_VALUE;
@ -25,15 +24,16 @@ public class VariableManaCost extends ManaCostImpl implements VariableCost {
this(1);
}
public VariableManaCost(int multiplier) {
this.multiplier = multiplier;
public VariableManaCost(int xInstancesCount) {
this.xInstancesCount = xInstancesCount;
this.cost = new Mana();
options.add(new Mana());
}
public VariableManaCost(final VariableManaCost manaCost) {
super(manaCost);
this.multiplier = manaCost.multiplier;
this.xInstancesCount = manaCost.xInstancesCount;
this.xValue = manaCost.xValue;
if (manaCost.filter != null) {
this.filter = manaCost.filter.copy();
}
@ -55,9 +55,9 @@ public class VariableManaCost extends ManaCostImpl implements VariableCost {
@Override
public String getText() {
if (multiplier > 1) {
StringBuilder symbol = new StringBuilder(multiplier);
for (int i = 0; i < multiplier; i++) {
if (xInstancesCount > 1) {
StringBuilder symbol = new StringBuilder(xInstancesCount);
for (int i = 0; i < xInstancesCount; i++) {
symbol.append("{X}");
}
return symbol.toString();
@ -73,12 +73,15 @@ public class VariableManaCost extends ManaCostImpl implements VariableCost {
@Override
public int getAmount() {
return payment.count() / multiplier;
// must return X value
//return payment.count() / multiplier;
return this.xValue;
}
@Override
public void setAmount(int amount) {
payment.setGeneric(amount);
public void setAmount(int xValue, int xPay) {
this.xValue = xValue;
payment.setGeneric(xPay);
}
@Override
@ -91,8 +94,8 @@ public class VariableManaCost extends ManaCostImpl implements VariableCost {
return new VariableManaCost(this);
}
public int getMultiplier() {
return multiplier;
public int getXInstancesCount() {
return this.xInstancesCount;
}
public int getMinX() {