mirror of
https://github.com/magefree/mage.git
synced 2026-01-23 19:59:54 -08:00
* Some changes to improve mana use of AI.
This commit is contained in:
parent
c3d0297045
commit
3972695428
7 changed files with 297 additions and 62 deletions
|
|
@ -31,6 +31,7 @@ import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import mage.ConditionalMana;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
import mage.abilities.*;
|
import mage.abilities.*;
|
||||||
|
|
@ -1261,7 +1262,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean playManaHandling(Ability ability, ManaCost unpaid, Game game) {
|
protected boolean playManaHandling(Ability ability, ManaCost unpaid, final Game game) {
|
||||||
// log.info("paying for " + unpaid.getText());
|
// log.info("paying for " + unpaid.getText());
|
||||||
UUID spendAnyManaId = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
|
UUID spendAnyManaId = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
|
||||||
ManaCost cost;
|
ManaCost cost;
|
||||||
|
|
@ -1279,7 +1280,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
// use color producing mana abilities with costs first that produce all color manas that are needed to pay
|
// use color producing mana abilities with costs first that produce all color manas that are needed to pay
|
||||||
// otherwise the computer may not be able to pay the cost for that source
|
// otherwise the computer may not be able to pay the cost for that source
|
||||||
ManaAbility:
|
ManaAbility:
|
||||||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
|
||||||
int colored = 0;
|
int colored = 0;
|
||||||
for (Mana mana : manaAbility.getNetMana(game)) {
|
for (Mana mana : manaAbility.getNetMana(game)) {
|
||||||
if (!unpaid.getMana().includesMana(mana)) {
|
if (!unpaid.getMana().includesMana(mana)) {
|
||||||
|
|
@ -1288,9 +1289,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
colored += mana.countColored();
|
colored += mana.countColored();
|
||||||
}
|
}
|
||||||
if (colored > 1 && (cost instanceof ColoredManaCost)) {
|
if (colored > 1 && (cost instanceof ColoredManaCost)) {
|
||||||
|
|
||||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||||
if (cost.testPay(netMana)) {
|
if (cost.testPay(netMana)) {
|
||||||
|
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (activateAbility(manaAbility, game)) {
|
if (activateAbility(manaAbility, game)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1302,10 +1305,13 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
|
|
||||||
for (MageObject mageObject : producers) {
|
for (MageObject mageObject : producers) {
|
||||||
// pay all colored costs first
|
// pay all colored costs first
|
||||||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
|
||||||
if (cost instanceof ColoredManaCost) {
|
if (cost instanceof ColoredManaCost) {
|
||||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||||
|
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (activateAbility(manaAbility, game)) {
|
if (activateAbility(manaAbility, game)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1314,10 +1320,13 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// pay snow covered mana
|
// pay snow covered mana
|
||||||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
|
||||||
if (cost instanceof SnowManaCost) {
|
if (cost instanceof SnowManaCost) {
|
||||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||||
|
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (activateAbility(manaAbility, game)) {
|
if (activateAbility(manaAbility, game)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1326,10 +1335,13 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// then pay hybrid
|
// then pay hybrid
|
||||||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
|
||||||
if (cost instanceof HybridManaCost) {
|
if (cost instanceof HybridManaCost) {
|
||||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||||
|
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (activateAbility(manaAbility, game)) {
|
if (activateAbility(manaAbility, game)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1338,10 +1350,13 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// then pay mono hybrid
|
// then pay mono hybrid
|
||||||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
|
||||||
if (cost instanceof MonoHybridManaCost) {
|
if (cost instanceof MonoHybridManaCost) {
|
||||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||||
|
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (activateAbility(manaAbility, game)) {
|
if (activateAbility(manaAbility, game)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1350,10 +1365,13 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// pay colorless
|
// pay colorless
|
||||||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
|
||||||
if (cost instanceof ColorlessManaCost) {
|
if (cost instanceof ColorlessManaCost) {
|
||||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||||
|
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (activateAbility(manaAbility, game)) {
|
if (activateAbility(manaAbility, game)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1362,10 +1380,13 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// finally pay generic
|
// finally pay generic
|
||||||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) {
|
||||||
if (cost instanceof GenericManaCost) {
|
if (cost instanceof GenericManaCost) {
|
||||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||||
|
if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (activateAbility(manaAbility, game)) {
|
if (activateAbility(manaAbility, game)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1383,6 +1404,32 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Abilities<ActivatedManaAbilityImpl> getManaAbilitiesSortedByManaCount(MageObject mageObject, final Game game) {
|
||||||
|
Abilities<ActivatedManaAbilityImpl> manaAbilities = mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game);
|
||||||
|
if (manaAbilities.size() > 1) {
|
||||||
|
// Sort mana abilities by numbver of produced manas, to use ability first that produces most mana (maybe also conditional if possible)
|
||||||
|
Collections.sort(manaAbilities, new Comparator<ActivatedManaAbilityImpl>() {
|
||||||
|
@Override
|
||||||
|
public int compare(ActivatedManaAbilityImpl a1, ActivatedManaAbilityImpl a2) {
|
||||||
|
int a1Max = 0;
|
||||||
|
for (Mana netMana : a1.getNetMana(game)) {
|
||||||
|
if (netMana.count() > a1Max) {
|
||||||
|
a1Max = netMana.count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int a2Max = 0;
|
||||||
|
for (Mana netMana : a2.getNetMana(game)) {
|
||||||
|
if (netMana.count() > a2Max) {
|
||||||
|
a2Max = netMana.count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a2Max - a1Max;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return manaAbilities;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* returns a list of Permanents that produce mana sorted by the number of
|
* returns a list of Permanents that produce mana sorted by the number of
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package org.mage.test.cards.mana;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class EldraziTempleTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestWithoutDampingSphere() {
|
||||||
|
// {T}: Add {C}.
|
||||||
|
// {T}: Add {C}{C}. Spend this mana only to cast colorless Eldrazi spells or activate abilities of colorless Eldrazi.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Eldrazi Temple", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
// Devoid (This card has no color.)
|
||||||
|
// {2}{R}, Sacrifice another colorless creature: Barrage Tyrant deals damage equal to the sacrificed creature's power to target creature or player.
|
||||||
|
addCard(Zone.HAND, playerA, "Barrage Tyrant", 1); // Creature {4}{R}
|
||||||
|
|
||||||
|
// If a land is tapped for two or more mana, it produces {C} instead of any other type and amount.
|
||||||
|
// Each spell a player casts costs {1} more to cast for each other spell that player has cast this turn.
|
||||||
|
// addCard(Zone.BATTLEFIELD, playerB, "Damping Sphere", 1);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barrage Tyrant");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Barrage Tyrant", 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Damping Sphere vs Eldrazi
|
||||||
|
*
|
||||||
|
* My opponent managed to produce 7 mana to cast a All Is Dust with 6 lands
|
||||||
|
* where one was an Eldrazi Temple. This should not be possible if my
|
||||||
|
* reading of Damping Sphere (If a land is tapped for two or more mana, it
|
||||||
|
* produces {C} instead of any other type and amount.) is correct. It should
|
||||||
|
* produce a single colorless mana rather than 2 colorless for the eldrazi
|
||||||
|
* tribal spell
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void TestWithDampingSphere() {
|
||||||
|
// {T}: Add {C}.
|
||||||
|
// {T}: Add {C}{C}. Spend this mana only to cast colorless Eldrazi spells or activate abilities of colorless Eldrazi.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Eldrazi Temple", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
// Devoid (This card has no color.)
|
||||||
|
// {2}{R}, Sacrifice another colorless creature: Barrage Tyrant deals damage equal to the sacrificed creature's power to target creature or player.
|
||||||
|
addCard(Zone.HAND, playerA, "Barrage Tyrant", 1); // Creature {4}{R}
|
||||||
|
|
||||||
|
// If a land is tapped for two or more mana, it produces {C} instead of any other type and amount.
|
||||||
|
// Each spell a player casts costs {1} more to cast for each other spell that player has cast this turn.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Damping Sphere", 1);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barrage Tyrant");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Barrage Tyrant", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestUseOfUnconditionalMana() {
|
||||||
|
// {T}: Add {C}.
|
||||||
|
// {T}: Add {C}{C}. Spend this mana only to cast colorless Eldrazi spells or activate abilities of colorless Eldrazi.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Eldrazi Temple", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||||
|
// {T}: Add {W}, {B}, or {G} to your mana pool.
|
||||||
|
// {W}{B}{G}, {T}, Sacrifice Abzan Banner: Draw a card.
|
||||||
|
addCard(Zone.HAND, playerA, "Abzan Banner", 1); // Artifact {3}
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Abzan Banner");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Abzan Banner", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -158,7 +158,7 @@ public class ManaOptionsTest extends CardTestPlayerBase {
|
||||||
assertDuplicatedManaOptions(manaOptions);
|
assertDuplicatedManaOptions(manaOptions);
|
||||||
|
|
||||||
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
|
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
|
||||||
assertManaOptions("{C}{W}{W}{G}{G}", manaOptions);
|
assertManaOptions("{C}{W}{W}{G}{G}", manaOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crystal Quarry
|
// Crystal Quarry
|
||||||
|
|
@ -236,6 +236,29 @@ public class ManaOptionsTest extends CardTestPlayerBase {
|
||||||
assertManaOptions("{C}{G}{Any}", manaOptions);
|
assertManaOptions("{C}{G}{Any}", manaOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nykthos, Shrine to Nyx
|
||||||
|
// {T}: Add {C}.
|
||||||
|
// {2}, {T}: Choose a color. Add an amount of mana of that color equal to your devotion to that color. (Your devotion to a color is the number of mana symbols of that color in the mana costs of permanents you control.)
|
||||||
|
@Test
|
||||||
|
public void testNykthos4() {
|
||||||
|
// If a land is tapped for two or more mana, it produces {C} instead of any other type and amount.
|
||||||
|
// Each spell a player casts costs {1} more to cast for each other spell that player has cast this turn.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Damping Sphere", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Sedge Scorpion", 4);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Nykthos, Shrine to Nyx", 1);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.UPKEEP);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
|
||||||
|
assertDuplicatedManaOptions(manaOptions);
|
||||||
|
|
||||||
|
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
|
||||||
|
assertManaOptions("{C}{G}{G}{G}", manaOptions);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDuplicatedDontHave1() {
|
public void testDuplicatedDontHave1() {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "City of Brass", 2); // Any
|
addCard(Zone.BATTLEFIELD, playerA, "City of Brass", 2); // Any
|
||||||
|
|
@ -401,4 +424,23 @@ public class ManaOptionsTest extends CardTestPlayerBase {
|
||||||
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
|
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
|
||||||
assertManaOptions("{B}{B}", manaOptions);
|
assertManaOptions("{B}{B}", manaOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDampingSphere() {
|
||||||
|
// If a land is tapped for two or more mana, it produces {C} instead of any other type and amount.
|
||||||
|
// Each spell a player casts costs {1} more to cast for each other spell that player has cast this turn.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Damping Sphere", 1);
|
||||||
|
// {T}: Add {C}.
|
||||||
|
// {T}: Add {C}{C}. Spend this mana only to cast colorless Eldrazi spells or activate abilities of colorless Eldrazi.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Eldrazi Temple", 1);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.UPKEEP);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
|
||||||
|
assertDuplicatedManaOptions(manaOptions);
|
||||||
|
|
||||||
|
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
|
||||||
|
assertManaOptions("{C}", manaOptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ public class ActivateIfConditionManaAbility extends ActivatedManaAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return new StringBuilder(super.getRule()).append(" Activate this ability only if ").append(condition.toString()).append('.').toString();
|
return super.getRule() + " Activate this ability only if " + condition.toString() + '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,11 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return netMana;
|
ArrayList<Mana> netManaCopy = new ArrayList<>();
|
||||||
|
for (Mana mana : netMana) {
|
||||||
|
netManaCopy.add(mana.copy());
|
||||||
|
}
|
||||||
|
return netManaCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
*/
|
*/
|
||||||
package mage.abilities.mana;
|
package mage.abilities.mana;
|
||||||
|
|
||||||
import mage.Mana;
|
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.effects.mana.AddConditionalColorlessManaEffect;
|
import mage.abilities.effects.mana.AddConditionalColorlessManaEffect;
|
||||||
|
|
@ -24,7 +23,7 @@ public class ConditionalColorlessManaAbility extends ActivatedManaAbilityImpl {
|
||||||
|
|
||||||
public ConditionalColorlessManaAbility(Cost cost, int amount, ConditionalManaBuilder manaBuilder) {
|
public ConditionalColorlessManaAbility(Cost cost, int amount, ConditionalManaBuilder manaBuilder) {
|
||||||
super(Zone.BATTLEFIELD, new AddConditionalColorlessManaEffect(amount, manaBuilder), cost);
|
super(Zone.BATTLEFIELD, new AddConditionalColorlessManaEffect(amount, manaBuilder), cost);
|
||||||
this.netMana.add(Mana.ColorlessMana(amount));
|
// this.netMana.add(Mana.ColorlessMana(amount)); // When produced during runtime, condition is added (how to add condition here?)
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConditionalColorlessManaAbility(final ConditionalColorlessManaAbility ability) {
|
public ConditionalColorlessManaAbility(final ConditionalColorlessManaAbility ability) {
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,13 @@ import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
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.abilities.costs.Cost;
|
||||||
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.events.ManaEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -64,43 +68,51 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
//if there is only one mana option available add it to all the existing options
|
//if there is only one mana option available add it to all the existing options
|
||||||
List<Mana> netManas = abilities.get(0).getNetMana(game);
|
List<Mana> netManas = abilities.get(0).getNetMana(game);
|
||||||
if (netManas.size() == 1) {
|
if (netManas.size() == 1) {
|
||||||
addMana(netManas.get(0));
|
if (!hasTapCost(abilities.get(0)) || checkTappedForManaReplacement(abilities.get(0), game, netManas.get(0))) {
|
||||||
|
addMana(netManas.get(0));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
List<Mana> copy = copy();
|
List<Mana> copy = copy();
|
||||||
this.clear();
|
this.clear();
|
||||||
|
boolean hasTapCost = hasTapCost(abilities.get(0));
|
||||||
for (Mana netMana : netManas) {
|
for (Mana netMana : netManas) {
|
||||||
for (Mana mana : copy) {
|
for (Mana mana : copy) {
|
||||||
Mana newMana = new Mana();
|
if (!hasTapCost || checkTappedForManaReplacement(abilities.get(0), game, netMana)) {
|
||||||
newMana.add(mana);
|
Mana newMana = new Mana();
|
||||||
newMana.add(netMana);
|
newMana.add(mana);
|
||||||
this.add(newMana);
|
newMana.add(netMana);
|
||||||
|
this.add(newMana);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (abilities.size() > 1) {
|
} else { // mana source has more than 1 ability
|
||||||
//perform a union of all existing options and the new options
|
//perform a union of all existing options and the new options
|
||||||
List<Mana> copy = copy();
|
List<Mana> copy = copy();
|
||||||
this.clear();
|
this.clear();
|
||||||
for (ActivatedManaAbilityImpl ability : abilities) {
|
for (ActivatedManaAbilityImpl ability : abilities) {
|
||||||
|
boolean hasTapCost = hasTapCost(ability);
|
||||||
for (Mana netMana : ability.getNetMana(game)) {
|
for (Mana netMana : ability.getNetMana(game)) {
|
||||||
SkipAddMana:
|
if (!hasTapCost || checkTappedForManaReplacement(ability, game, netMana)) {
|
||||||
for (Mana mana : copy) {
|
SkipAddMana:
|
||||||
Mana newMana = new Mana();
|
for (Mana mana : copy) {
|
||||||
newMana.add(mana);
|
Mana newMana = new Mana();
|
||||||
newMana.add(netMana);
|
newMana.add(mana);
|
||||||
for (Mana existingMana : this) {
|
newMana.add(netMana);
|
||||||
if (existingMana.equalManaValue(newMana)) {
|
for (Mana existingMana : this) {
|
||||||
continue SkipAddMana;
|
if (existingMana.equalManaValue(newMana)) {
|
||||||
}
|
continue SkipAddMana;
|
||||||
Mana moreValuable = Mana.getMoreValuableMana(newMana, existingMana);
|
}
|
||||||
if (moreValuable != null) {
|
Mana moreValuable = Mana.getMoreValuableMana(newMana, existingMana);
|
||||||
// only keep the more valuable mana
|
if (moreValuable != null) {
|
||||||
existingMana.setToMana(moreValuable);
|
// only keep the more valuable mana
|
||||||
continue SkipAddMana;
|
existingMana.setToMana(moreValuable);
|
||||||
|
continue SkipAddMana;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this.add(newMana);
|
||||||
}
|
}
|
||||||
this.add(newMana);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -108,6 +120,23 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkTappedForManaReplacement(Ability ability, Game game, Mana mana) {
|
||||||
|
ManaEvent event = new ManaEvent(GameEvent.EventType.TAPPED_FOR_MANA, ability.getSourceId(), ability.getSourceId(), ability.getControllerId(), mana);
|
||||||
|
if (!game.replaceEvent(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasTapCost(Ability ability) {
|
||||||
|
for (Cost cost : ability.getCosts()) {
|
||||||
|
if (cost instanceof TapSourceCost) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void addManaWithCost(List<ActivatedManaAbilityImpl> abilities, Game game) {
|
public void addManaWithCost(List<ActivatedManaAbilityImpl> abilities, Game game) {
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
this.add(new Mana());
|
this.add(new Mana());
|
||||||
|
|
@ -153,37 +182,41 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
List<Mana> copy = copy();
|
List<Mana> copy = copy();
|
||||||
this.clear();
|
this.clear();
|
||||||
for (ActivatedManaAbilityImpl ability : abilities) {
|
for (ActivatedManaAbilityImpl ability : abilities) {
|
||||||
|
boolean hasTapCost = hasTapCost(ability);
|
||||||
List<Mana> netManas = ability.getNetMana(game);
|
List<Mana> netManas = ability.getNetMana(game);
|
||||||
|
|
||||||
if (ability.getManaCosts().isEmpty()) {
|
if (ability.getManaCosts().isEmpty()) {
|
||||||
for (Mana netMana : netManas) {
|
for (Mana netMana : netManas) {
|
||||||
for (Mana mana : copy) {
|
if (!hasTapCost || checkTappedForManaReplacement(ability, game, netMana)) {
|
||||||
Mana newMana = new Mana();
|
for (Mana mana : copy) {
|
||||||
newMana.add(mana);
|
Mana newMana = new Mana();
|
||||||
newMana.add(netMana);
|
newMana.add(mana);
|
||||||
this.add(newMana);
|
newMana.add(netMana);
|
||||||
|
this.add(newMana);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (Mana netMana : netManas) {
|
for (Mana netMana : netManas) {
|
||||||
for (Mana previousMana : copy) {
|
if (!hasTapCost || checkTappedForManaReplacement(ability, game, netMana)) {
|
||||||
CombineWithExisting:
|
for (Mana previousMana : copy) {
|
||||||
for (Mana manaOption : ability.getManaCosts().getManaOptions()) {
|
CombineWithExisting:
|
||||||
Mana newMana = new Mana(previousMana);
|
for (Mana manaOption : ability.getManaCosts().getManaOptions()) {
|
||||||
if (previousMana.includesMana(manaOption)) { // costs can be paid
|
Mana newMana = new Mana(previousMana);
|
||||||
newMana.subtractCost(manaOption);
|
if (previousMana.includesMana(manaOption)) { // costs can be paid
|
||||||
newMana.add(netMana);
|
newMana.subtractCost(manaOption);
|
||||||
// if the new mana is in all colors more than another already existing than replace
|
newMana.add(netMana);
|
||||||
for (Mana existingMana : this) {
|
// if the new mana is in all colors more than another already existing than replace
|
||||||
Mana moreValuable = Mana.getMoreValuableMana(newMana, existingMana);
|
for (Mana existingMana : this) {
|
||||||
if (moreValuable != null) {
|
Mana moreValuable = Mana.getMoreValuableMana(newMana, existingMana);
|
||||||
existingMana.setToMana(moreValuable);
|
if (moreValuable != null) {
|
||||||
continue CombineWithExisting;
|
existingMana.setToMana(moreValuable);
|
||||||
|
continue CombineWithExisting;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// no existing Mana includes this new mana so add
|
||||||
|
this.add(newMana);
|
||||||
}
|
}
|
||||||
// no existing Mana includes this new mana so add
|
|
||||||
this.add(newMana);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -330,16 +363,15 @@ public class ManaOptions extends ArrayList<Mana> {
|
||||||
payCombinationsStrings.add(newMana.toString());
|
payCombinationsStrings.add(newMana.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeDuplicated() {
|
||||||
public void removeDuplicated(){
|
|
||||||
Set<String> list = new HashSet<>();
|
Set<String> list = new HashSet<>();
|
||||||
|
|
||||||
for(int i = this.size() - 1; i >= 0; i--){
|
for (int i = this.size() - 1; i >= 0; i--) {
|
||||||
String s = this.get(i).toString();
|
String s = this.get(i).toString();
|
||||||
if (list.contains(s)){
|
if (list.contains(s)) {
|
||||||
// remove duplicated
|
// remove duplicated
|
||||||
this.remove(i);
|
this.remove(i);
|
||||||
}else{
|
} else {
|
||||||
list.add(s);
|
list.add(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue