diff --git a/forge-ai/src/main/java/forge/ai/AiProps.java b/forge-ai/src/main/java/forge/ai/AiProps.java index 9fbc1f6ab7c..696066440c2 100644 --- a/forge-ai/src/main/java/forge/ai/AiProps.java +++ b/forge-ai/src/main/java/forge/ai/AiProps.java @@ -43,6 +43,7 @@ public enum AiProps { /** */ ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS (""), /** */ ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS ("false"), /** */ PRIORITY_REDUCTION_FOR_STORM_SPELLS ("0"), /** */ + USE_BERSERK_AGGRESSIVELY ("false"), /** */ MIN_COUNT_FOR_STORM_SPELLS ("0"); /** */ private final String strDefaultVal; diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 322544b9a2c..59533f0bad8 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -1087,6 +1087,7 @@ public class ComputerUtilCard { final Game game = ai.getGame(); final PhaseHandler phase = game.getPhaseHandler(); final Combat combat = phase.getCombat(); + final boolean isBerserk = "Berserk".equals(sa.getParam("AILogic")); if (!c.canBeTargetedBy(sa)) { return false; @@ -1173,6 +1174,9 @@ public class ComputerUtilCard { List opposing = null; boolean pumpedWillDie = false; final boolean isAttacking = combat.isAttacking(c); + + if (isBerserk && isAttacking) { pumpedWillDie = true; } + if (isAttacking) { pumpedCombat.addAttacker(pumped, opp); opposing = combat.getBlockers(c); @@ -1302,6 +1306,17 @@ public class ComputerUtilCard { } } } + + if (isBerserk) { + // if we got here, Berserk will result in the pumped creature dying at EOT and the opponent will not lose + if (ai.getController() instanceof PlayerControllerAi) { + boolean aggr = ((PlayerControllerAi)ai.getController()).getAi().getBooleanProperty(AiProps.USE_BERSERK_AGGRESSIVELY); + if (!aggr) { + return false; + } + } + } + return MyRandom.getRandom().nextFloat() < chance; } @@ -1329,8 +1344,12 @@ public class ComputerUtilCard { kws.add(kw); } } + + final boolean isBerserk = "Berserk".equals(sa.getParam("AILogic")); + final int berserkPower = isBerserk ? c.getCurrentPower() : 0; + pumped.addNewPT(c.getCurrentPower(), c.getCurrentToughness(), timestamp); - pumped.addTempPowerBoost(c.getTempPowerBoost() + power); + pumped.addTempPowerBoost(c.getTempPowerBoost() + power + berserkPower); pumped.addTempToughnessBoost(c.getTempToughnessBoost() + toughness); pumped.addChangedCardKeywords(kws, new ArrayList(), false, timestamp); Set types = c.getCounters().keySet(); diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java index ce0ed8fb8ba..8876d89f153 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java @@ -1308,7 +1308,7 @@ public class ComputerUtilMana { * @param shardColor * a mana shard to specifically test for. * @return a int. - * @since 1.0.15 + * @since 1.5.59 */ public static int determineLeftoverMana(final SpellAbility sa, final Player player, final String shardColor) { ManaCost origCost = sa.getPayCosts().getTotalMana(); diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java index 11377dfa538..6c776199b3f 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java @@ -1,13 +1,11 @@ package forge.ai.ability; import java.util.Arrays; -import java.util.Collections; import java.util.List; import org.apache.commons.lang3.StringUtils; import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import forge.ai.AiController; @@ -36,7 +34,6 @@ import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.player.PlayerActionConfirmMode; -import forge.game.player.PlayerPredicates; import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbilityRestriction; import forge.game.spellability.TargetRestrictions; @@ -144,6 +141,7 @@ public class PumpAi extends PumpAiBase { final String aiLogic = sa.getParam("AILogic"); final boolean isFight = "Fight".equals(aiLogic) || "PowerDmg".equals(aiLogic); + final boolean isBerserk = "Berserk".equals(aiLogic); if ("MoveCounter".equals(aiLogic)) { final SpellAbility moveSA = sa.findSubAbilityByType(ApiType.MoveCounter); @@ -337,7 +335,7 @@ public class PumpAi extends PumpAiBase { attack = AbilityUtils.calculateAmount(sa.getHostCard(), numAttack, sa); } - if ((numDefense.contains("X") && defense == 0) || (numAttack.contains("X") && attack == 0)) { + if ((numDefense.contains("X") && defense == 0) || (numAttack.contains("X") && attack == 0 && !isBerserk)) { return false; } diff --git a/forge-gui/res/ai/Default.ai b/forge-gui/res/ai/Default.ai index 264703db174..c27e50bc0f0 100644 --- a/forge-gui/res/ai/Default.ai +++ b/forge-gui/res/ai/Default.ai @@ -1,4 +1,5 @@ PLAY_AGGRO=false +USE_BERSERK_AGGRESSIVELY=false MULLIGAN_THRESHOLD=5 CHEAT_WITH_MANA_ON_SHUFFLE=true diff --git a/forge-gui/res/ai/Experimental.ai b/forge-gui/res/ai/Experimental.ai index 0769d73b240..c4f09fde81f 100644 --- a/forge-gui/res/ai/Experimental.ai +++ b/forge-gui/res/ai/Experimental.ai @@ -1,4 +1,5 @@ PLAY_AGGRO=false +USE_BERSERK_AGGRESSIVELY=false MULLIGAN_THRESHOLD=4 CHEAT_WITH_MANA_ON_SHUFFLE=true diff --git a/forge-gui/res/ai/Reckless.ai b/forge-gui/res/ai/Reckless.ai index 19fdae018db..ed06272098b 100644 --- a/forge-gui/res/ai/Reckless.ai +++ b/forge-gui/res/ai/Reckless.ai @@ -1,4 +1,5 @@ PLAY_AGGRO=true +USE_BERSERK_AGGRESSIVELY=true MULLIGAN_THRESHOLD=3 CHEAT_WITH_MANA_ON_SHUFFLE=true diff --git a/forge-gui/res/cardsfolder/b/berserk.txt b/forge-gui/res/cardsfolder/b/berserk.txt index e74b10b110f..a78f4c8db94 100644 --- a/forge-gui/res/cardsfolder/b/berserk.txt +++ b/forge-gui/res/cardsfolder/b/berserk.txt @@ -1,10 +1,9 @@ Name:Berserk ManaCost:G Types:Instant -A:SP$ Pump | Cost$ G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ X | KW$ Trample | ActivationPhases$ Upkeep->Declare Blockers | References$ X | SubAbility$ DelTrig | SpellDescription$ Cast CARDNAME only before the combat damage step. Target creature gains trample and gets +X/+0 until end of turn, where X is its power. At the beginning of the next end step, destroy that creature if it attacked this turn. +A:SP$ Pump | Cost$ G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ X | KW$ Trample | ActivationPhases$ Upkeep->Declare Blockers | References$ X | SubAbility$ DelTrig | AILogic$ Berserk | SpellDescription$ Cast CARDNAME only before the combat damage step. Target creature gains trample and gets +X/+0 until end of turn, where X is its power. At the beginning of the next end step, destroy that creature if it attacked this turn. SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End Of Turn | Execute$ TrigDestroy | RememberObjects$ Targeted | TriggerDescription$ At the beginning of the next end step, destroy that creature if it attacked this turn. | AILogic$ Always SVar:TrigDestroy:DB$ Destroy | Defined$ DelayTriggerRemembered | ConditionDefined$ DelayTriggerRemembered | ConditionPresent$ Card.attackedThisTurn | ConditionCompare$ GE1 SVar:X:Targeted$CardPower -SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/berserk.jpg Oracle:Cast Berserk only before the combat damage step.\nTarget creature gains trample and gets +X/+0 until end of turn, where X is its power. At the beginning of the next end step, destroy that creature if it attacked this turn.