mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
- AI fix for "fight" keyword. Added "AILogic$ Main2" to Domri Rade's +1 to allow AI to choose -2 ability if available.
This commit is contained in:
@@ -2,6 +2,7 @@ package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.*;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
@@ -12,6 +13,7 @@ import forge.game.cost.Cost;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -48,7 +50,7 @@ public class CountersPutAi extends SpellAbilityAi {
|
||||
if ("Never".equals(sa.getParam("AILogic"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
|
||||
@@ -92,6 +94,34 @@ public class CountersPutAi extends SpellAbilityAi {
|
||||
// TODO handle proper calculation of X values based on Cost
|
||||
int amount = AbilityUtils.calculateAmount(source, amountStr, sa);
|
||||
|
||||
if (sa.getParam("AILogic").equals("Fight")) {
|
||||
int nPump = 0;
|
||||
if (type.equals("P1P1")) {
|
||||
nPump = amount;
|
||||
}
|
||||
final AbilitySub tgtFight = sa.getSubAbility();
|
||||
List<Card> aiCreatures = ai.getCreaturesInPlay();
|
||||
aiCreatures = CardLists.getTargetableCards(aiCreatures, sa);
|
||||
aiCreatures = ComputerUtil.getSafeTargets(ai, sa, aiCreatures);
|
||||
CardLists.sortByPowerDesc(aiCreatures);
|
||||
|
||||
List<Card> humCreatures = ai.getOpponent().getCreaturesInPlay();
|
||||
humCreatures = CardLists.getTargetableCards(humCreatures, tgtFight);
|
||||
CardLists.sortByCmcDesc(humCreatures);
|
||||
if (humCreatures.isEmpty() || aiCreatures.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (Card humanCreature : humCreatures) {
|
||||
for (Card aiCreature : aiCreatures) {
|
||||
if (FightAi.shouldFight(aiCreature, humanCreature, nPump, nPump)) {
|
||||
sa.getTargets().add(aiCreature);
|
||||
tgtFight.getTargets().add(humanCreature);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (amountStr.equals("X") && source.getSVar(amountStr).equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
amount = ComputerUtilMana.determineLeftoverMana(sa, ai);
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
@@ -13,6 +15,7 @@ import forge.game.combat.CombatUtil;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
@@ -120,6 +123,29 @@ public class EffectAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
randomReturn = threatened;
|
||||
} else if (logic.equals("Fight")) {
|
||||
List<Card> humCreatures = ai.getOpponent().getCreaturesInPlay();
|
||||
humCreatures = CardLists.getTargetableCards(humCreatures, sa);
|
||||
CardLists.sortByCmcDesc(humCreatures);
|
||||
|
||||
final AbilitySub tgtFight = sa.getSubAbility();
|
||||
List<Card> aiCreatures = ai.getCreaturesInPlay();
|
||||
aiCreatures = CardLists.getTargetableCards(aiCreatures, tgtFight);
|
||||
aiCreatures = ComputerUtil.getSafeTargets(ai, tgtFight, aiCreatures);
|
||||
CardLists.sortByPowerDesc(aiCreatures);
|
||||
|
||||
if (humCreatures.isEmpty() || aiCreatures.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (Card humanCreature : humCreatures) {
|
||||
for (Card aiCreature : aiCreatures) {
|
||||
if (FightAi.shouldFight(aiCreature, humanCreature, 0, 0)) {
|
||||
tgtFight.getTargets().add(aiCreature);
|
||||
sa.getTargets().add(humanCreature);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { //no AILogic
|
||||
return false;
|
||||
|
||||
@@ -53,7 +53,7 @@ public class FightAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
if (sa.hasParam("TargetsFromDifferentZone")) {
|
||||
if (humCreatures.isEmpty() && aiCreatures.isEmpty()) {
|
||||
if (!(humCreatures.isEmpty() && aiCreatures.isEmpty())) {
|
||||
for (Card humanCreature : humCreatures) {
|
||||
for (Card aiCreature : aiCreatures) {
|
||||
if (ComputerUtilCombat.getDamageToKill(humanCreature) <= aiCreature.getNetAttack()
|
||||
@@ -135,5 +135,29 @@ public class FightAi extends SpellAbilityAi {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean shouldFight(Card fighter, Card opponent, int pumpAttack, int pumpDefense) {
|
||||
if (canKill(fighter, opponent, pumpAttack)) {
|
||||
if (!canKill(opponent, fighter, -pumpDefense)) {
|
||||
return true;
|
||||
} else {
|
||||
final Random r = MyRandom.getRandom();
|
||||
if (r.nextInt(20)<(opponent.getCMC() - fighter.getCMC())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static boolean canKill(Card fighter, Card opponent, int pumpAttack) {
|
||||
if (opponent.getSVar("Targeting").equals("Dies")) {
|
||||
return true;
|
||||
}
|
||||
if (opponent.hasProtectionFrom(fighter) || !opponent.canBeDestroyed()) {
|
||||
return false;
|
||||
}
|
||||
if (fighter.hasKeyword("Deathtouch") || ComputerUtilCombat.getDamageToKill(opponent) <= fighter.getNetAttack() + pumpAttack) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package forge.ai.ability;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.SpellApiToAi;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.AbilityStatic;
|
||||
@@ -22,6 +23,11 @@ public class PeekAndRevealAi extends SpellAbilityAi {
|
||||
if (sa instanceof AbilityStatic) {
|
||||
return false;
|
||||
}
|
||||
if (sa.getParam("AILogic").equals("Main2")) {
|
||||
if (aiPlayer.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// So far this only appears on Triggers, but will expand
|
||||
// once things get converted from Dig + NoMove
|
||||
return true;
|
||||
|
||||
@@ -13,6 +13,7 @@ import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityRestriction;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
@@ -211,9 +212,31 @@ public class PumpAi extends PumpAiBase {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (sa.getParam("AILogic").equals("Fight")) {
|
||||
final AbilitySub tgtFight = sa.getSubAbility();
|
||||
List<Card> aiCreatures = ai.getCreaturesInPlay();
|
||||
aiCreatures = CardLists.getTargetableCards(aiCreatures, sa);
|
||||
aiCreatures = ComputerUtil.getSafeTargets(ai, sa, aiCreatures);
|
||||
CardLists.sortByPowerDesc(aiCreatures);
|
||||
|
||||
List<Card> humCreatures = ai.getOpponent().getCreaturesInPlay();
|
||||
humCreatures = CardLists.getTargetableCards(humCreatures, tgtFight);
|
||||
CardLists.sortByCmcDesc(humCreatures);
|
||||
if (humCreatures.isEmpty() || aiCreatures.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (Card humanCreature : humCreatures) {
|
||||
for (Card aiCreature : aiCreatures) {
|
||||
if (FightAi.shouldFight(aiCreature, humanCreature, attack, defense)) {
|
||||
sa.getTargets().add(aiCreature);
|
||||
tgtFight.getTargets().add(humanCreature);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (sa.isCurse()) {
|
||||
if (sa.canTarget(opp)) {
|
||||
sa.getTargets().add(opp);
|
||||
|
||||
Reference in New Issue
Block a user