mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
* Fixed some more available mana calculation problems. Mana of the pool is now taken into account (e.g. Coal Golem problem). Crucible of the Spirit Dragon - Conditional mana curretnly not handled correctly in available mana calculation. Crystalline Crawler works now.Related to #6698.
This commit is contained in:
parent
e3b2fa1240
commit
3a82840e66
16 changed files with 253 additions and 89 deletions
|
@ -1,5 +1,9 @@
|
|||
package mage.player.ai;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import mage.ConditionalMana;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
|
@ -57,11 +61,6 @@ import mage.util.TournamentUtil;
|
|||
import mage.util.TreeNode;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* suitable for two player games and some multiplayer games
|
||||
*
|
||||
|
@ -137,8 +136,6 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
// - target.getTargetController(), this.getId() -- player that must makes choices (must be same with this.getId)
|
||||
// - target.getAbilityController(), abilityControllerId -- affected player/controller for all actions/filters
|
||||
// - affected controler can be different from target controller (another player makes choices for controller)
|
||||
|
||||
|
||||
// sometimes a target selection can be made from a player that does not control the ability
|
||||
UUID abilityControllerId = playerId;
|
||||
if (target.getTargetController() != null
|
||||
|
@ -478,7 +475,6 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
// target - real target, make all changes and add targets to it
|
||||
// target.getOriginalTarget() - copy spell effect replaces original target with TargetWithAdditionalFilter
|
||||
// use originalTarget to get filters and target class info
|
||||
|
||||
// source can be null (as example: legendary rule permanent selection)
|
||||
UUID sourceId = source != null ? source.getSourceId() : null;
|
||||
|
||||
|
@ -731,9 +727,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
|
||||
// TODO: in multiplayer game there many opponents - if random opponents don't have targets then AI must use next opponent, but it skips
|
||||
// (e.g. you randomOpponentId must be replaced by List<UUID> randomOpponents)
|
||||
|
||||
// normal cycle (good for you, bad for opponents)
|
||||
|
||||
// possible good/bad permanents
|
||||
if (outcome.isGood()) {
|
||||
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
|
||||
|
@ -1312,7 +1306,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
playableAbilities.clear();
|
||||
Set<Card> nonLands = hand.getCards(new FilterNonlandCard(), game);
|
||||
ManaOptions available = getManaAvailable(game);
|
||||
available.addMana(manaPool.getMana());
|
||||
// available.addMana(manaPool.getMana());
|
||||
|
||||
for (Card card : nonLands) {
|
||||
ManaOptions options = card.getManaCost().getOptions();
|
||||
|
@ -2562,7 +2556,6 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
protected List<Permanent> threats(UUID playerId, UUID sourceId, FilterPermanent filter, Game game, List<UUID> targets) {
|
||||
return threats(playerId, sourceId, filter, game, targets, true);
|
||||
}
|
||||
|
@ -2688,7 +2681,6 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
return before != after;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets a possible target player
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -11,6 +10,7 @@ import mage.abilities.condition.Condition;
|
|||
import mage.abilities.costs.common.RemoveVariableCountersSourceCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
|
@ -31,13 +31,13 @@ import mage.game.Game;
|
|||
public final class CrucibleOfTheSpiritDragon extends CardImpl {
|
||||
|
||||
public CrucibleOfTheSpiritDragon(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.LAND},"");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||
|
||||
// {T}: Add {C}.
|
||||
this.addAbility(new ColorlessManaAbility());
|
||||
|
||||
// {1}, {T}: Put a storage counter on Crucible of the Spirit Dragon.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()),new GenericManaCost(1));
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()), new GenericManaCost(1));
|
||||
ability.addCost(new TapSourceCost());
|
||||
this.addAbility(ability);
|
||||
|
||||
|
@ -45,9 +45,10 @@ public final class CrucibleOfTheSpiritDragon extends CardImpl {
|
|||
ability = new ConditionalAnyColorManaAbility(
|
||||
new TapSourceCost(),
|
||||
RemovedCountersForCostValue.instance,
|
||||
new CountersSourceCount(CounterType.STORAGE),
|
||||
new CrucibleOfTheSpiritDragonManaBuilder(),
|
||||
false
|
||||
);
|
||||
);
|
||||
ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance()));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
@ -94,4 +95,4 @@ class CrucibleOfTheSpiritDragonManaCondition implements Condition {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -8,6 +7,7 @@ import mage.abilities.common.SimpleActivatedAbility;
|
|||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.dynamicvalue.common.ColorsOfManaSpentToCastCount;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.mana.AnyColorManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -30,13 +30,14 @@ public final class CrystallineCrawler extends CardImpl {
|
|||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// <i>Converge</i> — Crystalline Crawler enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.
|
||||
// Converge - Crystalline Crawler enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.
|
||||
this.addAbility(new EntersBattlefieldAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(), ColorsOfManaSpentToCastCount.getInstance(), true),
|
||||
null, "<i>Converge</i> — {this} enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.", null));
|
||||
|
||||
// Remove a +1/+1 counter from Crystalline Crawler: Add one mana of any color.
|
||||
this.addAbility(new AnyColorManaAbility(new RemoveCountersSourceCost(CounterType.P1P1.createInstance(1))));
|
||||
this.addAbility(new AnyColorManaAbility(new RemoveCountersSourceCost(CounterType.P1P1.createInstance(1)),
|
||||
new CountersSourceCount(CounterType.P1P1), false));
|
||||
|
||||
// {T}: Put a +1/+1 counter on Crystalline Crawler.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), new TapSourceCost()));
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.d;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -7,16 +6,19 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
|
||||
import mage.abilities.dynamicvalue.LimitedDynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.effects.common.ExileTargetEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
||||
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.common.FilterLandCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
|
@ -37,17 +39,18 @@ public final class DeathriteShaman extends CardImpl {
|
|||
}
|
||||
|
||||
public DeathriteShaman(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B/G}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B/G}");
|
||||
this.subtype.add(SubType.ELF);
|
||||
this.subtype.add(SubType.SHAMAN);
|
||||
|
||||
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// {T}: Exile target land card from a graveyard. Add one mana of any color.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new TapSourceCost());
|
||||
ability.addEffect(new AddManaOfAnyColorEffect());
|
||||
// Because this is no mana ability, this mana will not be calculated during available mana calculation
|
||||
ability.addEffect(new AddManaOfAnyColorEffect(1, new LimitedDynamicValue(1,
|
||||
new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_LAND)), false));
|
||||
ability.addTarget(new TargetCardInGraveyard(new FilterLandCard("land card from a graveyard")));
|
||||
this.addAbility(ability);
|
||||
|
||||
|
@ -74,4 +77,4 @@ public final class DeathriteShaman extends CardImpl {
|
|||
public DeathriteShaman copy() {
|
||||
return new DeathriteShaman(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@ import mage.abilities.effects.common.DoIfCostPaid;
|
|||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.mana.AddConditionalManaOfAnyColorEffect;
|
||||
import mage.abilities.mana.conditional.ConditionalSpellManaBuilder;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.game.permanent.token.DragonToken2;
|
||||
|
||||
|
@ -46,6 +46,7 @@ public final class SarkhanFireblood extends CardImpl {
|
|||
// +1: Add two mana of any combination of colors. Spend this mana only to cast Dragon spells.
|
||||
this.addAbility(new LoyaltyAbility(
|
||||
new AddConditionalManaOfAnyColorEffect(
|
||||
StaticValue.get(2),
|
||||
StaticValue.get(2),
|
||||
new ConditionalSpellManaBuilder(filter),
|
||||
false
|
||||
|
|
|
@ -45,7 +45,7 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
|
|||
assertHandCount(playerA, "Through the Breach", 1);
|
||||
assertPermanentCount(playerA, "Silvercoat Lion", 1);
|
||||
assertAbility(playerA, "Silvercoat Lion", HasteAbility.getInstance(), true);
|
||||
Assert.assertEquals("All available mana has to be used", 0, playerA.getManaAvailable(currentGame).size());
|
||||
Assert.assertEquals("All available mana has to be used", "[]", playerA.getManaAvailable(currentGame).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -29,7 +29,7 @@ public class SasayaOrochiAscendantTest extends CardTestPlayerBase {
|
|||
addCard(Zone.HAND, playerA, "Upwelling", 1); // Enchantment {3}{G}
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reveal your hand: If you have seven or more land cards in your hand, flip");
|
||||
|
||||
|
||||
activateManaAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}: Add {G}");
|
||||
activateManaAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}: Add {G}");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Upwelling");
|
||||
|
@ -38,7 +38,7 @@ public class SasayaOrochiAscendantTest extends CardTestPlayerBase {
|
|||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Sasaya's Essence", 1);
|
||||
assertPermanentCount(playerA, "Upwelling", 1);
|
||||
|
||||
|
@ -48,11 +48,11 @@ public class SasayaOrochiAscendantTest extends CardTestPlayerBase {
|
|||
assertDuplicatedManaOptions(manaOptions);
|
||||
|
||||
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
|
||||
assertManaOptions("{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{G}{G}{G}{G}{G}", manaOptions);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@Test
|
||||
public void testSasayasEssence2() {
|
||||
addCard(Zone.HAND, playerA, "Plains", 7);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Brushland", 3);
|
||||
|
@ -73,26 +73,25 @@ public class SasayaOrochiAscendantTest extends CardTestPlayerBase {
|
|||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Sasaya's Essence", 1);
|
||||
assertPermanentCount(playerA, "Upwelling", 1);
|
||||
|
||||
assertManaPool(playerA, ManaType.GREEN, 2);
|
||||
|
||||
assertLife(playerA, 18);
|
||||
|
||||
|
||||
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
|
||||
assertDuplicatedManaOptions(manaOptions);
|
||||
|
||||
Assert.assertEquals("mana variations don't fit", 3, manaOptions.size());
|
||||
assertManaOptions("{C}{C}{C}", manaOptions);
|
||||
assertManaOptions("{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{W}{W}{W}", manaOptions);
|
||||
assertManaOptions("{C}{C}{C}{G}{G}", manaOptions);
|
||||
assertManaOptions("{G}{G}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{W}{W}{W}{G}{G}", manaOptions);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSasayasEssence3() {
|
||||
addCard(Zone.HAND, playerA, "Plains", 7);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||
|
@ -115,22 +114,22 @@ public class SasayaOrochiAscendantTest extends CardTestPlayerBase {
|
|||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Sasaya's Essence", 1);
|
||||
assertPermanentCount(playerA, "Upwelling", 1);
|
||||
|
||||
assertManaPool(playerA, ManaType.GREEN, 2);
|
||||
|
||||
assertLife(playerA, 20);
|
||||
|
||||
|
||||
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
|
||||
assertDuplicatedManaOptions(manaOptions);
|
||||
|
||||
Assert.assertEquals("mana variations don't fit", 4, manaOptions.size());
|
||||
assertManaOptions("{R}{R}{R}{R}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{R}{R}{R}{G}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{R}{R}{G}{G}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{R}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||
}
|
||||
|
||||
assertManaOptions("{R}{R}{R}{R}{G}{G}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{R}{R}{R}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{R}{R}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{R}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import mage.constants.PhaseStep;
|
|||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
import static org.mage.test.utils.ManaOptionsTestUtils.assertManaOptions;
|
||||
|
@ -199,4 +200,44 @@ public class TappedForManaRelatedTest extends CardTestPlayerBase {
|
|||
assertManaOptions("{U}", manaOptions);
|
||||
assertManaOptions("{R}", manaOptions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestCrystallineCrawler() {
|
||||
setStrictChooseMode(true);
|
||||
// Converge - Crystalline Crawler enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.
|
||||
// Remove a +1/+1 counter from Crystalline Crawler: Add one mana of any color.
|
||||
// {T}: Put a +1/+1 counter on Crystalline Crawler.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Crystalline Crawler", 1);
|
||||
addCounters(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Crystalline Crawler", CounterType.P1P1, 2);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
|
||||
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
|
||||
assertManaOptions("{Any}{Any}", manaOptions);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // Because this is no mana ability, this mana will not be calculated during available mana calculation
|
||||
public void TestDeathriteShaman() {
|
||||
setStrictChooseMode(true);
|
||||
// {T}: Exile target land card from a graveyard. Add one mana of any color.
|
||||
// {B}, {T}: Exile target instant or sorcery card from a graveyard. Each opponent loses 2 life.
|
||||
// {G}, {T}: Exile target creature card from a graveyard. You gain 2 life.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Deathrite Shaman", 1);
|
||||
|
||||
addCard(Zone.GRAVEYARD, playerA, "Mountain", 3);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
|
||||
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
|
||||
assertManaOptions("{Any}", manaOptions);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.abilities.dynamicvalue;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class LimitedDynamicValue implements DynamicValue {
|
||||
|
||||
private final DynamicValue value;
|
||||
private final int limit;
|
||||
|
||||
/**
|
||||
* Returns a dynamic but with an upper limit.
|
||||
*
|
||||
* @param limit the max value the dynamic value will return
|
||||
* @param value the dynamic value to calculate the row dynamic value
|
||||
*/
|
||||
public LimitedDynamicValue(int limit, DynamicValue value) {
|
||||
this.value = value;
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
LimitedDynamicValue(final LimitedDynamicValue dynamicValue) {
|
||||
this.value = dynamicValue.value;
|
||||
this.limit = dynamicValue.limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
return Math.min(limit, value.calculate(game, sourceAbility, effect));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LimitedDynamicValue copy() {
|
||||
return new LimitedDynamicValue(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return value.getMessage();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package mage.abilities.effects.mana;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import mage.ConditionalMana;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -13,9 +15,6 @@ import mage.players.Player;
|
|||
import mage.util.CardUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
*/
|
||||
|
@ -24,20 +23,22 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect {
|
|||
private static final Logger logger = Logger.getLogger(AddConditionalManaOfAnyColorEffect.class);
|
||||
|
||||
private final DynamicValue amount;
|
||||
private final DynamicValue netAmount;
|
||||
private final ConditionalManaBuilder manaBuilder;
|
||||
private final boolean oneChoice;
|
||||
|
||||
public AddConditionalManaOfAnyColorEffect(int amount, ConditionalManaBuilder manaBuilder) {
|
||||
this(StaticValue.get(amount), manaBuilder);
|
||||
this(StaticValue.get(amount), StaticValue.get(amount), manaBuilder);
|
||||
}
|
||||
|
||||
public AddConditionalManaOfAnyColorEffect(DynamicValue amount, ConditionalManaBuilder manaBuilder) {
|
||||
this(amount, manaBuilder, true);
|
||||
public AddConditionalManaOfAnyColorEffect(DynamicValue amount, DynamicValue netAmount, ConditionalManaBuilder manaBuilder) {
|
||||
this(amount, netAmount, manaBuilder, true);
|
||||
}
|
||||
|
||||
public AddConditionalManaOfAnyColorEffect(DynamicValue amount, ConditionalManaBuilder manaBuilder, boolean oneChoice) {
|
||||
public AddConditionalManaOfAnyColorEffect(DynamicValue amount, DynamicValue netAmount, ConditionalManaBuilder manaBuilder, boolean oneChoice) {
|
||||
super();
|
||||
this.amount = amount;
|
||||
this.netAmount = netAmount;
|
||||
this.manaBuilder = manaBuilder;
|
||||
this.oneChoice = oneChoice;
|
||||
//
|
||||
|
@ -53,6 +54,7 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect {
|
|||
public AddConditionalManaOfAnyColorEffect(final AddConditionalManaOfAnyColorEffect effect) {
|
||||
super(effect);
|
||||
this.amount = effect.amount;
|
||||
this.netAmount = effect.netAmount;
|
||||
this.manaBuilder = effect.manaBuilder;
|
||||
this.oneChoice = effect.oneChoice;
|
||||
}
|
||||
|
@ -66,9 +68,16 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect {
|
|||
public List<Mana> getNetMana(Game game, Ability source) {
|
||||
List<Mana> netMana = new ArrayList<>();
|
||||
if (game != null) {
|
||||
int value = amount.calculate(game, source, this);
|
||||
if (value > 0) {
|
||||
netMana.add(Mana.AnyMana(value));
|
||||
if (game.inCheckPlayableState()) {
|
||||
int amountAvailableMana = netAmount.calculate(game, source, this);
|
||||
if (amountAvailableMana > 0) {
|
||||
netMana.add(manaBuilder.setMana(Mana.AnyMana(amountAvailableMana), source, game).build());
|
||||
}
|
||||
} else {
|
||||
int amountOfManaLeft = amount.calculate(game, source, this);
|
||||
if (amountOfManaLeft > 0) {
|
||||
netMana.add(Mana.AnyMana(amountOfManaLeft));
|
||||
}
|
||||
}
|
||||
}
|
||||
return netMana;
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
package mage.abilities.effects.mana;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.choices.ChoiceColor;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class AddManaOfAnyColorEffect extends BasicManaEffect {
|
||||
|
||||
protected final int amount;
|
||||
protected final DynamicValue netAmount;
|
||||
protected final ArrayList<Mana> netMana = new ArrayList<>();
|
||||
protected final boolean setFlag;
|
||||
|
||||
|
@ -28,8 +29,13 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
|
|||
}
|
||||
|
||||
public AddManaOfAnyColorEffect(int amount, boolean setFlag) {
|
||||
this(amount, null, setFlag);
|
||||
}
|
||||
|
||||
public AddManaOfAnyColorEffect(int amount, DynamicValue netAmount, boolean setFlag) {
|
||||
super(new Mana(0, 0, 0, 0, 0, 0, amount, 0));
|
||||
this.amount = amount;
|
||||
this.netAmount = netAmount;
|
||||
netMana.add(Mana.AnyMana(amount));
|
||||
this.staticText = "add " + CardUtil.numberToText(amount) + " mana of any " + (amount > 1 ? "one " : "") + "color";
|
||||
this.setFlag = setFlag;
|
||||
|
@ -40,6 +46,12 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
|
|||
this.amount = effect.amount;
|
||||
this.netMana.addAll(effect.netMana);
|
||||
this.setFlag = effect.setFlag;
|
||||
if (effect.netAmount == null) {
|
||||
this.netAmount = null;
|
||||
} else {
|
||||
this.netAmount = effect.netAmount.copy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,6 +61,16 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
|
|||
|
||||
@Override
|
||||
public List<Mana> getNetMana(Game game, Ability source) {
|
||||
if (game != null && game.inCheckPlayableState()) {
|
||||
if (netAmount != null) {
|
||||
int count = netAmount.calculate(game, source, this);
|
||||
Mana mana = new Mana();
|
||||
mana.setAny(count * amount);
|
||||
ArrayList<Mana> possibleNetMana = new ArrayList<>();
|
||||
possibleNetMana.add(mana);
|
||||
return possibleNetMana;
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(this.netMana);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpecialAction;
|
||||
|
@ -20,22 +21,20 @@ import mage.target.Target;
|
|||
import mage.target.TargetPlayer;
|
||||
import mage.util.ManaUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 702.131. Assist
|
||||
* <p>
|
||||
* 702.131a Assist is a static ability that modifies the rules of paying for the spell with assist (see rules 601.2g-h).
|
||||
* If the total cost to cast a spell with assist includes a generic mana component, before you activate mana
|
||||
* abilities while casting it, you may choose another player. That player has a chance to activate mana abilities.
|
||||
* Once that player chooses not to activate any more mana abilities, you have a chance to activate mana abilities.
|
||||
* Before you begin to pay the total cost of the spell, the player you chose may pay for any amount of the generic
|
||||
* mana in the spell’s total cost.
|
||||
* 702.131a Assist is a static ability that modifies the rules of paying for the
|
||||
* spell with assist (see rules 601.2g-h). If the total cost to cast a spell
|
||||
* with assist includes a generic mana component, before you activate mana
|
||||
* abilities while casting it, you may choose another player. That player has a
|
||||
* chance to activate mana abilities. Once that player chooses not to activate
|
||||
* any more mana abilities, you have a chance to activate mana abilities. Before
|
||||
* you begin to pay the total cost of the spell, the player you chose may pay
|
||||
* for any amount of the generic mana in the spell’s total cost.
|
||||
*
|
||||
* @author emerald000, JayDi85
|
||||
*/
|
||||
|
||||
|
||||
public class AssistAbility extends SimpleStaticAbility implements AlternateManaPaymentAbility {
|
||||
|
||||
private static final FilterPlayer filter = new FilterPlayer("another player");
|
||||
|
@ -107,7 +106,7 @@ public class AssistAbility extends SimpleStaticAbility implements AlternateManaP
|
|||
if (opponent != null) {
|
||||
// basic and pool, but no coditional mana
|
||||
ManaOptions availableMana = opponent.getManaAvailable(game);
|
||||
availableMana.addMana(opponent.getManaPool().getMana());
|
||||
// availableMana.addMana(opponent.getManaPool().getMana());
|
||||
for (Mana mana : availableMana) {
|
||||
if (mana.count() > 0) {
|
||||
opponentCanPayMax = Math.max(opponentCanPayMax, mana.count());
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
package mage.abilities.mana;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import mage.Mana;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.ManaEffect;
|
||||
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
public class AnyColorManaAbility extends ActivatedManaAbilityImpl {
|
||||
|
||||
|
@ -21,10 +27,39 @@ public class AnyColorManaAbility extends ActivatedManaAbilityImpl {
|
|||
this.netMana.add(new Mana(0, 0, 0, 0, 0, 0, 1, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param cost
|
||||
* @param netAmount dynamic value used during available mana calculation to
|
||||
* set the max possible amount the source can produce
|
||||
* @param setFlag
|
||||
*/
|
||||
public AnyColorManaAbility(Cost cost, DynamicValue netAmount, boolean setFlag) {
|
||||
super(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(1, netAmount, setFlag), cost);
|
||||
this.netMana.add(new Mana(0, 0, 0, 0, 0, 0, 1, 0));
|
||||
}
|
||||
|
||||
public AnyColorManaAbility(final AnyColorManaAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mana> getNetMana(Game game) {
|
||||
if (game != null && game.inCheckPlayableState()) {
|
||||
List<Mana> dynamicNetMana = new ArrayList<>();
|
||||
for (Effect effect : getEffects()) {
|
||||
if (effect instanceof ManaEffect) {
|
||||
List<Mana> effectNetMana = ((ManaEffect) effect).getNetMana(game, this);
|
||||
if (effectNetMana != null) {
|
||||
dynamicNetMana.addAll(effectNetMana);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dynamicNetMana;
|
||||
}
|
||||
return super.getNetMana(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnyColorManaAbility copy() {
|
||||
return new AnyColorManaAbility(this);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
package mage.abilities.mana;
|
||||
|
||||
import java.util.List;
|
||||
import mage.Mana;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
|
@ -11,11 +11,9 @@ import mage.abilities.mana.builder.ConditionalManaBuilder;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* For cards like:
|
||||
* {tap}: Add three mana of any one color. Spend this mana only to cast creature spells.
|
||||
* For cards like: {tap}: Add three mana of any one color. Spend this mana only
|
||||
* to cast creature spells.
|
||||
*
|
||||
* @author noxx
|
||||
*/
|
||||
|
@ -32,11 +30,11 @@ public class ConditionalAnyColorManaAbility extends ActivatedManaAbilityImpl {
|
|||
}
|
||||
|
||||
public ConditionalAnyColorManaAbility(Cost cost, int amount, ConditionalManaBuilder manaBuilder, boolean oneChoice) {
|
||||
this(cost, StaticValue.get(amount), manaBuilder, oneChoice);
|
||||
this(cost, StaticValue.get(amount), StaticValue.get(amount), manaBuilder, oneChoice);
|
||||
}
|
||||
|
||||
public ConditionalAnyColorManaAbility(Cost cost, DynamicValue amount, ConditionalManaBuilder manaBuilder, boolean oneChoice) {
|
||||
super(Zone.BATTLEFIELD, new AddConditionalManaOfAnyColorEffect(amount, manaBuilder, oneChoice), cost);
|
||||
public ConditionalAnyColorManaAbility(Cost cost, DynamicValue amount, DynamicValue netAmount, ConditionalManaBuilder manaBuilder, boolean oneChoice) {
|
||||
super(Zone.BATTLEFIELD, new AddConditionalManaOfAnyColorEffect(amount, netAmount, manaBuilder, oneChoice), cost);
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
|
@ -60,7 +58,6 @@ public class ConditionalAnyColorManaAbility extends ActivatedManaAbilityImpl {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ConditionalAnyColorManaAbility copy() {
|
||||
return new ConditionalAnyColorManaAbility(this);
|
||||
|
|
|
@ -22,6 +22,9 @@ import org.apache.log4j.Logger;
|
|||
* be used to find all the ways to pay a mana cost or all the different mana
|
||||
* combinations available to a player
|
||||
*
|
||||
* TODO: Conditional Mana is not supported yet. The mana adding removes the
|
||||
* condition of conditional mana
|
||||
*
|
||||
*/
|
||||
public class ManaOptions extends ArrayList<Mana> {
|
||||
|
||||
|
|
|
@ -2881,6 +2881,11 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
game.setCheckPlayableState(true);
|
||||
|
||||
ManaOptions availableMana = new ManaOptions();
|
||||
availableMana.addMana(manaPool.getMana());
|
||||
// conditional mana
|
||||
for (ConditionalMana conditionalMana : manaPool.getConditionalMana()) {
|
||||
availableMana.addMana(conditionalMana);
|
||||
}
|
||||
|
||||
List<Abilities<ActivatedManaAbilityImpl>> sourceWithoutManaCosts = new ArrayList<>();
|
||||
List<Abilities<ActivatedManaAbilityImpl>> sourceWithCosts = new ArrayList<>();
|
||||
|
@ -3407,11 +3412,11 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
try {
|
||||
// basic mana
|
||||
ManaOptions availableMana = getManaAvailable(game);
|
||||
availableMana.addMana(manaPool.getMana());
|
||||
// availableMana.addMana(manaPool.getMana());
|
||||
// conditional mana
|
||||
for (ConditionalMana conditionalMana : manaPool.getConditionalMana()) {
|
||||
availableMana.addMana(conditionalMana);
|
||||
}
|
||||
// for (ConditionalMana conditionalMana : manaPool.getConditionalMana()) {
|
||||
// availableMana.addMana(conditionalMana);
|
||||
// }
|
||||
|
||||
boolean fromAll = fromZone.equals(Zone.ALL);
|
||||
if (hidden && (fromAll || fromZone == Zone.HAND)) {
|
||||
|
|
Loading…
Reference in a new issue