mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
Merge remote-tracking branch 'core/master'
This commit is contained in:
@@ -491,7 +491,7 @@ public class AiAttackController {
|
||||
Zone oppBattlefield = c.getController().getZone(ZoneType.Battlefield);
|
||||
|
||||
if (c.getName().equals("Heart of Kiran")) {
|
||||
if (oppBattlefield.contains(CardPredicates.Presets.PLANESWALKERS)) {
|
||||
if (Iterables.any(oppBattlefield, CardPredicates.Presets.PLANESWALKERS)) {
|
||||
// can be activated by removing a loyalty counter instead of tapping a creature
|
||||
continue;
|
||||
}
|
||||
@@ -500,7 +500,7 @@ public class AiAttackController {
|
||||
// TODO: the AI should ideally predict how many times it can activate
|
||||
// for now, unless the opponent is tapped out, break at this point
|
||||
// and do not predict the blocker limit (which is safer)
|
||||
if (oppBattlefield.contains(Predicates.and(CardPredicates.Presets.UNTAPPED, CardPredicates.Presets.LANDS))) {
|
||||
if (Iterables.any(oppBattlefield, Predicates.and(CardPredicates.Presets.UNTAPPED, CardPredicates.Presets.LANDS))) {
|
||||
maxBlockersAfterCrew = Integer.MAX_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1335,7 +1335,7 @@ public class AiBlockController {
|
||||
boolean creatureParityOrAllowedDiff = aiCreatureCount
|
||||
+ (randomTradeIfBehindOnBoard ? maxCreatDiff : 0) >= oppCreatureCount;
|
||||
boolean wantToTradeWithCreatInHand = !checkingOther && randomTradeIfCreatInHand
|
||||
&& Iterables.any(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.CREATURES)
|
||||
&& ai.getZone(ZoneType.Hand).contains(CardPredicates.Presets.CREATURES)
|
||||
&& aiCreatureCount + maxCreatDiffWithRepl >= oppCreatureCount;
|
||||
boolean wantToSavePlaneswalker = MyRandom.percentTrue(chanceToSavePW)
|
||||
&& combat.getDefenderByAttacker(attacker) instanceof Card
|
||||
|
||||
@@ -444,8 +444,7 @@ public class AiController {
|
||||
CardCollection nonLandsInHand = CardLists.filter(player.getCardsIn(ZoneType.Hand), Predicates.not(CardPredicates.Presets.LANDS));
|
||||
|
||||
// Some considerations for Momir/MoJhoSto
|
||||
boolean hasMomir = Iterables.any(player.getCardsIn(ZoneType.Command),
|
||||
CardPredicates.nameEquals("Momir Vig, Simic Visionary Avatar"));
|
||||
boolean hasMomir = player.getZone(ZoneType.Command).contains(CardPredicates.nameEquals("Momir Vig, Simic Visionary Avatar"));
|
||||
if (hasMomir && nonLandsInHand.isEmpty()) {
|
||||
// Only do this if we have an all-basic land hand, which covers both stock Momir and MoJhoSto modes
|
||||
// and also a custom Vanguard setup with a customized basic land deck and Momir as the avatar.
|
||||
@@ -1525,8 +1524,7 @@ public class AiController {
|
||||
}
|
||||
|
||||
private boolean isSafeToHoldLandDropForMain2(Card landToPlay) {
|
||||
boolean hasMomir = Iterables.any(player.getCardsIn(ZoneType.Command),
|
||||
CardPredicates.nameEquals("Momir Vig, Simic Visionary Avatar"));
|
||||
boolean hasMomir = player.getZone(ZoneType.Command).contains(CardPredicates.nameEquals("Momir Vig, Simic Visionary Avatar"));
|
||||
if (hasMomir) {
|
||||
// Don't do this in Momir variants since it messes with the AI decision making for the avatar.
|
||||
return false;
|
||||
@@ -1711,7 +1709,7 @@ public class AiController {
|
||||
|
||||
if (sa.getHostCard().hasKeyword(Keyword.STORM)
|
||||
&& sa.getApi() != ApiType.Counter // AI would suck at trying to deliberately proc a Storm counterspell
|
||||
&& Iterables.any(player.getCardsIn(ZoneType.Hand), Predicates.not(Predicates.or(CardPredicates.Presets.LANDS, CardPredicates.hasKeyword("Storm"))))) {
|
||||
&& player.getZone(ZoneType.Hand).contains(Predicates.not(Predicates.or(CardPredicates.Presets.LANDS, CardPredicates.hasKeyword("Storm"))))) {
|
||||
if (game.getView().getStormCount() < this.getIntProperty(AiProps.MIN_COUNT_FOR_STORM_SPELLS)) {
|
||||
// skip evaluating Storm unless we reached the minimum Storm count
|
||||
continue;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import forge.ai.*;
|
||||
@@ -110,7 +109,7 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
&& game.getPhaseHandler().getNextTurn() != ai
|
||||
&& source.isPermanent();
|
||||
if (ph.isPlayerTurn(ai) && ai.getLife() < 6 && opponent.getLife() > 6
|
||||
&& Iterables.any(opponent.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES)
|
||||
&& opponent.getZone(ZoneType.Battlefield).contains(CardPredicates.Presets.CREATURES)
|
||||
&& !sa.hasParam("AILogic") && !"Permanent".equals(sa.getParam("Duration")) && !activateAsPotentialBlocker) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
||||
sa.getTargets().add(aiPlayer);
|
||||
return true;
|
||||
} else {
|
||||
for (Player p : aiPlayer.getTeamMates(true)) {
|
||||
for (Player p : aiPlayer.getYourTeam()) {
|
||||
if (sa.canTarget(p)) {
|
||||
sa.getTargets().add(p);
|
||||
return true;
|
||||
|
||||
@@ -46,7 +46,7 @@ public class LearnAi extends SpellAbilityAi {
|
||||
|
||||
if (!lessons.isEmpty()) {
|
||||
return ComputerUtilCard.getBestAI(lessons);
|
||||
} else if (!goodDiscards.isEmpty()) {
|
||||
} else if (goodDiscards != null && !goodDiscards.isEmpty()) {
|
||||
return ComputerUtilCard.getWorstAI(goodDiscards);
|
||||
}
|
||||
|
||||
|
||||
@@ -385,11 +385,11 @@ public class DigEffect extends SpellAbilityEffect {
|
||||
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
|
||||
moveParams.put(AbilityKey.LastStateBattlefield, lastStateBattlefield);
|
||||
moveParams.put(AbilityKey.LastStateGraveyard, lastStateGraveyard);
|
||||
if (sa.hasParam("Tapped")) {
|
||||
c.setTapped(true);
|
||||
}
|
||||
c = game.getAction().moveTo(zone, c, sa, moveParams);
|
||||
if (destZone1.equals(ZoneType.Battlefield)) {
|
||||
if (sa.hasParam("Tapped")) {
|
||||
c.setTapped(true);
|
||||
}
|
||||
if (addToCombat(c, c.getController(), sa, "Attacking", "Blocking")) {
|
||||
combatChanged = true;
|
||||
}
|
||||
|
||||
@@ -114,12 +114,12 @@ public class DigMultipleEffect extends SpellAbilityEffect {
|
||||
}
|
||||
c = game.getAction().moveTo(zone, c, libraryPosition, sa);
|
||||
} else {
|
||||
c = game.getAction().moveTo(zone, c, sa);
|
||||
if (destZone1.equals(ZoneType.Battlefield)) {
|
||||
if (sa.hasParam("Tapped")) {
|
||||
c.setTapped(true);
|
||||
}
|
||||
}
|
||||
c = game.getAction().moveTo(zone, c, sa);
|
||||
}
|
||||
if (!origin.equals(c.getZone().getZoneType())) {
|
||||
table.put(origin, c.getZone().getZoneType(), c);
|
||||
|
||||
@@ -180,10 +180,10 @@ public class DigUntilEffect extends SpellAbilityEffect {
|
||||
Card m = null;
|
||||
if (sa.hasParam("GainControl") && foundDest.equals(ZoneType.Battlefield)) {
|
||||
c.setController(sa.getActivatingPlayer(), game.getNextTimestamp());
|
||||
m = game.getAction().moveTo(c.getController().getZone(foundDest), c, sa, moveParams);
|
||||
if (sa.hasParam("Tapped")) {
|
||||
c.setTapped(true);
|
||||
}
|
||||
m = game.getAction().moveTo(c.getController().getZone(foundDest), c, sa, moveParams);
|
||||
if (addToCombat(c, c.getController(), sa, "Attacking", "Blocking")) {
|
||||
combatChanged = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user