mirror of
https://github.com/correl/mage.git
synced 2024-11-14 19:19:32 +00:00
Fixed tests with multiple X values
This commit is contained in:
parent
b64a75aa4b
commit
0e2cfb7def
11 changed files with 102 additions and 48 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in a new issue