Refactoring snow mana to allow tracking how much is spent (Ready for Review) (#7406)

* refactored mana methods to WUBRG order

* more WUBRG refactoring

* added new mana tracking object

* fixed code error

* fixed missing mana count

* fixed null pointer exception in tests

* fixed issue with equality

* more equality fixes

* some cosmetic changes to ManaTest

* added copy method to setToMana

* fixed some initialization issues

* fixed serialization issue

* [KHM] Implemented Search for Glory

* updated mana handling to track snow

* added tests for snow mana tracking

* updated implementation of setter methods

* updated paramater to use copy methods

* fixed snow mana test to ensure proper mana tapping

* replaced instances of getPayment with getUsedManaToPay

* updated tracking of snow mana

* reverted snow mana tracking removal

* finished reverting change
This commit is contained in:
Evan Kranzler 2021-01-21 18:13:51 -05:00 committed by GitHub
parent 5e4b5239d8
commit e5344b7a96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
99 changed files with 1006 additions and 720 deletions

View file

@ -1,8 +1,7 @@
package mage.players;
import java.io.Serializable;
import java.util.*;
import mage.ConditionalMana;
import mage.MageObject;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
@ -18,6 +17,9 @@ import mage.game.events.ManaEvent;
import mage.game.events.ManaPaidEvent;
import mage.game.stack.Spell;
import java.io.Serializable;
import java.util.*;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -35,12 +37,25 @@ public class ManaPool implements Serializable {
private final Set<ManaType> doNotEmptyManaTypes = new HashSet<>();
private static final class ConditionalManaInfo {
private final ManaType manaType;
private final MageObject sourceObject;
private ConditionalManaInfo(ManaType conditionalMana, MageObject sourceObject) {
this.manaType = conditionalMana;
this.sourceObject = sourceObject;
}
}
private boolean lastPaymentWasSnow;
public ManaPool(UUID playerId) {
this.playerId = playerId;
autoPayment = true;
autoPaymentRestricted = true;
unlockedManaType = null;
forcedToPay = false;
lastPaymentWasSnow = false;
}
public ManaPool(final ManaPool pool) {
@ -56,6 +71,7 @@ public class ManaPool implements Serializable {
poolBookmark.add(item.copy());
}
this.doNotEmptyManaTypes.addAll(pool.doNotEmptyManaTypes);
this.lastPaymentWasSnow = pool.lastPaymentWasSnow;
}
public int getRed() {
@ -89,6 +105,7 @@ public class ManaPool implements Serializable {
* @return
*/
public boolean pay(ManaType manaType, Ability ability, Filter filter, Game game, Cost costToPay, Mana usedManaToPay) {
lastPaymentWasSnow = false;
if (!isAutoPayment() && manaType != unlockedManaType) {
// if manual payment and the needed mana type was not unlocked, nothing will be paid
return false;
@ -112,12 +129,13 @@ public class ManaPool implements Serializable {
}
}
// first try to pay from conditional mana (the returned manaType can be changed if AsThoughEffects are active)
ManaType conditionalManaType = getConditional(manaType, ability, filter, game, costToPay, possibleAsThoughPoolManaType);
if (conditionalManaType != null) {
removeConditional(conditionalManaType, ability, game, costToPay, usedManaToPay);
ConditionalManaInfo manaInfo = getConditional(manaType, ability, filter, game, costToPay, possibleAsThoughPoolManaType);
if (manaInfo != null) {
removeConditional(manaInfo, ability, game, costToPay, usedManaToPay);
lockManaType(); // pay only one mana if mana payment is set to manually
return true;
}
lastPaymentWasSnow = false;
for (ManaPoolItem mana : manaItems) {
if (filter != null) {
@ -144,8 +162,9 @@ public class ManaPool implements Serializable {
if (mana.get(usableManaType) > 0) {
GameEvent event = new ManaPaidEvent(ability, mana.getSourceId(), mana.getFlag(), mana.getOriginalId());
game.fireEvent(event);
usedManaToPay.increase(usableManaType);
usedManaToPay.increase(usableManaType, mana.getSourceObject().isSnow());
mana.remove(usableManaType);
lastPaymentWasSnow |= mana.getSourceObject().isSnow();
if (mana.count() == 0) { // so no items with count 0 stay in list
manaItems.remove(mana);
}
@ -160,7 +179,7 @@ public class ManaPool implements Serializable {
return getMana().get(manaType);
}
private ManaType getConditional(ManaType manaType, Ability ability, Filter filter, Game game, Cost costToPay, ManaType possibleAsThoughPoolManaType) {
private ConditionalManaInfo getConditional(ManaType manaType, Ability ability, Filter filter, Game game, Cost costToPay, ManaType possibleAsThoughPoolManaType) {
if (ability == null || getConditionalMana().isEmpty()) {
return null;
}
@ -180,7 +199,7 @@ public class ManaPool implements Serializable {
if (manaTypeToUse != null && mana.getConditionalMana().apply(ability, game, mana.getSourceId(), costToPay)) {
if (filter == null
|| filter.match(mana.getSourceObject(), game)) {
return manaTypeToUse;
return new ConditionalManaInfo(manaTypeToUse, mana.getSourceObject());
}
}
}
@ -313,7 +332,7 @@ public class ManaPool implements Serializable {
if (mana instanceof ConditionalMana) {
ManaPoolItem item = new ManaPoolItem((ConditionalMana) mana, source.getSourceObject(game),
((ConditionalMana) mana).getManaProducerOriginalId() != null
? ((ConditionalMana) mana).getManaProducerOriginalId() : source.getOriginalId());
? ((ConditionalMana) mana).getManaProducerOriginalId() : source.getOriginalId());
if (emptyOnTurnsEnd) {
item.setDuration(Duration.EndOfTurn);
}
@ -365,11 +384,11 @@ public class ManaPool implements Serializable {
return new ManaPool(this);
}
private void removeConditional(ManaType manaType, Ability ability, Game game, Cost costToPay, Mana usedManaToPay) {
private void removeConditional(ConditionalManaInfo manaInfo, Ability ability, Game game, Cost costToPay, Mana usedManaToPay) {
for (ConditionalMana mana : getConditionalMana()) {
if (mana.get(manaType) > 0 && mana.apply(ability, game, mana.getManaProducerId(), costToPay)) {
mana.set(manaType, mana.get(manaType) - 1);
usedManaToPay.increase(manaType);
if (mana.get(manaInfo.manaType) > 0 && mana.apply(ability, game, mana.getManaProducerId(), costToPay)) {
mana.set(manaInfo.manaType, mana.get(manaInfo.manaType) - 1);
usedManaToPay.increase(manaInfo.manaType, manaInfo.sourceObject.isSnow());
GameEvent event = new ManaPaidEvent(ability, mana.getManaProducerId(), mana.getFlag(), mana.getManaProducerOriginalId());
game.fireEvent(event);
break;
@ -486,4 +505,8 @@ public class ManaPool implements Serializable {
throw new IllegalArgumentException("Wrong mana type " + manaType);
}
}
public boolean getLastPaymentWasSnow() {
return lastPaymentWasSnow;
}
}