mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +00:00
Merge branch 'fix' into 'master'
Simulation: fix for Pack Rat tokens (bad diff because of missing CMC) See merge request core-developers/forge!5980
This commit is contained in:
@@ -514,9 +514,8 @@ public class AiAttackController {
|
||||
if (Iterables.any(oppBattlefield, Predicates.and(CardPredicates.Presets.UNTAPPED, CardPredicates.Presets.LANDS))) {
|
||||
maxBlockersAfterCrew = Integer.MAX_VALUE;
|
||||
break;
|
||||
} else {
|
||||
maxBlockersAfterCrew--;
|
||||
}
|
||||
maxBlockersAfterCrew--;
|
||||
} else if (cardType.hasSubtype("Vehicle") && !cardType.isCreature()) {
|
||||
maxBlockersAfterCrew--;
|
||||
}
|
||||
|
||||
@@ -2436,7 +2436,7 @@ public class ComputerUtil {
|
||||
CardCollection cardsInPlay = CardLists.getNotType(game.getCardsIn(ZoneType.Battlefield), "Land");
|
||||
CardCollection humanlist = CardLists.filterControlledBy(cardsInPlay, ai.getOpponents());
|
||||
CardCollection computerlist = ai.getCreaturesInPlay();
|
||||
return (ComputerUtilCard.evaluatePermanentList(computerlist) + 3) < ComputerUtilCard.evaluatePermanentList(humanlist) ? "Carnage" : "Homage";
|
||||
return ComputerUtilCard.evaluatePermanentList(computerlist) + 3 < ComputerUtilCard.evaluatePermanentList(humanlist) ? "Carnage" : "Homage";
|
||||
case "Judgment":
|
||||
if (votes.isEmpty()) {
|
||||
CardCollection list = new CardCollection();
|
||||
@@ -2446,9 +2446,8 @@ public class ComputerUtil {
|
||||
}
|
||||
}
|
||||
return ComputerUtilCard.getBestAI(list);
|
||||
} else {
|
||||
return Iterables.getFirst(votes.keySet(), null);
|
||||
}
|
||||
return Iterables.getFirst(votes.keySet(), null);
|
||||
case "Protection":
|
||||
if (votes.isEmpty()) {
|
||||
List<String> restrictedToColors = Lists.newArrayList();
|
||||
@@ -2459,9 +2458,8 @@ public class ComputerUtil {
|
||||
}
|
||||
CardCollection lists = CardLists.filterControlledBy(game.getCardsInGame(), ai.getOpponents());
|
||||
return StringUtils.capitalize(ComputerUtilCard.getMostProminentColor(lists, restrictedToColors));
|
||||
} else {
|
||||
return Iterables.getFirst(votes.keySet(), null);
|
||||
}
|
||||
return Iterables.getFirst(votes.keySet(), null);
|
||||
case "FeatherOrQuill":
|
||||
// try to mill opponent with Quill vote
|
||||
if (opponent && !controller.cantLose()) {
|
||||
|
||||
@@ -2292,9 +2292,8 @@ public class ComputerUtilCombat {
|
||||
}
|
||||
if (!withoutAbilities) {
|
||||
return canGainKeyword(combatant, Lists.newArrayList(keyword), combat);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final static boolean canGainKeyword(final Card combatant, final List<String> keywords, final Combat combat) {
|
||||
|
||||
@@ -306,7 +306,6 @@ public class ComputerUtilMana {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (saHost != null) {
|
||||
if (ma.getPayCosts().hasTapCost() && AiCardMemory.isRememberedCard(ai, ma.getHostCard(), MemorySet.PAYS_TAP_COST)) {
|
||||
continue;
|
||||
}
|
||||
@@ -353,7 +352,6 @@ public class ComputerUtilMana {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpellAbility paymentChoice = ma;
|
||||
|
||||
|
||||
@@ -1023,9 +1023,8 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
}
|
||||
if (blink) {
|
||||
return c.isToken();
|
||||
} else {
|
||||
return c.isToken() || c.getCMC() > 0;
|
||||
}
|
||||
return c.isToken() || c.getCMC() > 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -315,7 +315,6 @@ public class ControlGainAi extends SpellAbilityAi {
|
||||
} else {
|
||||
return this.canPlayAI(ai, sa);
|
||||
}
|
||||
|
||||
} // pumpDrawbackAI()
|
||||
|
||||
@Override
|
||||
|
||||
@@ -153,12 +153,11 @@ public abstract class DamageAiBase extends SpellAbilityAi {
|
||||
}
|
||||
if (value < 0.2f) { //hard floor to reduce ridiculous odds for instants over time
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
final float chance = MyRandom.getRandom().nextFloat();
|
||||
return chance < value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -811,9 +811,8 @@ public class DamageDealAi extends DamageAiBase {
|
||||
if (!c.hasKeyword(Keyword.INDESTRUCTIBLE) && ComputerUtilCombat.getDamageToKill(c, false) <= restDamage) {
|
||||
if (c.getController().equals(ai)) {
|
||||
return false;
|
||||
} else {
|
||||
urgent = true;
|
||||
}
|
||||
urgent = true;
|
||||
}
|
||||
if (c.getController().isOpponentOf(ai) ^ c.getName().equals("Stuffy Doll")) {
|
||||
positive = true;
|
||||
|
||||
@@ -198,7 +198,7 @@ public class EffectAi extends SpellAbilityAi {
|
||||
final Card host = saTop.getHostCard();
|
||||
if (saTop.getActivatingPlayer() != ai // from opponent
|
||||
&& host.canDamagePrevented(false) // no prevent damage
|
||||
&& host != null && (host.isInstant() || host.isSorcery())
|
||||
&& (host.isInstant() || host.isSorcery())
|
||||
&& !host.hasKeyword("Prevent all damage that would be dealt by CARDNAME.")) { // valid target
|
||||
final ApiType type = saTop.getApi();
|
||||
if (type == ApiType.DealDamage || type == ApiType.DamageAll) { // burn spell
|
||||
|
||||
@@ -287,12 +287,11 @@ public class FightAi extends SpellAbilityAi {
|
||||
if (canKill(fighter, opponent, pumpAttack)) {
|
||||
if (!canKill(opponent, fighter, -pumpDefense)) { // can survive
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
if (MyRandom.getRandom().nextInt(20) < (opponent.getCMC() - fighter.getCMC())) { // trade
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,6 +233,10 @@ public class GameCopier {
|
||||
if (card.isPaired()) {
|
||||
otherCard.setPairedWith(cardMap.get(card.getPairedWith()));
|
||||
}
|
||||
if (card.getCopiedPermanent() != null) {
|
||||
// TODO would it be safe to simply reuse the prototype?
|
||||
otherCard.setCopiedPermanent(CardFactory.copyCard(card.getCopiedPermanent(), false));
|
||||
}
|
||||
// TODO: Verify that the above relationships are preserved bi-directionally or not.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -547,9 +547,8 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView,
|
||||
public String getSVar(final String name) {
|
||||
if (sVars.containsKey(name)) {
|
||||
return sVars.get(name);
|
||||
} else {
|
||||
return getSVarFallback().getSVar(name);
|
||||
}
|
||||
return getSVarFallback().getSVar(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1422,7 +1422,7 @@ public class AbilityUtils {
|
||||
|
||||
// do blessing there before condition checks
|
||||
if (sa.isSpell() && sa.isBlessing() && !sa.getHostCard().isPermanent()) {
|
||||
if (pl != null && pl.getZone(ZoneType.Battlefield).size() >= 10) {
|
||||
if (pl.getZone(ZoneType.Battlefield).size() >= 10) {
|
||||
pl.setBlessing(true);
|
||||
}
|
||||
}
|
||||
@@ -1871,9 +1871,8 @@ public class AbilityUtils {
|
||||
list = CardLists.getValidCards(list, k[1].split(","), sa.getActivatingPlayer(), c, sa);
|
||||
if (k[0].contains("TotalToughness")) {
|
||||
return doXMath(Aggregates.sum(list, CardPredicates.Accessors.fnGetNetToughness), expr, c, ctb);
|
||||
} else {
|
||||
return doXMath(list.size(), expr, c, ctb);
|
||||
}
|
||||
return doXMath(list.size(), expr, c, ctb);
|
||||
}
|
||||
|
||||
if (sq[0].startsWith("LastStateGraveyard")) {
|
||||
@@ -3208,9 +3207,8 @@ public class AbilityUtils {
|
||||
} else if (s[0].contains("DivideEvenlyDown")) {
|
||||
if (secondaryNum == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return num / secondaryNum;
|
||||
}
|
||||
return num / secondaryNum;
|
||||
} else if (s[0].contains("Mod")) {
|
||||
return num % secondaryNum;
|
||||
} else if (s[0].contains("Abs")) {
|
||||
@@ -3218,15 +3216,13 @@ public class AbilityUtils {
|
||||
} else if (s[0].contains("LimitMax")) {
|
||||
if (num < secondaryNum) {
|
||||
return num;
|
||||
} else {
|
||||
return secondaryNum;
|
||||
}
|
||||
return secondaryNum;
|
||||
} else if (s[0].contains("LimitMin")) {
|
||||
if (num > secondaryNum) {
|
||||
return num;
|
||||
} else {
|
||||
return secondaryNum;
|
||||
}
|
||||
return secondaryNum;
|
||||
|
||||
} else {
|
||||
return num;
|
||||
|
||||
@@ -3037,7 +3037,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
return tokenCard;
|
||||
}
|
||||
public final void setTokenCard(boolean tokenC) {
|
||||
if (tokenCard = tokenC) { return; }
|
||||
if (tokenCard == tokenC) { return; }
|
||||
tokenCard = tokenC;
|
||||
view.updateTokenCard(this);
|
||||
}
|
||||
@@ -5232,9 +5232,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
// this is the amount of damage a creature needs to receive before it dies
|
||||
public final int getLethal() {
|
||||
if (hasKeyword("Lethal damage dealt to CARDNAME is determined by its power rather than its toughness.")) {
|
||||
return getNetPower(); }
|
||||
else {
|
||||
return getNetToughness(); }
|
||||
return getNetPower();
|
||||
}
|
||||
return getNetToughness();
|
||||
}
|
||||
|
||||
// this is the minimal damage a trampling creature has to assign to a blocker
|
||||
|
||||
@@ -185,7 +185,6 @@ public class TokenInfo {
|
||||
}
|
||||
}
|
||||
if (!typeMap.isEmpty()) {
|
||||
|
||||
CardType type = new CardType(result.getType());
|
||||
final boolean nameGenerated = result.getName().endsWith(" Token");
|
||||
boolean typeChanged = false;
|
||||
|
||||
@@ -135,8 +135,7 @@ public class CostDiscard extends CostPartWithList {
|
||||
if (this.payCostFromSource()) {
|
||||
return source.canBeDiscardedBy(ability, effect);
|
||||
}
|
||||
else {
|
||||
if (type.equals("Hand")) {
|
||||
else if (type.equals("Hand")) {
|
||||
// trying to discard an empty hand always work even with Tamiyo
|
||||
if (payer.getZone(ZoneType.Hand).isEmpty()) {
|
||||
return true;
|
||||
@@ -186,7 +185,6 @@ public class CostDiscard extends CostPartWithList {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -148,14 +148,13 @@ public class CostPartMana extends CostPart {
|
||||
int timesToPay = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getSVar("NumTimes"), sa);
|
||||
if (timesToPay == 0) {
|
||||
return null;
|
||||
} else {
|
||||
}
|
||||
ManaCostBeingPaid totalMana = new ManaCostBeingPaid(getManaToPay());
|
||||
for (int i = 1; i < timesToPay; i++) {
|
||||
totalMana.addManaCost(getManaToPay());
|
||||
}
|
||||
return totalMana.toManaCost();
|
||||
}
|
||||
}
|
||||
return getManaToPay();
|
||||
}
|
||||
|
||||
|
||||
@@ -434,8 +434,8 @@ public class ReplacementHandler {
|
||||
private void getPossibleReplaceDamageList(PlayerCollection players, final boolean isCombat, final CardDamageMap damageMap, final SpellAbility cause) {
|
||||
for (Map.Entry<GameEntity, Map<Card, Integer>> et : damageMap.columnMap().entrySet()) {
|
||||
final GameEntity target = et.getKey();
|
||||
int playerIndex = (target instanceof Player ? players.indexOf(((Player) target)) :
|
||||
players.indexOf(((Card) target).getController()));
|
||||
int playerIndex = target instanceof Player ? players.indexOf(((Player) target)) :
|
||||
players.indexOf(((Card) target).getController());
|
||||
if (playerIndex == -1) continue;
|
||||
Map<ReplacementEffect, List<Map<AbilityKey, Object>>> replaceCandidateMap = replaceDamageList.get(playerIndex);
|
||||
for (Map.Entry<Card, Integer> e : et.getValue().entrySet()) {
|
||||
@@ -501,8 +501,8 @@ public class ReplacementHandler {
|
||||
Map<ReplacementEffect, List<Map<AbilityKey, Object>>> newReplaceCandidateMap = replaceCandidateMap;
|
||||
if (!target.equals(newTarget)) {
|
||||
PlayerCollection players = game.getPlayersInTurnOrder();
|
||||
int playerIndex = (newTarget instanceof Player ? players.indexOf(((Player) newTarget)) :
|
||||
players.indexOf(((Card) newTarget).getController()));
|
||||
int playerIndex = newTarget instanceof Player ? players.indexOf(((Player) newTarget)) :
|
||||
players.indexOf(((Card) newTarget).getController());
|
||||
newReplaceCandidateMap = replaceDamageList.get(playerIndex);
|
||||
}
|
||||
|
||||
|
||||
@@ -386,9 +386,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")) {
|
||||
return InputConfirm.confirm(this, CardView.get(attacker),
|
||||
localizer.getMessage("lblAssignCombatDamageWerentBlocked"));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user