mirror of
https://github.com/correl/mage.git
synced 2024-11-25 03:00:11 +00:00
* Mana pay to cast - fixed random values in games with AI (example: Marath, Will of the Wild, see #8204);
This commit is contained in:
parent
3a8e04f2bc
commit
473a81e13c
3 changed files with 73 additions and 1 deletions
|
@ -3,6 +3,9 @@ package org.mage.test.cards.single.c13;
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.watchers.common.ManaPaidSourceWatcher;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestCommanderDuelBase;
|
import org.mage.test.serverside.base.CardTestCommanderDuelBase;
|
||||||
|
|
||||||
|
@ -31,6 +34,32 @@ public class MarathWillOfTheWildTest extends CardTestCommanderDuelBase {
|
||||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
checkPermanentCounters("after first cast must have 3x counters", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Marath, Will of the Wild", CounterType.P1P1, 3);
|
checkPermanentCounters("after first cast must have 3x counters", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Marath, Will of the Wild", CounterType.P1P1, 3);
|
||||||
|
|
||||||
|
// COPY WATCHER testing (e.g. rollback compatible)
|
||||||
|
runCode("test copy watcher", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||||
|
ManaPaidSourceWatcher watcher = game.getState().getWatcher(ManaPaidSourceWatcher.class);
|
||||||
|
Permanent perm = game.getBattlefield().getAllPermanents()
|
||||||
|
.stream()
|
||||||
|
.filter(p -> p.getName().equals("Marath, Will of the Wild"))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
Assert.assertNotNull(perm);
|
||||||
|
|
||||||
|
// check correct copy
|
||||||
|
int before = watcher.testsReturnTotal(perm);
|
||||||
|
Assert.assertEquals("original must have 3x", 3, before);
|
||||||
|
ManaPaidSourceWatcher copiedWatcher = watcher.copy();
|
||||||
|
int after = copiedWatcher.testsReturnTotal(perm);
|
||||||
|
Assert.assertEquals("copied must have 3x", before, after);
|
||||||
|
|
||||||
|
// check correct refs and changes
|
||||||
|
// simulate ai games (changes in copied watcher must not touch original watcher)
|
||||||
|
copiedWatcher.testsIncrementManaAmount(game, perm);
|
||||||
|
int afterChangeCopied = copiedWatcher.testsReturnTotal(perm);
|
||||||
|
int afterChangeOriginal = watcher.testsReturnTotal(perm);
|
||||||
|
Assert.assertEquals("after change, copied", 4, afterChangeCopied);
|
||||||
|
Assert.assertEquals("after change, original", 3, afterChangeOriginal);
|
||||||
|
});
|
||||||
|
|
||||||
// kill
|
// kill
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Marath, Will of the Wild");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Marath, Will of the Wild");
|
||||||
setChoice(playerA, true); // move to command
|
setChoice(playerA, true); // move to command
|
||||||
|
|
|
@ -5,6 +5,7 @@ import mage.constants.WatcherScope;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.players.PlayerList;
|
import mage.players.PlayerList;
|
||||||
|
import mage.util.Copyable;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -142,6 +143,14 @@ public abstract class Watcher implements Serializable {
|
||||||
Cards list = e.getValue().copy();
|
Cards list = e.getValue().copy();
|
||||||
target.put(e.getKey(), list);
|
target.put(e.getKey(), list);
|
||||||
}
|
}
|
||||||
|
} else if (Arrays.stream(((Class) valueType).getInterfaces()).anyMatch(c -> c.equals(Copyable.class))) {
|
||||||
|
Map<Object, Copyable> source = (Map<Object, Copyable>) field.get(this);
|
||||||
|
Map<Object, Copyable> target = (Map<Object, Copyable>) field.get(watcher);
|
||||||
|
target.clear();
|
||||||
|
for (Map.Entry<Object, Copyable> e : source.entrySet()) {
|
||||||
|
Copyable object = (Copyable) e.getValue().copy();
|
||||||
|
target.put(e.getKey(), object);
|
||||||
|
}
|
||||||
} else if (valueType.getTypeName().contains("List")) {
|
} else if (valueType.getTypeName().contains("List")) {
|
||||||
Map<Object, List<Object>> source = (Map<Object, List<Object>>) field.get(this);
|
Map<Object, List<Object>> source = (Map<Object, List<Object>>) field.get(this);
|
||||||
Map<Object, List<Object>> target = (Map<Object, List<Object>>) field.get(watcher);
|
Map<Object, List<Object>> target = (Map<Object, List<Object>>) field.get(watcher);
|
||||||
|
@ -161,6 +170,8 @@ public abstract class Watcher implements Serializable {
|
||||||
target.put(e.getKey(), map);
|
target.put(e.getKey(), map);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: add additional tests to find unsupported watcher data
|
||||||
|
|
||||||
((Map) field.get(watcher)).putAll((Map) field.get(this));
|
((Map) field.get(watcher)).putAll((Map) field.get(this));
|
||||||
}
|
}
|
||||||
} else if (field.getType() == List.class) {
|
} else if (field.getType() == List.class) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import mage.game.events.GameEvent;
|
||||||
import mage.game.events.ManaPaidEvent;
|
import mage.game.events.ManaPaidEvent;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
|
import mage.util.Copyable;
|
||||||
import mage.watchers.Watcher;
|
import mage.watchers.Watcher;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -25,7 +26,8 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public class ManaPaidSourceWatcher extends Watcher {
|
public class ManaPaidSourceWatcher extends Watcher {
|
||||||
|
|
||||||
private static final class ManaPaidTracker implements Serializable {
|
private static final class ManaPaidTracker implements Serializable, Copyable<ManaPaidTracker> {
|
||||||
|
|
||||||
private int total = 0;
|
private int total = 0;
|
||||||
private int whiteSnow = 0;
|
private int whiteSnow = 0;
|
||||||
private int blueSnow = 0;
|
private int blueSnow = 0;
|
||||||
|
@ -35,6 +37,26 @@ public class ManaPaidSourceWatcher extends Watcher {
|
||||||
private int colorlessSnow = 0;
|
private int colorlessSnow = 0;
|
||||||
private int treasure = 0;
|
private int treasure = 0;
|
||||||
|
|
||||||
|
private ManaPaidTracker() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ManaPaidTracker(final ManaPaidTracker tracker) {
|
||||||
|
this.total = tracker.total;
|
||||||
|
this.whiteSnow = tracker.whiteSnow;
|
||||||
|
this.blueSnow = tracker.blueSnow;
|
||||||
|
this.blackSnow = tracker.blackSnow;
|
||||||
|
this.redSnow = tracker.redSnow;
|
||||||
|
this.greenSnow = tracker.greenSnow;
|
||||||
|
this.colorlessSnow = tracker.colorlessSnow;
|
||||||
|
this.treasure = tracker.treasure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ManaPaidTracker copy() {
|
||||||
|
return new ManaPaidTracker(this);
|
||||||
|
}
|
||||||
|
|
||||||
private void increment(MageObject sourceObject, ManaType manaType, Game game) {
|
private void increment(MageObject sourceObject, ManaType manaType, Game game) {
|
||||||
total++;
|
total++;
|
||||||
if (sourceObject.hasSubtype(SubType.TREASURE, game)) {
|
if (sourceObject.hasSubtype(SubType.TREASURE, game)) {
|
||||||
|
@ -129,4 +151,14 @@ public class ManaPaidSourceWatcher extends Watcher {
|
||||||
ManaPaidSourceWatcher watcher = game.getState().getWatcher(ManaPaidSourceWatcher.class);
|
ManaPaidSourceWatcher watcher = game.getState().getWatcher(ManaPaidSourceWatcher.class);
|
||||||
return watcher != null && watcher.manaMap.getOrDefault(spell.getSpellAbility().getId(), emptyTracker).checkSnowColor(spell, game);
|
return watcher != null && watcher.manaMap.getOrDefault(spell.getSpellAbility().getId(), emptyTracker).checkSnowColor(spell, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testsIncrementManaAmount(Game game, MageObject mageObject) {
|
||||||
|
// for tests only (logic here: change data in tracker like real event do)
|
||||||
|
this.manaMap.getOrDefault(mageObject.getId(), null).increment(mageObject, ManaType.RED, game);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int testsReturnTotal(MageObject mageObject) {
|
||||||
|
// for tests only
|
||||||
|
return this.manaMap.getOrDefault(mageObject.getId(), null).total;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue