tests: improved show playable abilities to print playable list instead unique (see showAvailableAbilities), added custom effect for transform tests (see addCustomEffect_TransformTarget);

This commit is contained in:
Oleg Agafonov 2023-12-10 14:31:55 +04:00
parent 3b603595a2
commit 50fd029c3b
5 changed files with 100 additions and 25 deletions

View file

@ -1026,10 +1026,10 @@ public class TestPlayer implements Player {
wasProccessed = true;
}
// show available abilities
if (params[0].equals(SHOW_COMMAND_AVAILABLE_ABILITIES) && params.length == 1) {
// show available abilities: show only unique list
if (params[0].equals(SHOW_COMMAND_AVAILABLE_ABILITIES) && params.length == 2) {
printStart(game, action.getActionName());
printAbilities(game, computerPlayer.getPlayable(game, true));
printAbilities(game, computerPlayer.getPlayable(game, true, Zone.ALL, Boolean.parseBoolean(params[1])));
printEnd();
actions.remove(action);
wasProccessed = true;
@ -1247,13 +1247,12 @@ public class TestPlayer implements Player {
if (abilities == null) {
return;
}
List<String> data = abilities.stream()
.map(a -> (a.getZone() + " -> "
+ a.getSourceObject(game).getIdName() + " -> "
+ (a.toString().startsWith("Cast ") ? "[" + a.getManaCostsToPay().getText() + "] -> " : "") // printed cost, not modified
+ (a.toString().length() > 0
? a.toString().substring(0, Math.min(40, a.toString().length())) + "..."
? CardUtil.substring(a.toString(), 40, "...")
: a.getClass().getSimpleName())
))
.sorted()

View file

@ -9,10 +9,7 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.ReturnFromExileEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.abilities.effects.common.*;
import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionAllEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
@ -519,6 +516,21 @@ public abstract class MageTestPlayerBase {
);
}
/**
* Add target transform ability that can be called by text "target transform"
*
* @param controller
*/
protected void addCustomEffect_TransformTarget(TestPlayer controller) {
Ability ability = new SimpleActivatedAbility(new TransformTargetEffect().setText("target transform"), new ManaCostsImpl<>(""));
ability.addTarget(new TargetPermanent());
addCustomCardWithAbility(
"target transform for " + controller.getName(),
controller,
ability
);
}
/**
* Return target card to hand that can be called by text "return from ..."
*

View file

@ -540,7 +540,14 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void showAvailableAbilities(String showName, int turnNum, PhaseStep step, TestPlayer player) {
show(showName, turnNum, step, player, SHOW_COMMAND_AVAILABLE_ABILITIES);
showAvailableAbilities(showName, turnNum, step, player, true);
}
/**
* @param showOnlyUniqueAbilities return full list or unique only (duplicated abilities with same name will be combined in one)
*/
public void showAvailableAbilities(String showName, int turnNum, PhaseStep step, TestPlayer player, Boolean showOnlyUniqueAbilities) {
show(showName, turnNum, step, player, SHOW_COMMAND_AVAILABLE_ABILITIES, showOnlyUniqueAbilities.toString());
}
public void showAvailableMana(String showName, int turnNum, PhaseStep step, TestPlayer player) {

View file

@ -2,6 +2,8 @@ package org.mage.test.utils;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.util.CardUtil;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -75,7 +77,7 @@ public class CardUtilTest extends CardTestPlayerBase {
@Test
public void testJadziPlayingLandAndCast() {
addCard(Zone.BATTLEFIELD, playerA, jadzi);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1+1+1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1 + 1 + 1);
addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
addCard(Zone.LIBRARY, playerA, "Cragcrown Pathway");
addCard(Zone.LIBRARY, playerA, akoumWarrior);
@ -92,4 +94,32 @@ public class CardUtilTest extends CardTestPlayerBase {
assertPermanentCount(playerA, akoumWarrior, 1);
assertPermanentCount(playerA, "Cragcrown Pathway", 1);
}
@Test
public void test_Substring() {
String str = "12345";
String ending = "...";
Assert.assertEquals("", CardUtil.substring(str, 0));
Assert.assertEquals("1", CardUtil.substring(str, 1));
Assert.assertEquals("12", CardUtil.substring(str, 2));
Assert.assertEquals("123", CardUtil.substring(str, 3));
Assert.assertEquals("1234", CardUtil.substring(str, 4));
Assert.assertEquals("12345", CardUtil.substring(str, 5));
Assert.assertEquals("12345", CardUtil.substring(str, 6));
Assert.assertEquals("12345", CardUtil.substring(str, 7));
Assert.assertEquals("12345", CardUtil.substring(str, 8));
Assert.assertEquals("12345", CardUtil.substring(str, 9));
Assert.assertEquals("", CardUtil.substring(str, 0, ending));
Assert.assertEquals(".", CardUtil.substring(str, 1, ending));
Assert.assertEquals("..", CardUtil.substring(str, 2, ending));
Assert.assertEquals("...", CardUtil.substring(str, 3, ending));
Assert.assertEquals("1...", CardUtil.substring(str, 4, ending));
Assert.assertEquals("12345", CardUtil.substring(str, 5, ending));
Assert.assertEquals("12345", CardUtil.substring(str, 6, ending));
Assert.assertEquals("12345", CardUtil.substring(str, 7, ending));
Assert.assertEquals("12345", CardUtil.substring(str, 8, ending));
Assert.assertEquals("12345", CardUtil.substring(str, 9, ending));
}
}

View file

@ -905,7 +905,7 @@ public final class CardUtil {
}
public static String getSimpleCountersText(int amount, String forOne, String counterType) {
return numberToText(amount, forOne)+" "+counterType+" counter"+ (amount==1 ? "" : "s");
return numberToText(amount, forOne) + " " + counterType + " counter" + (amount == 1 ? "" : "s");
}
public static String getOneOneCountersText(int amount) {
@ -1654,6 +1654,7 @@ public final class CardUtil {
}
return zcc;
}
/**
* Create a MageObjectReference of the ability's source
* Subtract 1 zcc if not on the stack, referencing when it was on the stack if it's a resolved permanent.
@ -1702,19 +1703,21 @@ public final class CardUtil {
}
return costTags;
}
/**
* Check if a specific tag exists in the cost tags of either the source ability, or the permanent source of the ability.
* Works in any moment (even before source ability activated)
*
* @param game
* @param source
* @param tag The tag's string identifier to look up
* @param tag The tag's string identifier to look up
* @return if the tag was found
*/
public static boolean checkSourceCostsTagExists(Game game, Ability source, String tag) {
Map<String, Object> costTags = getSourceCostsTagsMap(game, source);
return costTags != null && costTags.containsKey(tag);
}
/**
* Find a specific tag in the cost tags of either the source ability, or the permanent source of the ability.
* Works in any moment (even before source ability activated)
@ -1722,11 +1725,11 @@ public final class CardUtil {
*
* @param game
* @param source
* @param tag The tag's string identifier to look up
* @param tag The tag's string identifier to look up
* @param defaultValue A default value to return if the tag is not found
* @return The object stored by the tag if found, the default if not
*/
public static <T> T getSourceCostsTag(Game game, Ability source, String tag, T defaultValue){
public static <T> T getSourceCostsTag(Game game, Ability source, String tag, T defaultValue) {
Map<String, Object> costTags = getSourceCostsTagsMap(game, source);
if (costTags != null) {
Object value = costTags.getOrDefault(tag, defaultValue);
@ -1748,13 +1751,14 @@ public final class CardUtil {
return "pay " + text;
}
private static boolean isImmutableObject(Object o){
private static boolean isImmutableObject(Object o) {
return o == null
|| o instanceof Number || o instanceof Boolean || o instanceof String
|| o instanceof MageObjectReference || o instanceof UUID
|| o instanceof Enum;
}
public static <T> T deepCopyObject(T value){
public static <T> T deepCopyObject(T value) {
if (isImmutableObject(value)) {
return value;
} else if (value instanceof Copyable) {
@ -1781,53 +1785,58 @@ public final class CardUtil {
return (T) deepCopyHashMap((HashMap) value);
} else if (value instanceof List) {
return (T) deepCopyList((List) value);
} else if (value instanceof AbstractMap.SimpleImmutableEntry){ //Used by Leonin Arbiter, Vessel Of The All Consuming Wanderer as a generic Pair class
} else if (value instanceof AbstractMap.SimpleImmutableEntry) { //Used by Leonin Arbiter, Vessel Of The All Consuming Wanderer as a generic Pair class
AbstractMap.SimpleImmutableEntry entryValue = (AbstractMap.SimpleImmutableEntry) value;
return (T) new AbstractMap.SimpleImmutableEntry(deepCopyObject(entryValue.getKey()),deepCopyObject(entryValue.getValue()));
return (T) new AbstractMap.SimpleImmutableEntry(deepCopyObject(entryValue.getKey()), deepCopyObject(entryValue.getValue()));
} else {
throw new IllegalStateException("Unhandled object " + value.getClass().getSimpleName() + " during deep copy, must add explicit handling of all Object types");
}
}
private static <T extends Comparable<T>> TreeSet<T> deepCopyTreeSet(TreeSet<T> original) {
if (original.getClass() != TreeSet.class) {
throw new IllegalStateException("Unhandled TreeSet type " + original.getClass().getSimpleName() + " in deep copy");
}
TreeSet<T> newSet = new TreeSet<>();
for (T value : original){
for (T value : original) {
newSet.add((T) deepCopyObject(value));
}
return newSet;
}
private static <T> HashSet<T> deepCopyHashSet(Set<T> original) {
if (original.getClass() != HashSet.class) {
throw new IllegalStateException("Unhandled HashSet type " + original.getClass().getSimpleName() + " in deep copy");
}
HashSet<T> newSet = new HashSet<>(original.size());
for (T value : original){
for (T value : original) {
newSet.add((T) deepCopyObject(value));
}
return newSet;
}
private static <T> LinkedHashSet<T> deepCopyLinkedHashSet(LinkedHashSet<T> original) {
if (original.getClass() != LinkedHashSet.class) {
throw new IllegalStateException("Unhandled LinkedHashSet type " + original.getClass().getSimpleName() + " in deep copy");
}
LinkedHashSet<T> newSet = new LinkedHashSet<>(original.size());
for (T value : original){
for (T value : original) {
newSet.add((T) deepCopyObject(value));
}
return newSet;
}
private static <T> List<T> deepCopyList(List<T> original) { //always returns an ArrayList
if (original.getClass() != ArrayList.class) {
throw new IllegalStateException("Unhandled List type " + original.getClass().getSimpleName() + " in deep copy");
}
ArrayList<T> newList = new ArrayList<>(original.size());
for (T value : original){
for (T value : original) {
newList.add((T) deepCopyObject(value));
}
return newList;
}
private static <K, V> HashMap<K, V> deepCopyHashMap(Map<K, V> original) {
if (original.getClass() != HashMap.class) {
throw new IllegalStateException("Unhandled HashMap type " + original.getClass().getSimpleName() + " in deep copy");
@ -1838,6 +1847,7 @@ public final class CardUtil {
}
return newMap;
}
private static <K, V> LinkedHashMap<K, V> deepCopyLinkedHashMap(Map<K, V> original) {
if (original.getClass() != LinkedHashMap.class) {
throw new IllegalStateException("Unhandled LinkedHashMap type " + original.getClass().getSimpleName() + " in deep copy");
@ -1848,6 +1858,7 @@ public final class CardUtil {
}
return newMap;
}
private static <K extends Enum<K>, V> EnumMap<K, V> deepCopyEnumMap(Map<K, V> original) {
if (original.getClass() != EnumMap.class) {
throw new IllegalStateException("Unhandled EnumMap type " + original.getClass().getSimpleName() + " in deep copy");
@ -2076,18 +2087,34 @@ public final class CardUtil {
}
}
public static String substring(String str, int maxLength) {
return substring(str, maxLength, "");
}
/**
* Don't raise exception, so must be used instead standard substring calls all the time
*
* @param str
* @param maxLength
* @param overflowEnding can add ... at the end
* @return
*/
public static String substring(String str, int maxLength) {
public static String substring(String str, int maxLength, String overflowEnding) {
if (str == null || str.isEmpty()) {
return str;
}
return str.substring(0, Math.min(str.length(), maxLength));
// full
if (str.length() <= maxLength) {
return str;
}
// short
if (maxLength <= overflowEnding.length()) {
return overflowEnding.substring(0, maxLength);
} else {
return (str + overflowEnding).substring(0, maxLength - overflowEnding.length()) + overflowEnding;
}
}