- 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:
excessum
2014-03-20 12:58:04 +00:00
parent 7c3bcda327
commit 9f810d131f
11 changed files with 160 additions and 56 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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);