Merge remote-tracking branch 'upstream/master' into collector-number-in-card-list-and-card-db-refactoring

This commit is contained in:
leriomaggio
2021-05-24 21:09:58 +01:00
21 changed files with 189 additions and 348 deletions

View File

@@ -76,7 +76,7 @@ public class ComputerUtilCard {
} }
}); });
} }
return ComputerUtilCard.getMostExpensivePermanentAI(all); return getMostExpensivePermanentAI(all);
} }
/** /**
@@ -381,7 +381,7 @@ public class ComputerUtilCard {
} }
if (biasLand && Iterables.any(list, CardPredicates.Presets.LANDS)) { if (biasLand && Iterables.any(list, CardPredicates.Presets.LANDS)) {
return ComputerUtilCard.getWorstLand(CardLists.filter(list, CardPredicates.Presets.LANDS)); return getWorstLand(CardLists.filter(list, CardPredicates.Presets.LANDS));
} }
final boolean hasCreatures = Iterables.any(list, CardPredicates.Presets.CREATURES); final boolean hasCreatures = Iterables.any(list, CardPredicates.Presets.CREATURES);
@@ -391,7 +391,7 @@ public class ComputerUtilCard {
List<Card> lands = CardLists.filter(list, CardPredicates.Presets.LANDS); List<Card> lands = CardLists.filter(list, CardPredicates.Presets.LANDS);
if (lands.size() > 6) { if (lands.size() > 6) {
return ComputerUtilCard.getWorstLand(lands); return getWorstLand(lands);
} }
if (hasEnchantmants || hasArtifacts) { if (hasEnchantmants || hasArtifacts) {
@@ -441,7 +441,7 @@ public class ComputerUtilCard {
public static final Comparator<Card> EvaluateCreatureComparator = new Comparator<Card>() { public static final Comparator<Card> EvaluateCreatureComparator = new Comparator<Card>() {
@Override @Override
public int compare(final Card a, final Card b) { public int compare(final Card a, final Card b) {
return ComputerUtilCard.evaluateCreature(b) - ComputerUtilCard.evaluateCreature(a); return evaluateCreature(b) - evaluateCreature(a);
} }
}; };

View File

@@ -360,8 +360,7 @@ public class AnimateAi extends SpellAbilityAi {
// This is reasonable for now. Kamahl, Fist of Krosa and a sorcery or // This is reasonable for now. Kamahl, Fist of Krosa and a sorcery or
// two are the only things // two are the only things
// that animate a target. Those can just use AI:RemoveDeck:All until // that animate a target. Those can just use AI:RemoveDeck:All until
// this can do a reasonably // this can do a reasonably good job of picking a good target
// good job of picking a good target
return false; return false;
} }

View File

@@ -555,12 +555,7 @@ public class AttachAi extends SpellAbilityAi {
if (!evenBetterList.isEmpty()) { if (!evenBetterList.isEmpty()) {
betterList = evenBetterList; betterList = evenBetterList;
} }
evenBetterList = CardLists.filter(betterList, new Predicate<Card>() { evenBetterList = CardLists.filter(betterList, CardPredicates.Presets.UNTAPPED);
@Override
public boolean apply(final Card c) {
return c.isUntapped();
}
});
if (!evenBetterList.isEmpty()) { if (!evenBetterList.isEmpty()) {
betterList = evenBetterList; betterList = evenBetterList;
} }

View File

@@ -165,7 +165,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
return sa.isTargetNumberValid(); // Pre-targeted in checkAiLogic return sa.isTargetNumberValid(); // Pre-targeted in checkAiLogic
} }
} }
if (isHidden(sa)) { if (sa.isHidden()) {
return hiddenOriginCanPlayAI(aiPlayer, sa); return hiddenOriginCanPlayAI(aiPlayer, sa);
} }
return knownOriginCanPlayAI(aiPlayer, sa); return knownOriginCanPlayAI(aiPlayer, sa);
@@ -182,21 +182,12 @@ public class ChangeZoneAi extends SpellAbilityAi {
*/ */
@Override @Override
public boolean chkAIDrawback(SpellAbility sa, Player aiPlayer) { public boolean chkAIDrawback(SpellAbility sa, Player aiPlayer) {
if (isHidden(sa)) { if (sa.isHidden()) {
return hiddenOriginPlayDrawbackAI(aiPlayer, sa); return hiddenOriginPlayDrawbackAI(aiPlayer, sa);
} }
return knownOriginPlayDrawbackAI(aiPlayer, sa); return knownOriginPlayDrawbackAI(aiPlayer, sa);
} }
private static boolean isHidden(SpellAbility sa) {
boolean hidden = sa.hasParam("Hidden");
if (!hidden && sa.hasParam("Origin")) {
hidden = ZoneType.isHidden(sa.getParam("Origin"));
}
return hidden;
}
/** /**
* <p> * <p>
* changeZoneTriggerAINoCost. * changeZoneTriggerAINoCost.
@@ -232,7 +223,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
return delta <= 0; return delta <= 0;
} }
if (isHidden(sa)) { if (sa.isHidden()) {
return hiddenTriggerAI(aiPlayer, sa, mandatory); return hiddenTriggerAI(aiPlayer, sa, mandatory);
} }
return knownOriginTriggerAI(aiPlayer, sa, mandatory); return knownOriginTriggerAI(aiPlayer, sa, mandatory);
@@ -788,7 +779,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
return ph.getNextTurn().equals(ai) && ph.is(PhaseType.END_OF_TURN); return ph.getNextTurn().equals(ai) && ph.is(PhaseType.END_OF_TURN);
} }
if (isHidden(sa)) { if (sa.isHidden()) {
return true; return true;
} }
@@ -1316,8 +1307,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
private static Card canBouncePermanent(final Player ai, SpellAbility sa, CardCollectionView list) { private static Card canBouncePermanent(final Player ai, SpellAbility sa, CardCollectionView list) {
Game game = ai.getGame(); Game game = ai.getGame();
// filter out untargetables // filter out untargetables
CardCollectionView aiPermanents = CardLists CardCollectionView aiPermanents = CardLists.filterControlledBy(list, ai);
.filterControlledBy(list, ai);
CardCollection aiPlaneswalkers = CardLists.filter(aiPermanents, Presets.PLANESWALKERS); CardCollection aiPlaneswalkers = CardLists.filter(aiPermanents, Presets.PLANESWALKERS);
// Felidar Guardian + Saheeli Rai combo support // Felidar Guardian + Saheeli Rai combo support
@@ -1989,8 +1979,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
boolean setPayX = false; boolean setPayX = false;
if (unlessCost.equals("X") && sa.getSVar(unlessCost).equals("Count$xPaid")) { if (unlessCost.equals("X") && sa.getSVar(unlessCost).equals("Count$xPaid")) {
setPayX = true; setPayX = true;
// TODO use ComputerUtilCost.getMaxXValue if able toPay = ComputerUtilCost.getMaxXValue(sa, ai);
toPay = ComputerUtilMana.determineLeftoverMana(sa, ai);
} else { } else {
toPay = AbilityUtils.calculateAmount(source, unlessCost, sa); toPay = AbilityUtils.calculateAmount(source, unlessCost, sa);
} }

View File

@@ -12,7 +12,7 @@ import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPredicates.Presets; import forge.game.card.CardPredicates;
import forge.game.combat.CombatUtil; import forge.game.combat.CombatUtil;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
@@ -49,7 +49,7 @@ public class TapAllAi extends SpellAbilityAi {
} }
validTappables = CardLists.getValidCards(validTappables, valid, source.getController(), source, sa); validTappables = CardLists.getValidCards(validTappables, valid, source.getController(), source, sa);
validTappables = CardLists.filter(validTappables, Presets.UNTAPPED); validTappables = CardLists.filter(validTappables, CardPredicates.Presets.UNTAPPED);
if (sa.hasParam("AILogic")) { if (sa.hasParam("AILogic")) {
String logic = sa.getParam("AILogic"); String logic = sa.getParam("AILogic");
@@ -69,18 +69,8 @@ public class TapAllAi extends SpellAbilityAi {
return false; return false;
} }
final List<Card> human = CardLists.filter(validTappables, new Predicate<Card>() { final List<Card> human = CardLists.filterControlledBy(validTappables, opp);
@Override final List<Card> compy = CardLists.filterControlledBy(validTappables, ai);
public boolean apply(final Card c) {
return c.getController().equals(opp);
}
});
final List<Card> compy = CardLists.filter(validTappables, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.getController().equals(ai);
}
});
if (human.size() <= compy.size()) { if (human.size() <= compy.size()) {
return false; return false;
} }
@@ -102,7 +92,7 @@ public class TapAllAi extends SpellAbilityAi {
final Game game = source.getGame(); final Game game = source.getGame();
CardCollectionView tmpList = game.getCardsIn(ZoneType.Battlefield); CardCollectionView tmpList = game.getCardsIn(ZoneType.Battlefield);
tmpList = CardLists.getValidCards(tmpList, valid, source.getController(), source, sa); tmpList = CardLists.getValidCards(tmpList, valid, source.getController(), source, sa);
tmpList = CardLists.filter(tmpList, Presets.UNTAPPED); tmpList = CardLists.filter(tmpList, CardPredicates.Presets.UNTAPPED);
return tmpList; return tmpList;
} }

View File

@@ -1872,7 +1872,6 @@ public class AbilityUtils {
} }
} }
// Count$DevotionDual.<color name>.<color name> // Count$DevotionDual.<color name>.<color name>
// Count$Devotion.<color name> // Count$Devotion.<color name>
if (sq[0].contains("Devotion")) { if (sq[0].contains("Devotion")) {
@@ -1896,15 +1895,6 @@ public class AbilityUtils {
return doXMath(colorOcurrencices, expr, c, ctb); return doXMath(colorOcurrencices, expr, c, ctb);
} }
if (sq[0].startsWith("DamageDoneByPlayerThisTurn")) {
int sum = 0;
for (Player p : AbilityUtils.getDefinedPlayers(c, sq[1], ctb)) {
sum += c.getReceivedDamageByPlayerThisTurn(p);
}
return doXMath(sum, expr, c, ctb);
}
} // end ctb != null } // end ctb != null
if (sq[0].contains("OppsAtLifeTotal")) { if (sq[0].contains("OppsAtLifeTotal")) {
@@ -1927,9 +1917,6 @@ public class AbilityUtils {
return doXMath(sum, expr, c, ctb); return doXMath(sum, expr, c, ctb);
} }
//return CardFactoryUtil.xCount(c, s2);
//////////////////// ////////////////////
// card info // card info
@@ -1965,7 +1952,7 @@ public class AbilityUtils {
return doXMath(c.getTotalDamageDoneBy(), expr, c, ctb); return doXMath(c.getTotalDamageDoneBy(), expr, c, ctb);
} }
if (sq[0].equals("TotalDamageReceivedThisTurn")) { if (sq[0].equals("TotalDamageReceivedThisTurn")) {
return doXMath(c.getTotalDamageRecievedThisTurn(), expr, c, ctb); return doXMath(c.getTotalDamageReceivedThisTurn(), expr, c, ctb);
} }
if (sq[0].contains("CardPower")) { if (sq[0].contains("CardPower")) {
@@ -2021,9 +2008,6 @@ public class AbilityUtils {
} }
return doXMath(sum, expr, c, ctb); return doXMath(sum, expr, c, ctb);
} }
if (sq[0].equals("DamageDoneThisTurn")) {
return doXMath(c.getDamageDoneThisTurn(), expr, c, ctb);
}
if (sq[0].equals("RegeneratedThisTurn")) { if (sq[0].equals("RegeneratedThisTurn")) {
return doXMath(c.getRegeneratedThisTurn(), expr, c, ctb); return doXMath(c.getRegeneratedThisTurn(), expr, c, ctb);
} }
@@ -2072,7 +2056,6 @@ public class AbilityUtils {
return doXMath(Integer.parseInt(sq[isMyMain ? 1 : 2]), expr, c, ctb); return doXMath(Integer.parseInt(sq[isMyMain ? 1 : 2]), expr, c, ctb);
} }
// Count$AttachedTo <DefinedCards related to spellability> <restriction> // Count$AttachedTo <DefinedCards related to spellability> <restriction>
if (sq[0].startsWith("AttachedTo")) { if (sq[0].startsWith("AttachedTo")) {
final String[] k = l[0].split(" "); final String[] k = l[0].split(" ");
@@ -2138,7 +2121,6 @@ public class AbilityUtils {
return doXMath(maxNum, expr, c, ctb); return doXMath(maxNum, expr, c, ctb);
} }
// Count$EnchantedControllerCreatures // Count$EnchantedControllerCreatures
if (sq[0].equals("EnchantedControllerCreatures")) { // maybe refactor into a Valid with ControlledBy if (sq[0].equals("EnchantedControllerCreatures")) { // maybe refactor into a Valid with ControlledBy
int v = 0; int v = 0;
@@ -2432,7 +2414,6 @@ public class AbilityUtils {
return doXMath(uniqueColors, expr, c, ctb); return doXMath(uniqueColors, expr, c, ctb);
} }
// TODO change into checking SpellAbility // TODO change into checking SpellAbility
if (sq[0].contains("xColorPaid")) { if (sq[0].contains("xColorPaid")) {
String[] attrs = sq[0].split(" "); String[] attrs = sq[0].split(" ");
@@ -2535,7 +2516,6 @@ public class AbilityUtils {
return doXMath(game.getStack().getMaxDistinctSources(), expr, c, ctb); return doXMath(game.getStack().getMaxDistinctSources(), expr, c, ctb);
} }
//Count$Random.<Min>.<Max> //Count$Random.<Min>.<Max>
if (sq[0].equals("Random")) { if (sq[0].equals("Random")) {
int min = AbilityUtils.calculateAmount(c, sq[1], ctb); int min = AbilityUtils.calculateAmount(c, sq[1], ctb);
@@ -2544,7 +2524,6 @@ public class AbilityUtils {
return MyRandom.getRandom().nextInt(1+max-min) + min; return MyRandom.getRandom().nextInt(1+max-min) + min;
} }
// Count$SumPower_valid // Count$SumPower_valid
if (sq[0].startsWith("SumPower")) { if (sq[0].startsWith("SumPower")) {
final String[] restrictions = l[0].split("_"); final String[] restrictions = l[0].split("_");
@@ -2566,9 +2545,6 @@ public class AbilityUtils {
return Aggregates.sum(filteredCards, CardPredicates.Accessors.fnGetCmc); return Aggregates.sum(filteredCards, CardPredicates.Accessors.fnGetCmc);
} }
// Count$TotalCounters.<counterType>_<valid> // Count$TotalCounters.<counterType>_<valid>
if (sq[0].startsWith("TotalCounters")) { if (sq[0].startsWith("TotalCounters")) {
final String[] restrictions = l[0].split("_"); final String[] restrictions = l[0].split("_");
@@ -3360,10 +3336,6 @@ public class AbilityUtils {
return doXMath(player.getAttackersDeclaredThisTurn(), m, source, ctb); return doXMath(player.getAttackersDeclaredThisTurn(), m, source, ctb);
} }
if (value.equals("DamageDoneToPlayerBy")) {
return doXMath(source.getDamageDoneToPlayerBy(player.getName()), m, source, ctb);
}
if (value.contains("DamageToOppsThisTurn")) { if (value.contains("DamageToOppsThisTurn")) {
int oppDmg = 0; int oppDmg = 0;
for (Player opp : player.getOpponents()) { for (Player opp : player.getOpponents()) {

View File

@@ -314,7 +314,6 @@ public class AnimateEffect extends AnimateEffectBase {
sb.append("."); sb.append(".");
} }
return sb.toString(); return sb.toString();
} }

View File

@@ -57,17 +57,9 @@ import forge.util.collect.FCollectionView;
public class ChangeZoneEffect extends SpellAbilityEffect { public class ChangeZoneEffect extends SpellAbilityEffect {
private boolean isHidden(SpellAbility sa) {
boolean hidden = sa.hasParam("Hidden");
if (!hidden && sa.hasParam("Origin")) {
hidden = ZoneType.isHidden(sa.getParam("Origin"));
}
return hidden;
}
@Override @Override
protected String getStackDescription(SpellAbility sa) { protected String getStackDescription(SpellAbility sa) {
if (isHidden(sa)) { if (sa.isHidden()) {
return changeHiddenOriginStackDescription(sa); return changeHiddenOriginStackDescription(sa);
} }
return changeKnownOriginStackDescription(sa); return changeKnownOriginStackDescription(sa);
@@ -424,7 +416,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
return; return;
} }
if (isHidden(sa) && !sa.hasParam("Ninjutsu")) { if (sa.isHidden() && !sa.hasParam("Ninjutsu")) {
changeHiddenOriginResolve(sa); changeHiddenOriginResolve(sa);
} else { } else {
//else if (isKnown(origin) || sa.containsKey("Ninjutsu")) { //else if (isKnown(origin) || sa.containsKey("Ninjutsu")) {

View File

@@ -146,7 +146,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private ZoneType castFrom = null; private ZoneType castFrom = null;
private SpellAbility castSA = null; private SpellAbility castSA = null;
private final CardDamageHistory damageHistory = new CardDamageHistory(); private CardDamageHistory damageHistory = new CardDamageHistory();
// Hidden keywords won't be displayed on the card // Hidden keywords won't be displayed on the card
private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection(); private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection();
@@ -203,13 +203,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private final Set<Object> rememberedObjects = Sets.newLinkedHashSet(); private final Set<Object> rememberedObjects = Sets.newLinkedHashSet();
private Map<Player, String> flipResult; private Map<Player, String> flipResult;
private Map<Card, Integer> receivedDamageFromThisTurn = Maps.newHashMap(); private Map<GameEntity, Integer> receivedDamageFromThisTurn = Maps.newHashMap();
private Map<Player, Integer> receivedDamageFromPlayerThisTurn = Maps.newHashMap();
private Map<Card, Integer> dealtDamageToThisTurn = Maps.newTreeMap();
private Map<String, Integer> dealtDamageToPlayerThisTurn = Maps.newTreeMap();
private final Map<Card, Integer> assignedDamageMap = Maps.newTreeMap(); private final Map<Card, Integer> assignedDamageMap = Maps.newTreeMap();
private boolean hasdealtDamagetoAny = false;
private boolean isCommander = false; private boolean isCommander = false;
private boolean canMoveToCommandZone = false; private boolean canMoveToCommandZone = false;
@@ -272,7 +268,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private Map<Long, Pair<Integer,Integer>> newPT = Maps.newTreeMap(); private Map<Long, Pair<Integer,Integer>> newPT = Maps.newTreeMap();
private Map<Long, Pair<Integer,Integer>> newPTCharacterDefining = Maps.newTreeMap(); private Map<Long, Pair<Integer,Integer>> newPTCharacterDefining = Maps.newTreeMap();
// x=Static Avility id or 0, y=timestamp // x=Static Ability id or 0, y=timestamp
private Table<Integer, Long, Pair<Integer,Integer>> boostPT = TreeBasedTable.create(); private Table<Integer, Long, Pair<Integer,Integer>> boostPT = TreeBasedTable.create();
private String oracleText = ""; private String oracleText = "";
@@ -4967,30 +4963,23 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
usedToPayCost = b; usedToPayCost = b;
} }
// ///////////////////////// public CardDamageHistory getDamageHistory() {
// return damageHistory;
// Damage code }
// public void setDamageHistory(CardDamageHistory history) {
// //////////////////////// damageHistory = history;
}
public final Map<Card, Integer> getReceivedDamageFromThisTurn() { public final Map<GameEntity, Integer> getReceivedDamageFromThisTurn() {
return receivedDamageFromThisTurn; return receivedDamageFromThisTurn;
} }
public final void setReceivedDamageFromThisTurn(final Map<Card, Integer> receivedDamageList) { public final void setReceivedDamageFromThisTurn(final Map<GameEntity, Integer> receivedDamageList) {
receivedDamageFromThisTurn = Maps.newHashMap(receivedDamageList); receivedDamageFromThisTurn = Maps.newHashMap(receivedDamageList);
} }
public final Map<Player, Integer> getReceivedDamageFromPlayerThisTurn() {
return receivedDamageFromPlayerThisTurn;
}
public final void setReceivedDamageFromPlayerThisTurn(final Map<Player, Integer> receivedDamageList) {
receivedDamageFromPlayerThisTurn = Maps.newHashMap(receivedDamageList);
}
public int getReceivedDamageByPlayerThisTurn(final Player p) { public int getReceivedDamageByPlayerThisTurn(final Player p) {
if (receivedDamageFromPlayerThisTurn.containsKey(p)) { if (receivedDamageFromThisTurn.containsKey(p)) {
return receivedDamageFromPlayerThisTurn.get(p); return receivedDamageFromThisTurn.get(p);
} }
return 0; return 0;
} }
@@ -5005,64 +4994,28 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
Player p = c.getController(); Player p = c.getController();
if (p != null) { if (p != null) {
currentDamage = 0; currentDamage = 0;
if (receivedDamageFromPlayerThisTurn.containsKey(p)) { if (receivedDamageFromThisTurn.containsKey(p)) {
currentDamage = receivedDamageFromPlayerThisTurn.get(p); currentDamage = receivedDamageFromThisTurn.get(p);
} }
receivedDamageFromPlayerThisTurn.put(p, damage+currentDamage); receivedDamageFromThisTurn.put(p, damage+currentDamage);
} }
} }
public final void resetReceivedDamageFromThisTurn() { public final void resetReceivedDamageFromThisTurn() {
receivedDamageFromThisTurn.clear(); receivedDamageFromThisTurn.clear();
receivedDamageFromPlayerThisTurn.clear();
} }
public final int getTotalDamageRecievedThisTurn() { public final int getTotalDamageReceivedThisTurn() {
int total = 0; int total = 0;
for (int damage : receivedDamageFromThisTurn.values()) { for (Entry<GameEntity, Integer> e : receivedDamageFromThisTurn.entrySet()) {
total += damage; if (e.getKey() instanceof Player) {
total += e.getValue();
}
} }
return total; return total;
} }
// TODO: Combine getDealtDamageToThisTurn with addDealtDamageToPlayerThisTurn using GameObject, Integer
public final Map<Card, Integer> getDealtDamageToThisTurn() {
return dealtDamageToThisTurn;
}
public final void setDealtDamageToThisTurn(final Map<Card, Integer> dealtDamageList) {
dealtDamageToThisTurn = dealtDamageList;
}
public final void addDealtDamageToThisTurn(final Card c, final int damage) {
int currentDamage = 0;
if (dealtDamageToThisTurn.containsKey(c)) {
currentDamage = dealtDamageToThisTurn.get(c);
}
dealtDamageToThisTurn.put(c, damage+currentDamage);
hasdealtDamagetoAny = true;
}
public final void resetDealtDamageToThisTurn() {
dealtDamageToThisTurn.clear();
}
public final Map<String, Integer> getDealtDamageToPlayerThisTurn() {
return dealtDamageToPlayerThisTurn;
}
public final void setDealtDamageToPlayerThisTurn(final Map<String, Integer> dealtDamageList) {
dealtDamageToPlayerThisTurn = dealtDamageList;
}
public final void addDealtDamageToPlayerThisTurn(final String player, final int damage) {
int currentDamage = 0;
if (dealtDamageToPlayerThisTurn.containsKey(player)) {
currentDamage = dealtDamageToPlayerThisTurn.get(player);
}
dealtDamageToPlayerThisTurn.put(player, damage+currentDamage);
hasdealtDamagetoAny = true;
}
public final void resetDealtDamageToPlayerThisTurn() {
dealtDamageToPlayerThisTurn.clear();
}
public final boolean hasDealtDamageToOpponentThisTurn() { public final boolean hasDealtDamageToOpponentThisTurn() {
for (final GameEntity e : getDamageHistory().getThisTurnDamaged()) { for (final GameEntity e : getDamageHistory().getThisTurnDamaged().keySet()) {
if (e instanceof Player) { if (e instanceof Player) {
final Player p = (Player) e; final Player p = (Player) e;
if (getController().isOpponentOf(p)) { if (getController().isOpponentOf(p)) {
@@ -5073,6 +5026,19 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return false; return false;
} }
/**
* Gets the total damage done by card this turn (after prevention and redirects).
*
* @return the damage done to player p this turn
*/
public final int getTotalDamageDoneBy() {
int sum = 0;
for (final GameEntity e : getDamageHistory().getThisTurnDamaged().keySet()) {
sum += getDamageHistory().getThisTurnDamaged().get(e);
}
return sum;
}
// this is the amount of damage a creature needs to receive before it dies // this is the amount of damage a creature needs to receive before it dies
public final int getLethal() { public final int getLethal() {
if (hasKeyword("Lethal damage dealt to CARDNAME is determined by its power rather than its toughness.")) { if (hasKeyword("Lethal damage dealt to CARDNAME is determined by its power rather than its toughness.")) {
@@ -5234,7 +5200,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
*/ */
@Override @Override
public final int addDamageAfterPrevention(final int damageIn, final Card source, final boolean isCombat, GameEntityCounterTable counterTable) { public final int addDamageAfterPrevention(final int damageIn, final Card source, final boolean isCombat, GameEntityCounterTable counterTable) {
if (damageIn <= 0) { if (damageIn <= 0) {
return 0; // Rule 119.8 return 0; // Rule 119.8
} }
@@ -5252,7 +5217,10 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
getGame().getReplacementHandler().run(ReplacementType.DealtDamage, AbilityKey.mapFromAffected(this)); getGame().getReplacementHandler().run(ReplacementType.DealtDamage, AbilityKey.mapFromAffected(this));
addReceivedDamageFromThisTurn(source, damageIn); addReceivedDamageFromThisTurn(source, damageIn);
source.addDealtDamageToThisTurn(this, damageIn); source.getDamageHistory().registerDamage(this, damageIn);
if (isCombat) {
source.getDamageHistory().registerCombatDamage(this, damageIn);
}
// Run triggers // Run triggers
Map<AbilityKey, Object> runParams = AbilityKey.newMap(); Map<AbilityKey, Object> runParams = AbilityKey.newMap();
@@ -5282,8 +5250,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
subtractCounter(CounterType.get(CounterEnumType.LOYALTY), damageIn); subtractCounter(CounterType.get(CounterEnumType.LOYALTY), damageIn);
} }
if (isCreature()) { if (isCreature()) {
final Game game = source.getGame();
boolean wither = (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.alwaysWither) boolean wither = (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.alwaysWither)
|| source.hasKeyword(Keyword.WITHER) || source.hasKeyword(Keyword.INFECT)); || source.hasKeyword(Keyword.WITHER) || source.hasKeyword(Keyword.INFECT));
@@ -5569,45 +5535,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
public void setMeldedWith(Card meldedWith) { this.meldedWith = meldedWith; } public void setMeldedWith(Card meldedWith) { this.meldedWith = meldedWith; }
public final int getDamageDoneThisTurn() {
int sum = 0;
for (final Card c : dealtDamageToThisTurn.keySet()) {
sum += dealtDamageToThisTurn.get(c);
}
return sum;
}
public final int getDamageDoneToPlayerBy(final String player) {
int sum = 0;
for (final String p : dealtDamageToPlayerThisTurn.keySet()) {
if (p.equals(player)) {
sum += dealtDamageToPlayerThisTurn.get(p);
}
}
return sum;
}
/**
* Gets the total damage done by card this turn (after prevention and redirects).
*
* @return the damage done to player p this turn
*/
public final int getTotalDamageDoneBy() {
int sum = 0;
for (final Card c : dealtDamageToThisTurn.keySet()) {
sum += dealtDamageToThisTurn.get(c);
}
for (final String p : dealtDamageToPlayerThisTurn.keySet()) {
sum += dealtDamageToPlayerThisTurn.get(p);
}
return sum;
}
public boolean getHasdealtDamagetoAny() {
return hasdealtDamagetoAny;
}
public boolean hasProtectionFrom(final Card source) { public boolean hasProtectionFrom(final Card source) {
return hasProtectionFrom(source, false, false); return hasProtectionFrom(source, false, false);
} }
@@ -5997,10 +5924,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
this.castSA = castSA; this.castSA = castSA;
} }
public CardDamageHistory getDamageHistory() {
return damageHistory;
}
public Card getEffectSource() { public Card getEffectSource() {
if (effectSourceAbility != null) { if (effectSourceAbility != null) {
return effectSourceAbility.getHostCard(); return effectSourceAbility.getHostCard();
@@ -6035,19 +5958,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
setDamage(0); setDamage(0);
setHasBeenDealtDeathtouchDamage(false); setHasBeenDealtDeathtouchDamage(false);
resetReceivedDamageFromThisTurn(); resetReceivedDamageFromThisTurn();
resetDealtDamageToThisTurn();
resetDealtDamageToPlayerThisTurn();
getDamageHistory().newTurn();
setRegeneratedThisTurn(0); setRegeneratedThisTurn(0);
resetShield(); resetShield();
setBecameTargetThisTurn(false); setBecameTargetThisTurn(false);
clearMustAttackEntity(turn); clearMustAttackEntity(turn);
clearMustBlockCards(); clearMustBlockCards();
getDamageHistory().newTurn();
getDamageHistory().setCreatureAttackedLastTurnOf(turn, getDamageHistory().getCreatureAttackedThisTurn()); getDamageHistory().setCreatureAttackedLastTurnOf(turn, getDamageHistory().getCreatureAttackedThisTurn());
getDamageHistory().setCreatureAttackedThisTurn(false); getDamageHistory().setCreatureAttackedThisTurn(false);
getDamageHistory().setCreatureAttacksThisTurn(0); getDamageHistory().setCreatureAttacksThisTurn(0);
getDamageHistory().setCreatureBlockedThisTurn(false);
getDamageHistory().setCreatureGotBlockedThisTurn(false);
clearBlockedByThisTurn(); clearBlockedByThisTurn();
clearBlockedThisTurn(); clearBlockedThisTurn();
resetMayPlayTurn(); resetMayPlayTurn();

View File

@@ -2,8 +2,10 @@ package forge.game.card;
import java.util.List; import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.player.Player; import forge.game.player.Player;
@@ -17,9 +19,7 @@ public class CardDamageHistory {
private boolean creatureAttackedThisTurn = false; private boolean creatureAttackedThisTurn = false;
private boolean creatureAttackedThisCombat = false; private boolean creatureAttackedThisCombat = false;
private boolean creatureBlockedThisCombat = false; private boolean creatureBlockedThisCombat = false;
private boolean creatureBlockedThisTurn = false;
private boolean creatureGotBlockedThisCombat = false; private boolean creatureGotBlockedThisCombat = false;
private boolean creatureGotBlockedThisTurn = false;
private int attacksThisTurn = 0; private int attacksThisTurn = 0;
private final List<Player> creatureAttackedLastTurnOf = Lists.newArrayList(); private final List<Player> creatureAttackedLastTurnOf = Lists.newArrayList();
@@ -27,10 +27,15 @@ public class CardDamageHistory {
private final List<Player> NotBlockedSinceLastUpkeepOf = Lists.newArrayList(); private final List<Player> NotBlockedSinceLastUpkeepOf = Lists.newArrayList();
private final List<Player> NotBeenBlockedSinceLastUpkeepOf = Lists.newArrayList(); private final List<Player> NotBeenBlockedSinceLastUpkeepOf = Lists.newArrayList();
private final List<GameEntity> damagedThisCombat = Lists.newArrayList(); private final Map<GameEntity, Integer> damagedThisCombat = Maps.newHashMap();
private final List<GameEntity> damagedThisTurn = Lists.newArrayList(); private final Map<GameEntity, Integer> damagedThisTurn = Maps.newHashMap();
private final List<GameEntity> damagedThisTurnInCombat = Lists.newArrayList(); private final Map<GameEntity, Integer> damagedThisTurnInCombat = Maps.newHashMap();
private final List<GameEntity> damagedThisGame = Lists.newArrayList(); private final Map<GameEntity, Integer> damagedThisGame = Maps.newHashMap();
public final boolean getHasdealtDamagetoAny() {
return !damagedThisGame.isEmpty();
}
// used to see if an attacking creature with a triggering attack ability // used to see if an attacking creature with a triggering attack ability
// triggered this phase: // triggered this phase:
/** /**
@@ -210,9 +215,6 @@ public class CardDamageHistory {
*/ */
public final void setCreatureBlockedThisCombat(final boolean b) { public final void setCreatureBlockedThisCombat(final boolean b) {
this.creatureBlockedThisCombat = b; this.creatureBlockedThisCombat = b;
if (b) {
this.setCreatureBlockedThisTurn(true);
}
} }
/** /**
* <p> * <p>
@@ -224,27 +226,6 @@ public class CardDamageHistory {
public final boolean getCreatureBlockedThisCombat() { public final boolean getCreatureBlockedThisCombat() {
return this.creatureBlockedThisCombat; return this.creatureBlockedThisCombat;
} }
/**
* <p>
* Setter for the field <code>creatureBlockedThisTurn</code>.
* </p>
*
* @param b
* a boolean.
*/
public final void setCreatureBlockedThisTurn(final boolean b) {
this.creatureBlockedThisTurn = b;
}
/**
* <p>
* Getter for the field <code>creatureBlockedThisTurn</code>.
* </p>
*
* @return a boolean.
*/
public final boolean getCreatureBlockedThisTurn() {
return this.creatureBlockedThisTurn;
}
/** /**
* <p> * <p>
* Setter for the field <code>creatureGotBlockedThisCombat</code>. * Setter for the field <code>creatureGotBlockedThisCombat</code>.
@@ -255,9 +236,6 @@ public class CardDamageHistory {
*/ */
public final void setCreatureGotBlockedThisCombat(final boolean b) { public final void setCreatureGotBlockedThisCombat(final boolean b) {
this.creatureGotBlockedThisCombat = b; this.creatureGotBlockedThisCombat = b;
if (b) {
this.setCreatureGotBlockedThisTurn(true);
}
} }
/** /**
* <p> * <p>
@@ -269,50 +247,33 @@ public class CardDamageHistory {
public final boolean getCreatureGotBlockedThisCombat() { public final boolean getCreatureGotBlockedThisCombat() {
return this.creatureGotBlockedThisCombat; return this.creatureGotBlockedThisCombat;
} }
/** public final Map<GameEntity, Integer> getThisCombatDamaged() {
* <p>
* Setter for the field <code>creatureGotBlockedThisTurn</code>.
* </p>
*
* @param b
* a boolean.
*/
public final void setCreatureGotBlockedThisTurn(final boolean b) {
this.creatureGotBlockedThisTurn = b;
}
/**
* <p>
* Getter for the field <code>creatureGotBlockedThisTurn</code>.
* </p>
*
* @return a boolean.
*/
public final boolean getCreatureGotBlockedThisTurn() {
return this.creatureGotBlockedThisTurn;
}
public final List<GameEntity> getThisCombatDamaged() {
return damagedThisCombat; return damagedThisCombat;
} }
public final List<GameEntity> getThisTurnDamaged() { public final Map<GameEntity, Integer> getThisTurnDamaged() {
return damagedThisTurn; return damagedThisTurn;
} }
public final List<GameEntity> getThisTurnCombatDamaged() { public final Map<GameEntity, Integer> getThisTurnCombatDamaged() {
return damagedThisTurnInCombat; return damagedThisTurnInCombat;
} }
public final List<GameEntity> getThisGameDamaged() { public final Map<GameEntity, Integer> getThisGameDamaged() {
return damagedThisGame; return damagedThisGame;
} }
/** /**
* TODO: Write javadoc for this method. * TODO: Write javadoc for this method.
* @param player * @param player
*/ */
public void registerCombatDamage(GameEntity entity) { public void registerCombatDamage(GameEntity entity, int amount) {
if (!damagedThisCombat.contains(entity)) { int old = 0;
damagedThisCombat.add(entity); if (damagedThisCombat.containsKey(entity)) {
old = damagedThisCombat.get(entity);
} }
if (!damagedThisTurnInCombat.contains(entity)) { damagedThisCombat.put(entity, old + amount);
damagedThisTurnInCombat.add(entity); old = 0;
if (damagedThisTurnInCombat.containsKey(entity)) {
old = damagedThisTurnInCombat.get(entity);
} }
damagedThisTurnInCombat.put(entity, old + amount);
} }
/** /**
* TODO: Write javadoc for this method. * TODO: Write javadoc for this method.
@@ -331,13 +292,17 @@ public class CardDamageHistory {
* TODO: Write javadoc for this method. * TODO: Write javadoc for this method.
* @param player * @param player
*/ */
public void registerDamage(GameEntity entity) { public void registerDamage(GameEntity entity, int amount) {
if (!damagedThisTurn.contains(entity)) { int old = 0;
damagedThisTurn.add(entity); if (damagedThisTurn.containsKey(entity)) {
old = damagedThisTurn.get(entity);
} }
if (!damagedThisGame.contains(entity)) { damagedThisTurn.put(entity, old + amount);
damagedThisGame.add(entity); old = 0;
if (damagedThisGame.containsKey(entity)) {
old = damagedThisGame.get(entity);
} }
damagedThisGame.put(entity, old + amount);
} }
} }

View File

@@ -227,6 +227,15 @@ public final class CardPredicates {
}; };
} }
public static final Predicate<Card> restriction(final String restrictions, final Player sourceController, final Card source, final CardTraitBase spellAbility) {
return new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return (c != null) && c.isValid(restrictions, sourceController, source, spellAbility);
}
};
}
public static final Predicate<Card> canBeSacrificedBy(final SpellAbility sa) { public static final Predicate<Card> canBeSacrificedBy(final SpellAbility sa) {
return new Predicate<Card>() { return new Predicate<Card>() {
@Override @Override

View File

@@ -591,14 +591,8 @@ public class CardProperty {
} }
} else { } else {
String prop = property.substring("DamagedBy".length()); String prop = property.substring("DamagedBy".length());
final Iterable<Card> list = Iterables.filter(card.getReceivedDamageFromThisTurn().keySet(), Card.class);
boolean found = false; boolean found = Iterables.any(list, CardPredicates.restriction(prop, sourceController, source, spellAbility));
for (Card d : card.getReceivedDamageFromThisTurn().keySet()) {
if (d.isValid(prop, sourceController, source, spellAbility)) {
found = true;
break;
}
}
if (!found) { if (!found) {
for (Card d : AbilityUtils.getDefinedCards(source, prop, spellAbility)) { for (Card d : AbilityUtils.getDefinedCards(source, prop, spellAbility)) {
@@ -613,7 +607,7 @@ public class CardProperty {
} }
} }
} else if (property.startsWith("Damaged")) { } else if (property.startsWith("Damaged")) {
if (!card.getDealtDamageToThisTurn().containsKey(source)) { if (!card.getDamageHistory().getThisTurnDamaged().containsKey(source)) {
return false; return false;
} }
} else if (property.startsWith("SharesCMCWith")) { } else if (property.startsWith("SharesCMCWith")) {
@@ -1077,7 +1071,7 @@ public class CardProperty {
return false; return false;
} }
} else if (property.startsWith("dealtDamageToYouThisTurn")) { } else if (property.startsWith("dealtDamageToYouThisTurn")) {
if (!card.getDamageHistory().getThisTurnDamaged().contains(sourceController)) { if (!card.getDamageHistory().getThisTurnDamaged().containsKey(sourceController)) {
return false; return false;
} }
} else if (property.startsWith("dealtDamageToOppThisTurn")) { } else if (property.startsWith("dealtDamageToOppThisTurn")) {
@@ -1086,36 +1080,24 @@ public class CardProperty {
} }
} else if (property.startsWith("dealtCombatDamageThisTurn ") || property.startsWith("notDealtCombatDamageThisTurn ")) { } else if (property.startsWith("dealtCombatDamageThisTurn ") || property.startsWith("notDealtCombatDamageThisTurn ")) {
final String v = property.split(" ")[1]; final String v = property.split(" ")[1];
final List<GameEntity> list = card.getDamageHistory().getThisTurnCombatDamaged(); final Iterable<Card> list = Iterables.filter(card.getDamageHistory().getThisTurnCombatDamaged().keySet(), Card.class);
boolean found = false; boolean found = Iterables.any(list, CardPredicates.restriction(v, sourceController, source, spellAbility));
for (final GameEntity e : list) {
if (e.isValid(v, sourceController, source, spellAbility)) {
found = true;
break;
}
}
if (found == property.startsWith("not")) { if (found == property.startsWith("not")) {
return false; return false;
} }
} else if (property.startsWith("dealtCombatDamageThisCombat ") || property.startsWith("notDealtCombatDamageThisCombat ")) { } else if (property.startsWith("dealtCombatDamageThisCombat ") || property.startsWith("notDealtCombatDamageThisCombat ")) {
final String v = property.split(" ")[1]; final String v = property.split(" ")[1];
final List<GameEntity> list = card.getDamageHistory().getThisCombatDamaged(); final Iterable<Card> list = Iterables.filter(card.getDamageHistory().getThisCombatDamaged().keySet(), Card.class);
boolean found = false; boolean found = Iterables.any(list, CardPredicates.restriction(v, sourceController, source, spellAbility));
for (final GameEntity e : list) {
if (e.isValid(v, sourceController, source, spellAbility)) {
found = true;
break;
}
}
if (found == property.startsWith("not")) { if (found == property.startsWith("not")) {
return false; return false;
} }
} else if (property.startsWith("controllerWasDealtCombatDamageByThisTurn")) { } else if (property.startsWith("controllerWasDealtCombatDamageByThisTurn")) {
if (!source.getDamageHistory().getThisTurnCombatDamaged().contains(controller)) { if (!source.getDamageHistory().getThisTurnCombatDamaged().containsKey(controller)) {
return false; return false;
} }
} else if (property.startsWith("controllerWasDealtDamageByThisTurn")) { } else if (property.startsWith("controllerWasDealtDamageByThisTurn")) {
if (!source.getDamageHistory().getThisTurnDamaged().contains(controller)) { if (!source.getDamageHistory().getThisTurnDamaged().containsKey(controller)) {
return false; return false;
} }
} else if (property.startsWith("wasDealtDamageThisTurn")) { } else if (property.startsWith("wasDealtDamageThisTurn")) {
@@ -1127,7 +1109,7 @@ public class CardProperty {
return false; return false;
} }
} else if (property.startsWith("dealtDamagetoAny")) { } else if (property.startsWith("dealtDamagetoAny")) {
return card.getHasdealtDamagetoAny(); return card.getDamageHistory().getHasdealtDamagetoAny();
} else if (property.startsWith("attackedThisTurn")) { } else if (property.startsWith("attackedThisTurn")) {
if (!card.getDamageHistory().getCreatureAttackedThisTurn()) { if (!card.getDamageHistory().getCreatureAttackedThisTurn()) {
return false; return false;
@@ -1135,7 +1117,11 @@ public class CardProperty {
} else if (property.startsWith("attackedLastTurn")) { } else if (property.startsWith("attackedLastTurn")) {
return card.getDamageHistory().getCreatureAttackedLastTurnOf(controller); return card.getDamageHistory().getCreatureAttackedLastTurnOf(controller);
} else if (property.startsWith("blockedThisTurn")) { } else if (property.startsWith("blockedThisTurn")) {
if (!card.getDamageHistory().getCreatureBlockedThisTurn()) { if (card.getBlockedThisTurn().isEmpty()) {
return false;
}
} else if (property.startsWith("notBlockedThisTurn")) {
if (!card.getBlockedThisTurn().isEmpty()) {
return false; return false;
} }
} else if (property.startsWith("notExertedThisTurn")) { } else if (property.startsWith("notExertedThisTurn")) {
@@ -1143,7 +1129,7 @@ public class CardProperty {
return false; return false;
} }
} else if (property.startsWith("gotBlockedThisTurn")) { } else if (property.startsWith("gotBlockedThisTurn")) {
if (!card.getDamageHistory().getCreatureGotBlockedThisTurn()) { if (card.getBlockedByThisTurn().isEmpty()) {
return false; return false;
} }
} else if (property.startsWith("notAttackedThisTurn")) { } else if (property.startsWith("notAttackedThisTurn")) {
@@ -1152,10 +1138,7 @@ public class CardProperty {
} }
} else if (property.startsWith("notAttackedLastTurn")) { } else if (property.startsWith("notAttackedLastTurn")) {
return !card.getDamageHistory().getCreatureAttackedLastTurnOf(controller); return !card.getDamageHistory().getCreatureAttackedLastTurnOf(controller);
} else if (property.startsWith("notBlockedThisTurn")) {
if (card.getDamageHistory().getCreatureBlockedThisTurn()) {
return false;
}
} else if (property.startsWith("greatestPower")) { } else if (property.startsWith("greatestPower")) {
CardCollectionView cards = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.CREATURES); CardCollectionView cards = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.CREATURES);
if (property.contains("ControlledBy")) { if (property.contains("ControlledBy")) {

View File

@@ -252,10 +252,13 @@ public final class CardUtil {
newCopy.setColor(in.determineColor().getColor()); newCopy.setColor(in.determineColor().getColor());
newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn()); newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn());
newCopy.setReceivedDamageFromPlayerThisTurn(in.getReceivedDamageFromPlayerThisTurn()); newCopy.setDamageHistory(in.getDamageHistory());
newCopy.setDealtDamageToThisTurn(in.getDealtDamageToThisTurn()); for (Card c : in.getBlockedThisTurn()) {
newCopy.setDealtDamageToPlayerThisTurn(in.getDealtDamageToPlayerThisTurn()); newCopy.addBlockedThisTurn(c);
newCopy.getDamageHistory().setCreatureGotBlockedThisTurn(in.getDamageHistory().getCreatureGotBlockedThisTurn()); }
for (Card c : in.getBlockedByThisTurn()) {
newCopy.addBlockedByThisTurn(c);
}
newCopy.setAttachedCards(getLKICopyList(in.getAttachedCards(), cachedMap)); newCopy.setAttachedCards(getLKICopyList(in.getAttachedCards(), cachedMap));
newCopy.setEntityAttachedTo(getLKICopy(in.getEntityAttachedTo(), cachedMap)); newCopy.setEntityAttachedTo(getLKICopy(in.getEntityAttachedTo(), cachedMap));
@@ -265,12 +268,8 @@ public final class CardUtil {
for (final Card haunter : in.getHauntedBy()) { for (final Card haunter : in.getHauntedBy()) {
newCopy.addHauntedBy(haunter, false); newCopy.addHauntedBy(haunter, false);
} }
for (final Object o : in.getRemembered()) { newCopy.addRemembered(in.getRemembered());
newCopy.addRemembered(o); newCopy.addImprintedCards(in.getImprintedCards());
}
for (final Card o : in.getImprintedCards()) {
newCopy.addImprintedCard(o);
}
for(Table.Cell<Player, CounterType, Integer> cl : in.getEtbCounters()) { for(Table.Cell<Player, CounterType, Integer> cl : in.getEtbCounters()) {
newCopy.addEtbCounter(cl.getColumnKey(), cl.getValue(), cl.getRowKey()); newCopy.addEtbCounter(cl.getColumnKey(), cl.getValue(), cl.getRowKey());

View File

@@ -665,8 +665,7 @@ public class PhaseHandler implements java.io.Serializable {
return; return;
} }
// Handles removing cards like Mogg Flunkies from combat if group block // Handles removing cards like Mogg Flunkies from combat if group block didn't occur
// didn't occur
for (Card blocker : CardLists.filterControlledBy(combat.getAllBlockers(), p)) { for (Card blocker : CardLists.filterControlledBy(combat.getAllBlockers(), p)) {
final List<Card> attackers = Lists.newArrayList(combat.getAttackersBlockedBy(blocker)); final List<Card> attackers = Lists.newArrayList(combat.getAttackersBlockedBy(blocker));
for (Card attacker : attackers) { for (Card attacker : attackers) {

View File

@@ -640,7 +640,6 @@ public class Player extends GameEntity implements Comparable<Player> {
return 0; return 0;
} }
//String additionalLog = ""; //String additionalLog = "";
source.addDealtDamageToPlayerThisTurn(getName(), amount);
boolean infect = source.hasKeyword(Keyword.INFECT) boolean infect = source.hasKeyword(Keyword.INFECT)
|| hasKeyword("All damage is dealt to you as though its source had infect."); || hasKeyword("All damage is dealt to you as though its source had infect.");
@@ -680,7 +679,7 @@ public class Player extends GameEntity implements Comparable<Player> {
int old = assignedDamage.containsKey(source) ? assignedDamage.get(source) : 0; int old = assignedDamage.containsKey(source) ? assignedDamage.get(source) : 0;
assignedDamage.put(source, old + amount); assignedDamage.put(source, old + amount);
source.getDamageHistory().registerDamage(this); source.getDamageHistory().registerDamage(this, amount);
if (isCombat) { if (isCombat) {
old = assignedCombatDamage.containsKey(source) ? assignedCombatDamage.get(source) : 0; old = assignedCombatDamage.containsKey(source) ? assignedCombatDamage.get(source) : 0;
@@ -688,6 +687,7 @@ public class Player extends GameEntity implements Comparable<Player> {
for (final String type : source.getType().getCreatureTypes()) { for (final String type : source.getType().getCreatureTypes()) {
source.getController().addProwlType(type); source.getController().addProwlType(type);
} }
source.getDamageHistory().registerCombatDamage(this, amount);
} }
// Run triggers // Run triggers

View File

@@ -96,7 +96,7 @@ public class PlayerProperty {
final List<Card> cards = AbilityUtils.getDefinedCards(source, v, spellAbility); final List<Card> cards = AbilityUtils.getDefinedCards(source, v, spellAbility);
int found = 0; int found = 0;
for (final Card card : cards) { for (final Card card : cards) {
if (card.getDamageHistory().getThisCombatDamaged().contains(player)) { if (card.getDamageHistory().getThisCombatDamaged().containsKey(player)) {
found++; found++;
} }
} }
@@ -115,7 +115,7 @@ public class PlayerProperty {
final List<Card> cards = AbilityUtils.getDefinedCards(source, v, spellAbility); final List<Card> cards = AbilityUtils.getDefinedCards(source, v, spellAbility);
int found = 0; int found = 0;
for (final Card card : cards) { for (final Card card : cards) {
if (card.getDamageHistory().getThisGameDamaged().contains(player)) { if (card.getDamageHistory().getThisGameDamaged().containsKey(player)) {
found++; found++;
} }
} }
@@ -134,7 +134,7 @@ public class PlayerProperty {
final List<Card> cards = AbilityUtils.getDefinedCards(source, v, spellAbility); final List<Card> cards = AbilityUtils.getDefinedCards(source, v, spellAbility);
int found = 0; int found = 0;
for (final Card card : cards) { for (final Card card : cards) {
if (card.getDamageHistory().getThisTurnDamaged().contains(player)) { if (card.getDamageHistory().getThisTurnDamaged().containsKey(player)) {
found++; found++;
} }
} }
@@ -154,7 +154,7 @@ public class PlayerProperty {
int found = 0; int found = 0;
for (final Card card : cards) { for (final Card card : cards) {
if (card.getDamageHistory().getThisTurnCombatDamaged().contains(player)) { if (card.getDamageHistory().getThisTurnCombatDamaged().containsKey(player)) {
found++; found++;
} }
} }

View File

@@ -32,7 +32,6 @@ public class PlayerStatistics {
private int turnsPlayed = 0; private int turnsPlayed = 0;
private PlayerOutcome outcome; private PlayerOutcome outcome;
/** /**

View File

@@ -2378,4 +2378,12 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
} }
rollbackEffects.clear(); rollbackEffects.clear();
} }
public boolean isHidden() {
boolean hidden = hasParam("Hidden");
if (!hidden && hasParam("Origin")) {
hidden = ZoneType.isHidden(getParam("Origin"));
}
return hidden;
}
} }

View File

@@ -160,7 +160,7 @@ public class TriggerChangesZone extends Trigger {
// need to check the ChangeZone LKI copy for damage, otherwise it'll return 0 for a new object in the new zone // need to check the ChangeZone LKI copy for damage, otherwise it'll return 0 for a new object in the new zone
Card lkiCard = card.getGame().getChangeZoneLKIInfo(card); Card lkiCard = card.getGame().getChangeZoneLKIInfo(card);
final boolean expr = Expressions.compare(lkiCard.getTotalDamageRecievedThisTurn(), cond, rightSide); final boolean expr = Expressions.compare(lkiCard.getTotalDamageReceivedThisTurn(), cond, rightSide);
if (!expr) { if (!expr) {
return false; return false;
} }

View File

@@ -23,6 +23,7 @@ Type=Promos
49 R Curator of Mysteries 49 R Curator of Mysteries
100 R Etali, Primal Storm 100 R Etali, Primal Storm
123 R Beast Whisperer 123 R Beast Whisperer
133 R Opportunistic Dragon
140 R Neheb, Dreadhorde Champion 140 R Neheb, Dreadhorde Champion
141 R Goblin Chieftain 141 R Goblin Chieftain
147 R Bristling Hydra 147 R Bristling Hydra

View File

@@ -277,28 +277,23 @@ public final class FModel {
} }
} }
allCardsNoAlt = ItemPool.createFrom(Iterables.concat(getMagicDb().getCommonCards().getAllCardsNoAlt(), getMagicDb().getCustomCards().getAllCardsNoAlt()), PaperCard.class); if (GuiBase.getInterface().isLibgdxPort() && GuiBase.getDeviceRAM() < 5000)
archenemyCards = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(Predicates.compose(CardRulesPredicates.Presets.IS_SCHEME, PaperCard.FN_GET_RULES)), PaperCard.class); return; // don't preload ItemPool on mobile port with less than 5GB RAM
planechaseCards = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(Predicates.compose(CardRulesPredicates.Presets.IS_PLANE_OR_PHENOMENON, PaperCard.FN_GET_RULES)), PaperCard.class);
//common ItemPool to preload
allCardsNoAlt = getAllCardsNoAlt();
archenemyCards = getArchenemyCards();
planechaseCards = getPlanechaseCards();
if (GuiBase.getInterface().isLibgdxPort()) { if (GuiBase.getInterface().isLibgdxPort()) {
//preload mobile Itempool //preload mobile Itempool
uniqueCardsNoAlt = ItemPool.createFrom(Iterables.concat(getMagicDb().getCommonCards().getUniqueCardsNoAlt(), getMagicDb().getCustomCards().getUniqueCardsNoAlt()), PaperCard.class); uniqueCardsNoAlt = getUniqueCardsNoAlt();
} else { } else {
//preload Desktop Itempool //preload Desktop Itempool
commanderPool = ItemPool.createFrom(Iterables.concat( commanderPool = getCommanderPool();
getMagicDb().getCommonCards().getAllCardsNoAlt(Predicates.compose(CardRulesPredicates.Presets.CAN_BE_COMMANDER, PaperCard.FN_GET_RULES)), brawlCommander = getBrawlCommander();
getMagicDb().getCustomCards().getAllCardsNoAlt(Predicates.compose(CardRulesPredicates.Presets.CAN_BE_COMMANDER, PaperCard.FN_GET_RULES))), PaperCard.class); tinyLeadersCommander = getTinyLeadersCommander();
brawlCommander = ItemPool.createFrom(Iterables.concat(getMagicDb().getCommonCards().getAllCardsNoAlt(Predicates.and( avatarPool = getAvatarPool();
FModel.getFormats().get("Brawl").getFilterPrinted(), Predicates.compose(CardRulesPredicates.Presets.CAN_BE_BRAWL_COMMANDER, PaperCard.FN_GET_RULES))), getMagicDb().getCustomCards().getAllCardsNoAlt(Predicates.and( conspiracyPool = getConspiracyPool();
FModel.getFormats().get("Brawl").getFilterPrinted(), Predicates.compose(CardRulesPredicates.Presets.CAN_BE_BRAWL_COMMANDER, PaperCard.FN_GET_RULES)))), PaperCard.class);
oathbreakerCommander = ItemPool.createFrom(Iterables.concat(
getMagicDb().getCommonCards().getAllCardsNoAlt(Predicates.compose(Predicates.or(CardRulesPredicates.Presets.CAN_BE_OATHBREAKER, CardRulesPredicates.Presets.CAN_BE_SIGNATURE_SPELL), PaperCard.FN_GET_RULES)),
getMagicDb().getCustomCards().getAllCardsNoAlt(Predicates.compose(Predicates.or(CardRulesPredicates.Presets.CAN_BE_OATHBREAKER, CardRulesPredicates.Presets.CAN_BE_SIGNATURE_SPELL), PaperCard.FN_GET_RULES))), PaperCard.class);
tinyLeadersCommander = ItemPool.createFrom(Iterables.concat(
getMagicDb().getCommonCards().getAllCardsNoAlt(Predicates.compose(CardRulesPredicates.Presets.CAN_BE_TINY_LEADERS_COMMANDER, PaperCard.FN_GET_RULES)),
getMagicDb().getCustomCards().getAllCardsNoAlt(Predicates.compose(CardRulesPredicates.Presets.CAN_BE_TINY_LEADERS_COMMANDER, PaperCard.FN_GET_RULES))), PaperCard.class);
avatarPool = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(Predicates.compose(CardRulesPredicates.Presets.IS_VANGUARD, PaperCard.FN_GET_RULES)), PaperCard.class);
conspiracyPool = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(Predicates.compose(CardRulesPredicates.Presets.IS_CONSPIRACY, PaperCard.FN_GET_RULES)), PaperCard.class);
} }
} }
@@ -317,42 +312,70 @@ public final class FModel {
} }
public static ItemPool<PaperCard> getUniqueCardsNoAlt() { public static ItemPool<PaperCard> getUniqueCardsNoAlt() {
if (uniqueCardsNoAlt == null)
return ItemPool.createFrom(Iterables.concat(getMagicDb().getCommonCards().getUniqueCardsNoAlt(), getMagicDb().getCustomCards().getUniqueCardsNoAlt()), PaperCard.class);
return uniqueCardsNoAlt; return uniqueCardsNoAlt;
} }
public static ItemPool<PaperCard> getAllCardsNoAlt() { public static ItemPool<PaperCard> getAllCardsNoAlt() {
if (allCardsNoAlt == null)
return ItemPool.createFrom(Iterables.concat(getMagicDb().getCommonCards().getAllCardsNoAlt(), getMagicDb().getCustomCards().getAllCardsNoAlt()), PaperCard.class);
return allCardsNoAlt; return allCardsNoAlt;
} }
public static ItemPool<PaperCard> getArchenemyCards() { public static ItemPool<PaperCard> getArchenemyCards() {
if (archenemyCards == null)
return ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(Predicates.compose(CardRulesPredicates.Presets.IS_SCHEME, PaperCard.FN_GET_RULES)), PaperCard.class);
return archenemyCards; return archenemyCards;
} }
public static ItemPool<PaperCard> getPlanechaseCards() { public static ItemPool<PaperCard> getPlanechaseCards() {
if (planechaseCards == null)
return ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(Predicates.compose(CardRulesPredicates.Presets.IS_PLANE_OR_PHENOMENON, PaperCard.FN_GET_RULES)), PaperCard.class);
return planechaseCards; return planechaseCards;
} }
public static ItemPool<PaperCard> getBrawlCommander() { public static ItemPool<PaperCard> getBrawlCommander() {
if (brawlCommander == null)
return ItemPool.createFrom(Iterables.concat(getMagicDb().getCommonCards().getAllCardsNoAlt(Predicates.and(
FModel.getFormats().get("Brawl").getFilterPrinted(), Predicates.compose(CardRulesPredicates.Presets.CAN_BE_BRAWL_COMMANDER, PaperCard.FN_GET_RULES))), getMagicDb().getCustomCards().getAllCardsNoAlt(Predicates.and(
FModel.getFormats().get("Brawl").getFilterPrinted(), Predicates.compose(CardRulesPredicates.Presets.CAN_BE_BRAWL_COMMANDER, PaperCard.FN_GET_RULES)))), PaperCard.class);
return brawlCommander; return brawlCommander;
} }
public static ItemPool<PaperCard> getOathbreakerCommander() { public static ItemPool<PaperCard> getOathbreakerCommander() {
if (oathbreakerCommander == null)
return ItemPool.createFrom(Iterables.concat(
getMagicDb().getCommonCards().getAllCardsNoAlt(Predicates.compose(Predicates.or(CardRulesPredicates.Presets.CAN_BE_OATHBREAKER, CardRulesPredicates.Presets.CAN_BE_SIGNATURE_SPELL), PaperCard.FN_GET_RULES)),
getMagicDb().getCustomCards().getAllCardsNoAlt(Predicates.compose(Predicates.or(CardRulesPredicates.Presets.CAN_BE_OATHBREAKER, CardRulesPredicates.Presets.CAN_BE_SIGNATURE_SPELL), PaperCard.FN_GET_RULES))), PaperCard.class);
return oathbreakerCommander; return oathbreakerCommander;
} }
public static ItemPool<PaperCard> getTinyLeadersCommander() { public static ItemPool<PaperCard> getTinyLeadersCommander() {
if (tinyLeadersCommander == null)
return ItemPool.createFrom(Iterables.concat(
getMagicDb().getCommonCards().getAllCardsNoAlt(Predicates.compose(CardRulesPredicates.Presets.CAN_BE_TINY_LEADERS_COMMANDER, PaperCard.FN_GET_RULES)),
getMagicDb().getCustomCards().getAllCardsNoAlt(Predicates.compose(CardRulesPredicates.Presets.CAN_BE_TINY_LEADERS_COMMANDER, PaperCard.FN_GET_RULES))), PaperCard.class);
return tinyLeadersCommander; return tinyLeadersCommander;
} }
public static ItemPool<PaperCard> getCommanderPool() { public static ItemPool<PaperCard> getCommanderPool() {
if (commanderPool == null)
return ItemPool.createFrom(Iterables.concat(
getMagicDb().getCommonCards().getAllCardsNoAlt(Predicates.compose(CardRulesPredicates.Presets.CAN_BE_COMMANDER, PaperCard.FN_GET_RULES)),
getMagicDb().getCustomCards().getAllCardsNoAlt(Predicates.compose(CardRulesPredicates.Presets.CAN_BE_COMMANDER, PaperCard.FN_GET_RULES))), PaperCard.class);
return commanderPool; return commanderPool;
} }
public static ItemPool<PaperCard> getAvatarPool() { public static ItemPool<PaperCard> getAvatarPool() {
if (avatarPool == null)
return ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(Predicates.compose(CardRulesPredicates.Presets.IS_VANGUARD, PaperCard.FN_GET_RULES)), PaperCard.class);
return avatarPool; return avatarPool;
} }
public static ItemPool<PaperCard> getConspiracyPool() { public static ItemPool<PaperCard> getConspiracyPool() {
if (conspiracyPool == null)
return ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(Predicates.compose(CardRulesPredicates.Presets.IS_CONSPIRACY, PaperCard.FN_GET_RULES)), PaperCard.class);
return conspiracyPool; return conspiracyPool;
} }