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