mirror of
https://github.com/correl/mage.git
synced 2024-12-25 11:11:16 +00:00
* Doubling Cube - Added support for possible mana calculation (related to #6698).
This commit is contained in:
parent
27db13605e
commit
c48331f216
15 changed files with 379 additions and 79 deletions
|
@ -1,5 +1,7 @@
|
||||||
package mage.cards.d;
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.ConditionalMana;
|
import mage.ConditionalMana;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
|
@ -25,7 +27,8 @@ public final class DoublingCube extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||||
|
|
||||||
// {3}, {T}: Double the amount of each type of mana in your mana pool.
|
// {3}, {T}: Double the amount of each type of mana in your mana pool.
|
||||||
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new DoublingCubeEffect(), new ManaCostsImpl("{3}"));
|
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new DoublingCubeEffect(), new ManaCostsImpl("{3}"))
|
||||||
|
.setPoolDependant(true);
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
@ -52,6 +55,22 @@ class DoublingCubeEffect extends ManaEffect {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Mana> getNetMana(Game game, Mana possibleManaInPool, Ability source) {
|
||||||
|
List<Mana> netMana = new ArrayList<>();
|
||||||
|
netMana.add(new Mana( // remove possible mana conditions
|
||||||
|
possibleManaInPool.getRed(),
|
||||||
|
possibleManaInPool.getGreen(),
|
||||||
|
possibleManaInPool.getBlue(),
|
||||||
|
possibleManaInPool.getWhite(),
|
||||||
|
possibleManaInPool.getBlack(),
|
||||||
|
0, // Generic may not be included
|
||||||
|
possibleManaInPool.getAny(),
|
||||||
|
possibleManaInPool.getColorless())
|
||||||
|
);
|
||||||
|
return netMana;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mana produceMana(Game game, Ability source) {
|
public Mana produceMana(Game game, Ability source) {
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
|
|
|
@ -22,10 +22,10 @@ public final class FetidHeath extends CardImpl {
|
||||||
public FetidHeath (UUID ownerId, CardSetInfo setInfo) {
|
public FetidHeath (UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.LAND},null);
|
super(ownerId,setInfo,new CardType[]{CardType.LAND},null);
|
||||||
|
|
||||||
// {tap}: Add {C}.
|
// {T}: Add {C}.
|
||||||
this.addAbility(new ColorlessManaAbility());
|
this.addAbility(new ColorlessManaAbility());
|
||||||
|
|
||||||
// {W/B}, {tap}: Add {W}{W}, {W}{B}, or {B}{B}.
|
// {W/B}, {T}: Add {W}{W}, {W}{B}, or {B}{B}.
|
||||||
SimpleManaAbility ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana(2), new ManaCostsImpl("{W/B}"));
|
SimpleManaAbility ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana(2), new ManaCostsImpl("{W/B}"));
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class CastDestroySpellsTest extends CardTestPlayerBaseAI {
|
||||||
addCard(Zone.HAND, playerA, "Orzhov Charm"); // {W}{B}
|
addCard(Zone.HAND, playerA, "Orzhov Charm"); // {W}{B}
|
||||||
|
|
||||||
// {T}: Add {C}.
|
// {T}: Add {C}.
|
||||||
// {T} {W/B}, {T}: Add {W}{W}, {W}{B}, or {B}{B}.
|
// {W/B}, {T}: Add {W}{W}, {W}{B}, or {B}{B}.
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Fetid Heath", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Fetid Heath", 1);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package org.mage.test.cards.mana;
|
package org.mage.test.cards.mana;
|
||||||
|
|
||||||
|
import mage.abilities.mana.ManaOptions;
|
||||||
import mage.constants.ManaType;
|
import mage.constants.ManaType;
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
import static org.mage.test.utils.ManaOptionsTestUtils.assertManaOptions;
|
||||||
|
|
||||||
public class DoublingCubeTest extends CardTestPlayerBase {
|
public class DoublingCubeTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
@ -17,7 +21,7 @@ public class DoublingCubeTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
//issue 3443
|
//issue 3443
|
||||||
@Test
|
@Test
|
||||||
public void DoublingCubeEldraziTemple() {
|
public void test_DoublingCubeEldraziTemple() {
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerA, temple);
|
addCard(Zone.BATTLEFIELD, playerA, temple);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
@ -37,4 +41,105 @@ public class DoublingCubeTest extends CardTestPlayerBase {
|
||||||
assertManaPool(playerA, ManaType.COLORLESS, 4);
|
assertManaPool(playerA, ManaType.COLORLESS, 4);
|
||||||
assertAllCommandsUsed();
|
assertAllCommandsUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_AvailableMana() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
// {3}, {T}: Double the amount of each type of mana in your mana pool.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, cube);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
|
||||||
|
Assert.assertEquals("mana variations don't fit", 4, manaOptions.size());
|
||||||
|
assertManaOptions("{R}{R}{R}{R}{R}{R}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{R}{R}{R}{R}{R}{R}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{R}{R}{R}{R}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{R}{R}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_AvailableMana2() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
// {3}, {T}: Double the amount of each type of mana in your mana pool.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, cube, 2);
|
||||||
|
// {T}: Add Colorless.
|
||||||
|
// {1}, {T}: Add Black.
|
||||||
|
// {2}, {T}: Add Blue or Red.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Castle Sengir", 2);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.UPKEEP);
|
||||||
|
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
|
||||||
|
Assert.assertEquals("mana variations don't fit", 138, manaOptions.size());
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{C}{C}{C}{C}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{C}{C}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{C}{C}{C}{C}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{C}{C}{C}{C}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{C}{C}{C}{C}{R}{R}{R}{R}{R}{R}{R}{R}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{C}{C}{C}{C}{R}{R}{R}{R}{R}{R}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{C}{C}{C}{C}{R}{R}{R}{R}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{C}{C}{C}{C}{R}{R}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{C}{C}{C}{C}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{R}{R}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{B}{B}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{R}{R}{R}{R}{R}{R}{R}{R}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{R}{R}{R}{R}{R}{R}{R}{R}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{B}{B}{R}{R}{R}{R}{R}{R}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{B}{B}{R}{R}{R}{R}{R}{R}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{R}{R}{R}{R}{R}{R}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{R}{R}{R}{R}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{B}{B}{R}{R}{R}{R}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{B}{B}{R}{R}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{B}{B}{B}{B}{G}{G}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{U}{U}{R}{R}{R}{R}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{U}{U}{U}{U}{R}{R}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{U}{U}{R}{R}{R}{R}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{U}{U}{R}{R}{R}{R}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{U}{U}{U}{U}{R}{R}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{U}{U}{U}{U}{R}{R}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{U}{U}{R}{R}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{U}{U}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{C}{C}{C}{C}{U}{U}{U}{U}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{B}{B}{B}{B}{B}{B}{R}{R}{R}{R}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{B}{B}{B}{B}{B}{B}{B}{B}{R}{R}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{B}{B}{B}{B}{B}{B}{R}{R}{R}{R}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{B}{B}{B}{B}{B}{B}{R}{R}{R}{R}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{B}{B}{B}{B}{B}{B}{B}{B}{R}{R}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{B}{B}{B}{B}{B}{B}{B}{B}{R}{R}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{B}{B}{B}{B}{B}{B}{R}{R}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{B}{B}{B}{B}{B}{B}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{B}{B}{B}{B}{B}{B}{B}{B}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{B}{B}{R}{R}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{U}{U}{B}{B}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{B}{B}{B}{B}{R}{R}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{U}{U}{B}{B}{B}{B}{R}{R}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{B}{B}{R}{R}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{B}{B}{R}{R}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{U}{U}{B}{B}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{U}{U}{B}{B}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{B}{B}{B}{B}{R}{R}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{B}{B}{B}{B}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{U}{U}{B}{B}{B}{B}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{B}{B}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||||
|
assertManaOptions("{U}{U}{U}{U}{U}{U}", manaOptions);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class TappedForManaRelatedTest extends CardTestPlayerBase {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Castle Sengir", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Castle Sengir", 1);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
setStopAt(1, PhaseStep.UPKEEP);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertAllCommandsUsed();
|
assertAllCommandsUsed();
|
||||||
|
|
|
@ -5,7 +5,6 @@ import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
import static org.mage.test.utils.ManaOptionsTestUtils.*;
|
import static org.mage.test.utils.ManaOptionsTestUtils.*;
|
||||||
|
@ -330,6 +329,8 @@ public class ManaOptionsTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFetidHeath() {
|
public void testFetidHeath() {
|
||||||
|
// {T}: Add {C}.
|
||||||
|
// {W/B}, {T}: Add {W}{W}, {W}{B}, or {B}{B}.
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Fetid Heath", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Fetid Heath", 1);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||||
|
|
||||||
|
|
|
@ -267,6 +267,12 @@ public interface Abilities<T extends Ability> extends List<T>, Serializable {
|
||||||
*/
|
*/
|
||||||
boolean containsClass(Class classObject);
|
boolean containsClass(Class classObject);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if one or more of the abilities are activated mana abilities with the pollDependant flag set to true.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean hasPoolDependantAbilities();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies this set of abilities. This copy should be new instances of all
|
* Copies this set of abilities. This copy should be new instances of all
|
||||||
* the contained abilities.
|
* the contained abilities.
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import mage.abilities.mana.ManaAbility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param <T>
|
* @param <T>
|
||||||
|
@ -185,6 +186,13 @@ public class AbilitiesImpl<T extends Ability> extends ArrayList<T> implements Ab
|
||||||
return zonedAbilities;
|
return zonedAbilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPoolDependantAbilities() {
|
||||||
|
return stream()
|
||||||
|
.anyMatch(ability -> ability.getAbilityType() == AbilityType.MANA
|
||||||
|
&& ((ManaAbility) ability).isPoolDependant());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Abilities<ProtectionAbility> getProtectionAbilities() {
|
public Abilities<ProtectionAbility> getProtectionAbilities() {
|
||||||
return stream()
|
return stream()
|
||||||
|
@ -224,7 +232,7 @@ public class AbilitiesImpl<T extends Ability> extends ArrayList<T> implements Ab
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(T ability) {
|
public boolean contains(T ability) {
|
||||||
for (Iterator<T> iterator = this.iterator(); iterator.hasNext(); ) { // simple loop can cause java.util.ConcurrentModificationException
|
for (Iterator<T> iterator = this.iterator(); iterator.hasNext();) { // simple loop can cause java.util.ConcurrentModificationException
|
||||||
T test = iterator.next();
|
T test = iterator.next();
|
||||||
// Checking also by getRule() without other restrictions is a problem when a triggered ability will be copied to a permanent that had the same ability
|
// Checking also by getRule() without other restrictions is a problem when a triggered ability will be copied to a permanent that had the same ability
|
||||||
// already before the copy. Because then it keeps the triggered ability twice and it triggers twice.
|
// already before the copy. Because then it keeps the triggered ability twice and it triggers twice.
|
||||||
|
|
|
@ -80,6 +80,22 @@ public abstract class ManaEffect extends OneShotEffect {
|
||||||
return netMana;
|
return netMana;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently available max mana variations the effect can
|
||||||
|
* produce. Also provides the possible before produced mana from other
|
||||||
|
* abilities. Needed for some abilities that produce mana related to the
|
||||||
|
* mana existing in the mana pool.
|
||||||
|
*
|
||||||
|
* @param game
|
||||||
|
* @param possibleManaInPool The possible mana already produced by other
|
||||||
|
* sources for this calculation option
|
||||||
|
* @param source
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<Mana> getNetMana(Game game, Mana possibleManaInPool, Ability source) {
|
||||||
|
return getNetMana(game, source);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of mana a permanent "could produce" is the type of mana that any
|
* The type of mana a permanent "could produce" is the type of mana that any
|
||||||
* ability of that permanent can generate, taking into account any
|
* ability of that permanent can generate, taking into account any
|
||||||
|
@ -95,7 +111,6 @@ public abstract class ManaEffect extends OneShotEffect {
|
||||||
return ManaType.getManaTypesFromManaList(getNetMana(game, source));
|
return ManaType.getManaTypesFromManaList(getNetMana(game, source));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produced the mana the effect can produce (DO NOT add it to mana pool --
|
* Produced the mana the effect can produce (DO NOT add it to mana pool --
|
||||||
* return all added as mana object to process by replace events)
|
* return all added as mana object to process by replace events)
|
||||||
|
|
|
@ -19,6 +19,7 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
|
||||||
|
|
||||||
protected List<Mana> netMana = new ArrayList<>();
|
protected List<Mana> netMana = new ArrayList<>();
|
||||||
protected boolean undoPossible;
|
protected boolean undoPossible;
|
||||||
|
protected boolean poolDependant;
|
||||||
|
|
||||||
public ActivatedManaAbilityImpl(Zone zone, ManaEffect effect, Cost cost) {
|
public ActivatedManaAbilityImpl(Zone zone, ManaEffect effect, Cost cost) {
|
||||||
super(AbilityType.MANA, zone);
|
super(AbilityType.MANA, zone);
|
||||||
|
@ -36,6 +37,7 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
|
||||||
super(ability);
|
super(ability);
|
||||||
this.netMana.addAll(ability.netMana);
|
this.netMana.addAll(ability.netMana);
|
||||||
this.undoPossible = ability.undoPossible;
|
this.undoPossible = ability.undoPossible;
|
||||||
|
this.poolDependant = ability.poolDependant;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -101,6 +103,23 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
|
||||||
return netManaCopy;
|
return netManaCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Mana> getNetMana(Game game, Mana possibleManaInPool) {
|
||||||
|
if (isPoolDependant()) {
|
||||||
|
List<Mana> poolDependantNetMana = new ArrayList<>();
|
||||||
|
for (Effect effect : getEffects()) {
|
||||||
|
if (effect instanceof ManaEffect) {
|
||||||
|
List<Mana> effectNetMana = ((ManaEffect) effect).getNetMana(game, possibleManaInPool, this);
|
||||||
|
if (effectNetMana != null) {
|
||||||
|
poolDependantNetMana.addAll(effectNetMana);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return poolDependantNetMana;
|
||||||
|
}
|
||||||
|
return getNetMana(game);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ManaType> getProducableManaTypes(Game game) {
|
public Set<ManaType> getProducableManaTypes(Game game) {
|
||||||
Set<ManaType> manaTypes = new HashSet<>();
|
Set<ManaType> manaTypes = new HashSet<>();
|
||||||
|
@ -127,8 +146,9 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
|
||||||
* game revealing information is related (like reveal the top card of the
|
* game revealing information is related (like reveal the top card of the
|
||||||
* library)
|
* library)
|
||||||
* <p>
|
* <p>
|
||||||
* TODO: it helps with single mana activate for mana pool, but will not work while activates on paying for casting
|
* TODO: it helps with single mana activate for mana pool, but will not work
|
||||||
* (e.g. user can cheats to see next draw card)
|
* while activates on paying for casting (e.g. user can cheats to see next
|
||||||
|
* draw card)
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ -140,4 +160,15 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
|
||||||
this.undoPossible = undoPossible;
|
this.undoPossible = undoPossible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPoolDependant() {
|
||||||
|
return poolDependant;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActivatedManaAbilityImpl setPoolDependant(boolean poolDependant) {
|
||||||
|
this.poolDependant = poolDependant;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ package mage.abilities.mana;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
|
import mage.abilities.Ability;
|
||||||
import mage.constants.ManaType;
|
import mage.constants.ManaType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
|
||||||
|
@ -26,6 +27,17 @@ public interface ManaAbility {
|
||||||
*/
|
*/
|
||||||
List<Mana> getNetMana(Game game);
|
List<Mana> getNetMana(Game game);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to check the possible mana production to determine which spells
|
||||||
|
* and/or abilities can be used. (player.getPlayable()).
|
||||||
|
* Only used for abilities were the poolDependant flag is set
|
||||||
|
*
|
||||||
|
* @param game
|
||||||
|
* @param possibleManaInPool The possible mana already produced by other sources for this calculation option
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<Mana> getNetMana(Game game, Mana possibleManaInPool);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of mana a permanent "could produce" is the type of mana that any
|
* The type of mana a permanent "could produce" is the type of mana that any
|
||||||
* ability of that permanent can generate, taking into account any
|
* ability of that permanent can generate, taking into account any
|
||||||
|
@ -45,4 +57,16 @@ public interface ManaAbility {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean definesMana(Game game);
|
boolean definesMana(Game game);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to true if the ability is dependant from the mana pool. E.g. the more
|
||||||
|
* mana the pool contains the more mana the ability can produce (Doubling
|
||||||
|
* Cube). Therefore the use of that ability after other mana abilities does produce more mana.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean isPoolDependant();
|
||||||
|
|
||||||
|
ManaAbility setPoolDependant(boolean pooleDependant);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,6 +176,7 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
newMana.add(mana);
|
newMana.add(mana);
|
||||||
newMana.add(triggeredManaVariation);
|
newMana.add(triggeredManaVariation);
|
||||||
this.add(newMana);
|
this.add(newMana);
|
||||||
|
wasUsable = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,7 +191,7 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
Mana startingMana = prevMana.copy();
|
Mana startingMana = prevMana.copy();
|
||||||
Mana manaCosts = ability.getManaCosts().getMana();
|
Mana manaCosts = ability.getManaCosts().getMana();
|
||||||
if (startingMana.includesMana(manaCosts)) { // can pay the mana costs to use the ability
|
if (startingMana.includesMana(manaCosts)) { // can pay the mana costs to use the ability
|
||||||
if (!subtractCostAddMana(manaCosts, triggeredManaVariation, ability.getCosts().isEmpty(), startingMana)) {
|
if (!subtractCostAddMana(manaCosts, triggeredManaVariation, ability.getCosts().isEmpty(), startingMana, ability, game)) {
|
||||||
// the starting mana includes mana parts that the increased mana does not include, so add starting mana also as an option
|
// the starting mana includes mana parts that the increased mana does not include, so add starting mana also as an option
|
||||||
add(prevMana);
|
add(prevMana);
|
||||||
}
|
}
|
||||||
|
@ -219,6 +220,7 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
newMana.add(mana);
|
newMana.add(mana);
|
||||||
newMana.add(triggeredManaVariation);
|
newMana.add(triggeredManaVariation);
|
||||||
this.add(newMana);
|
this.add(newMana);
|
||||||
|
wasUsable = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,21 +231,8 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
for (Mana previousMana : copy) {
|
for (Mana previousMana : copy) {
|
||||||
CombineWithExisting:
|
CombineWithExisting:
|
||||||
for (Mana manaOption : ability.getManaCosts().getManaOptions()) {
|
for (Mana manaOption : ability.getManaCosts().getManaOptions()) {
|
||||||
Mana newMana = new Mana(previousMana);
|
|
||||||
if (previousMana.includesMana(manaOption)) { // costs can be paid
|
if (previousMana.includesMana(manaOption)) { // costs can be paid
|
||||||
newMana.subtractCost(manaOption);
|
wasUsable |= subtractCostAddMana(manaOption, triggeredManaVariation, ability.getCosts().isEmpty(), previousMana, ability, game);
|
||||||
newMana.add(triggeredManaVariation);
|
|
||||||
// if the new mana is in all colors more than another already existing than replace
|
|
||||||
for (Mana existingMana : this) {
|
|
||||||
Mana moreValuable = Mana.getMoreValuableMana(newMana, existingMana);
|
|
||||||
if (moreValuable != null) {
|
|
||||||
existingMana.setToMana(moreValuable);
|
|
||||||
replaces++;
|
|
||||||
continue CombineWithExisting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// no existing Mana includes this new mana so add
|
|
||||||
this.add(newMana);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,6 +253,35 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
return wasUsable;
|
return wasUsable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean addManaPoolDependant(List<ActivatedManaAbilityImpl> abilities, Game game) {
|
||||||
|
boolean wasUsable = false;
|
||||||
|
if (!abilities.isEmpty()) {
|
||||||
|
if (abilities.size() == 1) {
|
||||||
|
ActivatedManaAbilityImpl ability = (ActivatedManaAbilityImpl) abilities.get(0);
|
||||||
|
List<Mana> copy = copy();
|
||||||
|
this.clear();
|
||||||
|
for (Mana previousMana : copy) {
|
||||||
|
Mana startingMana = previousMana.copy();
|
||||||
|
Mana manaCosts = ability.getManaCosts().getMana();
|
||||||
|
if (startingMana.includesMana(manaCosts)) { // can pay the mana costs to use the ability
|
||||||
|
for (Mana manaOption : ability.getManaCosts().getManaOptions()) {
|
||||||
|
if (!subtractCostAddMana(manaOption, null, ability.getCosts().isEmpty(), startingMana, ability, game)) {
|
||||||
|
// the starting mana includes mana parts that the increased mana does not include, so add starting mana also as an option
|
||||||
|
add(previousMana);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wasUsable = true;
|
||||||
|
} else {
|
||||||
|
// mana costs can't be paid so keep starting mana
|
||||||
|
add(previousMana);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wasUsable;
|
||||||
|
}
|
||||||
|
|
||||||
public static List<Mana> getTriggeredManaVariations(Game game, Ability ability, Mana baseMana) {
|
public static List<Mana> getTriggeredManaVariations(Game game, Ability ability, Mana baseMana) {
|
||||||
List<Mana> baseManaPlusTriggeredMana = new ArrayList<>();
|
List<Mana> baseManaPlusTriggeredMana = new ArrayList<>();
|
||||||
baseManaPlusTriggeredMana.add(baseMana);
|
baseManaPlusTriggeredMana.add(baseMana);
|
||||||
|
@ -391,62 +409,60 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
* @param oldManaWasReplaced returns the info if the new complete mana does
|
* @param oldManaWasReplaced returns the info if the new complete mana does
|
||||||
* replace the current mana completely
|
* replace the current mana completely
|
||||||
*/
|
*/
|
||||||
private boolean subtractCostAddMana(Mana cost, Mana manaToAdd, boolean onlyManaCosts, Mana currentMana) {
|
private boolean subtractCostAddMana(Mana cost, Mana manaToAdd, boolean onlyManaCosts, Mana currentMana, ManaAbility manaAbility, Game game) {
|
||||||
boolean oldManaWasReplaced = false; // true if the newly created mana includes all mana possibilities of the old
|
boolean oldManaWasReplaced = false; // true if the newly created mana includes all mana possibilities of the old
|
||||||
boolean repeatable = false;
|
boolean repeatable = false;
|
||||||
if ((manaToAdd.countColored() > 0 || manaToAdd.getAny() > 0) && manaToAdd.count() > 0 && onlyManaCosts) {
|
if (manaToAdd != null && (manaToAdd.countColored() > 0 || manaToAdd.getAny() > 0) && manaToAdd.count() > 0 && onlyManaCosts) {
|
||||||
// deactivated because it does cause loops TODO: Find reason
|
|
||||||
repeatable = true; // only replace to any with mana costs only will be repeated if able
|
repeatable = true; // only replace to any with mana costs only will be repeated if able
|
||||||
}
|
}
|
||||||
Mana prevMana = currentMana.copy();
|
|
||||||
// generic mana costs can be paid with different colored mana, can lead to different color combinations
|
|
||||||
if (cost.getGeneric() > 0 && cost.getGeneric() > (currentMana.getGeneric() + currentMana.getColorless())) {
|
|
||||||
for (Mana payCombination : ManaOptions.getPossiblePayCombinations(cost.getGeneric(), currentMana)) {
|
|
||||||
Mana currentManaCopy = currentMana.copy();
|
|
||||||
while (currentManaCopy.includesMana(payCombination)) { // loop for multiple usage if possible
|
|
||||||
boolean newCombinations = false;
|
|
||||||
|
|
||||||
|
for (Mana payCombination : ManaOptions.getPossiblePayCombinations(cost, currentMana)) {
|
||||||
|
Mana currentManaCopy = currentMana.copy(); // copy start mana because in iteration it will be updated
|
||||||
|
while (currentManaCopy.includesMana(payCombination)) { // loop for multiple usage if possible
|
||||||
|
boolean newCombinations = false;
|
||||||
|
|
||||||
|
if (manaToAdd == null) {
|
||||||
|
Mana newMana = currentManaCopy.copy();
|
||||||
|
newMana.subtract(payCombination);
|
||||||
|
for (Mana mana : manaAbility.getNetMana(game, newMana)) { // get the mana to add from the ability related to the currently generated possible mana pool
|
||||||
|
newMana.add(mana);
|
||||||
|
if (!isExistingManaCombination(newMana)) {
|
||||||
|
this.add(newMana); // add the new combination
|
||||||
|
newCombinations = true; // repeat the while as long there are new combinations and usage is repeatable
|
||||||
|
|
||||||
|
Mana moreValuable = Mana.getMoreValuableMana(currentManaCopy, newMana);
|
||||||
|
if (newMana.equals(moreValuable)) {
|
||||||
|
oldManaWasReplaced = true; // the new mana includes all possibilities of the old one, so no need to add it after return
|
||||||
|
if (!currentMana.equalManaValue(currentManaCopy)) {
|
||||||
|
this.removeEqualMana(currentManaCopy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentManaCopy = newMana.copy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Mana newMana = currentManaCopy.copy();
|
Mana newMana = currentManaCopy.copy();
|
||||||
newMana.subtract(payCombination);
|
newMana.subtract(payCombination);
|
||||||
newMana.add(manaToAdd);
|
newMana.add(manaToAdd);
|
||||||
// Mana moreValuable = Mana.getMoreValuableMana(currentMana, newMana);
|
|
||||||
if (!isExistingManaCombination(newMana)) {
|
if (!isExistingManaCombination(newMana)) {
|
||||||
this.add(newMana); // add the new combination
|
this.add(newMana); // add the new combination
|
||||||
newCombinations = true; // repeat the while as long there are new combinations and usage is repeatable
|
newCombinations = true; // repeat the while as long there are new combinations and usage is repeatable
|
||||||
currentManaCopy = newMana.copy();
|
Mana moreValuable = Mana.getMoreValuableMana(currentManaCopy, newMana);
|
||||||
Mana moreValuable = Mana.getMoreValuableMana(currentMana, newMana);
|
if (newMana.equals(moreValuable)) {
|
||||||
if (!oldManaWasReplaced && newMana.equals(moreValuable)) {
|
oldManaWasReplaced = true; // the new mana includes all possible mana of the old one, so no need to add it after return
|
||||||
oldManaWasReplaced = true; // the new mana includes all possibilities of the old one, so no need to add it after return
|
if (!currentMana.equalManaValue(currentManaCopy)) {
|
||||||
|
this.removeEqualMana(currentManaCopy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
currentManaCopy = newMana.copy();
|
||||||
if (!newCombinations || !repeatable) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!newCombinations || !repeatable) {
|
||||||
}
|
break;
|
||||||
} else {
|
|
||||||
while (currentMana.includesMana(cost)) { // loop for multiple usage if possible
|
|
||||||
currentMana.subtractCost(cost);
|
|
||||||
currentMana.add(manaToAdd);
|
|
||||||
if (!repeatable) {
|
|
||||||
break; // Stop adding multiple usages of the ability
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Don't use mana that only reduce the available mana
|
|
||||||
if (prevMana.contains(currentMana) && prevMana.count() > currentMana.count()) {
|
|
||||||
currentMana.setToMana(prevMana);
|
|
||||||
}
|
|
||||||
Mana moreValuable = Mana.getMoreValuableMana(prevMana, currentMana);
|
|
||||||
if (!prevMana.equals(moreValuable)) {
|
|
||||||
this.add(currentMana);
|
|
||||||
if (moreValuable != null) {
|
|
||||||
oldManaWasReplaced = true; // the new mana includes all possibilities of the old one
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
forceManaDeduplication();
|
forceManaDeduplication();
|
||||||
|
|
||||||
return oldManaWasReplaced;
|
return oldManaWasReplaced;
|
||||||
|
@ -457,12 +473,23 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
* @param manaAvailable
|
* @param manaAvailable
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static List<Mana> getPossiblePayCombinations(int number, Mana manaAvailable) {
|
public static List<Mana> getPossiblePayCombinations(Mana manaCost, Mana manaAvailable) {
|
||||||
List<Mana> payCombinations = new ArrayList<>();
|
List<Mana> payCombinations = new ArrayList<>();
|
||||||
List<String> payCombinationsStrings = new ArrayList<>();
|
List<String> payCombinationsStrings = new ArrayList<>();
|
||||||
|
// handle fixed mana costs
|
||||||
|
Mana fixedMana = manaCost.copy();
|
||||||
|
if (manaCost.getGeneric() == 0) {
|
||||||
|
payCombinations.add(fixedMana);
|
||||||
|
return payCombinations;
|
||||||
|
}
|
||||||
|
fixedMana.setGeneric(0);
|
||||||
|
Mana manaAfterFixedPayment = manaAvailable.copy();
|
||||||
|
manaAfterFixedPayment.subtract(fixedMana);
|
||||||
|
|
||||||
|
// handle generic mana costs
|
||||||
if (manaAvailable.countColored() > 0) {
|
if (manaAvailable.countColored() > 0) {
|
||||||
|
|
||||||
for (int i = 0; i < number; i++) {
|
for (int i = 0; i < manaCost.getGeneric(); i++) {
|
||||||
List<Mana> existingManas = new ArrayList<>();
|
List<Mana> existingManas = new ArrayList<>();
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
existingManas.addAll(payCombinations);
|
existingManas.addAll(payCombinations);
|
||||||
|
@ -472,7 +499,7 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
existingManas.add(new Mana());
|
existingManas.add(new Mana());
|
||||||
}
|
}
|
||||||
for (Mana existingMana : existingManas) {
|
for (Mana existingMana : existingManas) {
|
||||||
Mana manaToPayFrom = manaAvailable.copy();
|
Mana manaToPayFrom = manaAfterFixedPayment.copy();
|
||||||
manaToPayFrom.subtract(existingMana);
|
manaToPayFrom.subtract(existingMana);
|
||||||
if (manaToPayFrom.getBlack() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.BlackMana(1).toString())) {
|
if (manaToPayFrom.getBlack() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.BlackMana(1).toString())) {
|
||||||
manaToPayFrom.subtract(Mana.BlackMana(1));
|
manaToPayFrom.subtract(Mana.BlackMana(1));
|
||||||
|
@ -494,6 +521,10 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
manaToPayFrom.subtract(Mana.WhiteMana(1));
|
manaToPayFrom.subtract(Mana.WhiteMana(1));
|
||||||
ManaOptions.addManaCombination(Mana.WhiteMana(1), existingMana, payCombinations, payCombinationsStrings);
|
ManaOptions.addManaCombination(Mana.WhiteMana(1), existingMana, payCombinations, payCombinationsStrings);
|
||||||
}
|
}
|
||||||
|
if (manaToPayFrom.getColorless() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.ColorlessMana(1).toString())) {
|
||||||
|
manaToPayFrom.subtract(Mana.ColorlessMana(1));
|
||||||
|
ManaOptions.addManaCombination(Mana.ColorlessMana(1), existingMana, payCombinations, payCombinationsStrings);
|
||||||
|
}
|
||||||
// Pay with any only needed if colored payment was not possible
|
// Pay with any only needed if colored payment was not possible
|
||||||
if (payCombinations.isEmpty() && manaToPayFrom.getAny() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.AnyMana(1).toString())) {
|
if (payCombinations.isEmpty() && manaToPayFrom.getAny() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.AnyMana(1).toString())) {
|
||||||
manaToPayFrom.subtract(Mana.AnyMana(1));
|
manaToPayFrom.subtract(Mana.AnyMana(1));
|
||||||
|
@ -502,7 +533,10 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
payCombinations.add(Mana.ColorlessMana(number));
|
payCombinations.add(Mana.ColorlessMana(manaCost.getGeneric()));
|
||||||
|
}
|
||||||
|
for (Mana mana : payCombinations) {
|
||||||
|
mana.add(fixedMana);
|
||||||
}
|
}
|
||||||
return payCombinations;
|
return payCombinations;
|
||||||
}
|
}
|
||||||
|
@ -517,6 +551,18 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean removeEqualMana(Mana manaToRemove) {
|
||||||
|
boolean result = false;
|
||||||
|
for (Iterator<Mana> iterator = this.iterator(); iterator.hasNext();) {
|
||||||
|
Mana next = iterator.next();
|
||||||
|
if (next.equalManaValue(manaToRemove)) {
|
||||||
|
iterator.remove();
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static void addManaCombination(Mana mana, Mana existingMana, List<Mana> payCombinations, List<String> payCombinationsStrings) {
|
public static void addManaCombination(Mana mana, Mana existingMana, List<Mana> payCombinations, List<String> payCombinationsStrings) {
|
||||||
Mana newMana = existingMana.copy();
|
Mana newMana = existingMana.copy();
|
||||||
newMana.add(mana);
|
newMana.add(mana);
|
||||||
|
@ -572,6 +618,7 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
Iterator<Mana> it = this.iterator();
|
Iterator<Mana> it = this.iterator();
|
||||||
if (!it.hasNext()) {
|
if (!it.hasNext()) {
|
||||||
|
|
|
@ -72,4 +72,5 @@ public class SimpleManaAbility extends ActivatedManaAbilityImpl {
|
||||||
return new ArrayList<>(netMana);
|
return new ArrayList<>(netMana);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import mage.constants.ManaType;
|
||||||
public abstract class TriggeredManaAbility extends TriggeredAbilityImpl implements ManaAbility {
|
public abstract class TriggeredManaAbility extends TriggeredAbilityImpl implements ManaAbility {
|
||||||
|
|
||||||
protected List<Mana> netMana = new ArrayList<>();
|
protected List<Mana> netMana = new ArrayList<>();
|
||||||
|
protected boolean poolDependant;
|
||||||
|
|
||||||
public TriggeredManaAbility(Zone zone, ManaEffect effect) {
|
public TriggeredManaAbility(Zone zone, ManaEffect effect) {
|
||||||
this(zone, effect, false);
|
this(zone, effect, false);
|
||||||
|
@ -37,6 +38,7 @@ public abstract class TriggeredManaAbility extends TriggeredAbilityImpl implemen
|
||||||
public TriggeredManaAbility(final TriggeredManaAbility ability) {
|
public TriggeredManaAbility(final TriggeredManaAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.netMana.addAll(ability.netMana);
|
this.netMana.addAll(ability.netMana);
|
||||||
|
this.poolDependant = ability.poolDependant;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,6 +62,23 @@ public abstract class TriggeredManaAbility extends TriggeredAbilityImpl implemen
|
||||||
return new ArrayList<>(netMana);
|
return new ArrayList<>(netMana);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Mana> getNetMana(Game game, Mana possibleManaInPool) {
|
||||||
|
if (isPoolDependant()) {
|
||||||
|
List<Mana> poolDependantNetMana = new ArrayList<>();
|
||||||
|
for (Effect effect : getEffects()) {
|
||||||
|
if (effect instanceof ManaEffect) {
|
||||||
|
List<Mana> effectNetMana = ((ManaEffect) effect).getNetMana(game, possibleManaInPool, this);
|
||||||
|
if (effectNetMana != null) {
|
||||||
|
poolDependantNetMana.addAll(effectNetMana);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return poolDependantNetMana;
|
||||||
|
}
|
||||||
|
return getNetMana(game);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ManaType> getProducableManaTypes(Game game) {
|
public Set<ManaType> getProducableManaTypes(Game game) {
|
||||||
Set<ManaType> manaTypes = new HashSet<>();
|
Set<ManaType> manaTypes = new HashSet<>();
|
||||||
|
@ -80,4 +99,16 @@ public abstract class TriggeredManaAbility extends TriggeredAbilityImpl implemen
|
||||||
public boolean definesMana(Game game) {
|
public boolean definesMana(Game game) {
|
||||||
return !netMana.isEmpty();
|
return !netMana.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPoolDependant() {
|
||||||
|
return poolDependant;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TriggeredManaAbility setPoolDependant(boolean poolDependant) {
|
||||||
|
this.poolDependant = poolDependant;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2894,7 +2894,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(playerId, game)) { // Some permanents allow use of abilities from non controlling players. so check all permanents in range
|
for (Permanent permanent : game.getBattlefield().getActivePermanents(playerId, game)) { // Some permanents allow use of abilities from non controlling players. so check all permanents in range
|
||||||
Boolean canUse = null;
|
Boolean canUse = null;
|
||||||
boolean canAdd = false;
|
boolean canAdd = false;
|
||||||
boolean withCost = false;
|
boolean useLater = false; // sources with mana costs or mana pool dependency
|
||||||
Abilities<ActivatedManaAbilityImpl> manaAbilities
|
Abilities<ActivatedManaAbilityImpl> manaAbilities
|
||||||
= permanent.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, playerId, game); // returns ability only if canActivate is true
|
= permanent.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, playerId, game); // returns ability only if canActivate is true
|
||||||
for (Iterator<ActivatedManaAbilityImpl> it = manaAbilities.iterator(); it.hasNext();) {
|
for (Iterator<ActivatedManaAbilityImpl> it = manaAbilities.iterator(); it.hasNext();) {
|
||||||
|
@ -2907,7 +2907,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
if (!ability.hasTapCost()) {
|
if (!ability.hasTapCost()) {
|
||||||
it.remove();
|
it.remove();
|
||||||
Abilities<ActivatedManaAbilityImpl> noTapAbilities = new AbilitiesImpl<>(ability);
|
Abilities<ActivatedManaAbilityImpl> noTapAbilities = new AbilitiesImpl<>(ability);
|
||||||
if (ability.getManaCosts().isEmpty()) {
|
if (ability.getManaCosts().isEmpty() && !ability.isPoolDependant()) {
|
||||||
sourceWithoutManaCosts.add(noTapAbilities);
|
sourceWithoutManaCosts.add(noTapAbilities);
|
||||||
} else {
|
} else {
|
||||||
sourceWithCosts.add(noTapAbilities);
|
sourceWithCosts.add(noTapAbilities);
|
||||||
|
@ -2916,14 +2916,14 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
canAdd = true;
|
canAdd = true;
|
||||||
if (!ability.getManaCosts().isEmpty()) {
|
if (!ability.getManaCosts().isEmpty() || ability.isPoolDependant()) {
|
||||||
withCost = true;
|
useLater = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (canAdd) {
|
if (canAdd) {
|
||||||
if (withCost) {
|
if (useLater) {
|
||||||
sourceWithCosts.add(manaAbilities);
|
sourceWithCosts.add(manaAbilities);
|
||||||
} else {
|
} else {
|
||||||
sourceWithoutManaCosts.add(manaAbilities);
|
sourceWithoutManaCosts.add(manaAbilities);
|
||||||
|
@ -2936,17 +2936,29 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean anAbilityWasUsed = true;
|
boolean anAbilityWasUsed = true;
|
||||||
|
boolean usePoolDependantAbilities = false; // use such abilities later than other if possible because it can maximize mana production
|
||||||
while (anAbilityWasUsed && !sourceWithCosts.isEmpty()) {
|
while (anAbilityWasUsed && !sourceWithCosts.isEmpty()) {
|
||||||
anAbilityWasUsed = false;
|
anAbilityWasUsed = false;
|
||||||
for (Iterator<Abilities<ActivatedManaAbilityImpl>> iterator = sourceWithCosts.iterator(); iterator.hasNext();) {
|
for (Iterator<Abilities<ActivatedManaAbilityImpl>> iterator = sourceWithCosts.iterator(); iterator.hasNext();) {
|
||||||
Abilities<ActivatedManaAbilityImpl> manaAbilities = iterator.next();
|
Abilities<ActivatedManaAbilityImpl> manaAbilities = iterator.next();
|
||||||
boolean used = availableMana.addManaWithCost(manaAbilities, game);
|
if (usePoolDependantAbilities || !manaAbilities.hasPoolDependantAbilities()) {
|
||||||
if (used) {
|
boolean used;
|
||||||
iterator.remove();
|
if (manaAbilities.hasPoolDependantAbilities()) {
|
||||||
availableMana.removeDuplicated();
|
used = availableMana.addManaPoolDependant(manaAbilities, game);
|
||||||
anAbilityWasUsed = true;
|
} else {
|
||||||
|
used = availableMana.addManaWithCost(manaAbilities, game);
|
||||||
|
}
|
||||||
|
if (used) {
|
||||||
|
iterator.remove();
|
||||||
|
availableMana.removeDuplicated();
|
||||||
|
anAbilityWasUsed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!anAbilityWasUsed && !usePoolDependantAbilities) {
|
||||||
|
usePoolDependantAbilities = true;
|
||||||
|
anAbilityWasUsed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove duplicated variants (see ManaOptionsTest for info - when that rises)
|
// remove duplicated variants (see ManaOptionsTest for info - when that rises)
|
||||||
|
|
Loading…
Reference in a new issue