- AI will now aggressively sacrifice stolen creatures to gain life.

This commit is contained in:
Sloth
2013-05-31 11:44:27 +00:00
parent 9b6a7379f3
commit cc5249c6fb
2 changed files with 42 additions and 14 deletions

View File

@@ -1,7 +1,5 @@
package forge.card.ability.ai; package forge.card.ability.ai;
import java.util.Random;
import forge.Card; import forge.Card;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
@@ -16,7 +14,6 @@ import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
import forge.util.MyRandom;
/** /**
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
@@ -30,8 +27,6 @@ public class LifeGainAi extends SpellAbilityAi {
*/ */
@Override @Override
protected boolean canPlayAI(Player ai, SpellAbility sa) { protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Random r = MyRandom.getRandom();
final Cost abCost = sa.getPayCosts(); final Cost abCost = sa.getPayCosts();
final Card source = sa.getSourceCard(); final Card source = sa.getSourceCard();
final Game game = source.getGame(); final Game game = source.getGame();
@@ -98,10 +93,12 @@ public class LifeGainAi extends SpellAbilityAi {
&& !sa.hasParam("ActivationPhases")) { && !sa.hasParam("ActivationPhases")) {
return false; return false;
} }
// Don't use lifegain before main 2 if possible // Don't use lifegain before main 2 if possible
if (!lifeCritical && (!game.getPhaseHandler().getNextTurn().equals(ai) if (!lifeCritical && (!game.getPhaseHandler().getNextTurn().equals(ai)
|| game.getPhaseHandler().getPhase().isBefore(PhaseType.END_OF_TURN)) || game.getPhaseHandler().getPhase().isBefore(PhaseType.END_OF_TURN))
&& !sa.hasParam("PlayerTurn") && !SpellAbilityAi.isSorcerySpeed(sa)) { && !sa.hasParam("PlayerTurn") && !SpellAbilityAi.isSorcerySpeed(sa)
&& !ComputerUtil.ActivateForSacCost(sa, ai)) {
return false; return false;
} }
@@ -111,7 +108,9 @@ public class LifeGainAi extends SpellAbilityAi {
} }
// prevent run-away activations - first time will always return true // prevent run-away activations - first time will always return true
final boolean chance = r.nextFloat() <= Math.pow(.9, sa.getActivationsThisTurn()); if (ComputerUtil.preventRunAwayActivations(sa)) {
return false;
}
final Target tgt = sa.getTarget(); final Target tgt = sa.getTarget();
if (tgt != null) { if (tgt != null) {
@@ -123,12 +122,7 @@ public class LifeGainAi extends SpellAbilityAi {
} }
} }
boolean randomReturn = r.nextFloat() <= .6667; return true;
if (lifeCritical || SpellAbilityAi.playReusable(ai, sa)) {
randomReturn = true;
}
return (randomReturn && chance);
} }

View File

@@ -43,6 +43,7 @@ import forge.card.cost.Cost;
import forge.card.cost.CostDiscard; import forge.card.cost.CostDiscard;
import forge.card.cost.CostPart; import forge.card.cost.CostPart;
import forge.card.cost.CostPayment; import forge.card.cost.CostPayment;
import forge.card.cost.CostSacrifice;
import forge.card.spellability.AbilityManaPart; import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.AbilityStatic; import forge.card.spellability.AbilityStatic;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
@@ -350,7 +351,7 @@ public class ComputerUtil {
} }
} }
if (pref.contains("SacCost")) { // search for permanents with SacMe if (pref.contains("SacCost")) { // search for permanents with SacMe
for (int ip = 1; ip < 6; ip++) { // priority 1 is the lowest, for (int ip = 0; ip < 6; ip++) { // priority 1 is the lowest,
// priority 5 the highest // priority 5 the highest
final int priority = 6 - ip; final int priority = 6 - ip;
final List<Card> sacMeList = CardLists.filter(typeList, new Predicate<Card>() { final List<Card> sacMeList = CardLists.filter(typeList, new Predicate<Card>() {
@@ -1084,6 +1085,39 @@ public class ComputerUtil {
return r.nextFloat() <= Math.pow(.95, activations); return r.nextFloat() <= Math.pow(.95, activations);
} }
/**
* TODO: Write javadoc for this method.
* @param sa
* @return
*/
public static boolean ActivateForSacCost(SpellAbility sa, final Player ai) {
final Cost abCost = sa.getPayCosts();
final Card source = sa.getSourceCard();
if (abCost == null) {
return false;
}
for (final CostPart part : abCost.getCostParts()) {
if (part instanceof CostSacrifice) {
final CostSacrifice sac = (CostSacrifice) part;
final String type = sac.getType();
if (type.equals("CARDNAME")) {
continue;
}
final List<Card> typeList =
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(","), source.getController(), source);
for (Card c : typeList) {
if (c.getSVar("SacMe").equals("6")) {
return true;
}
}
}
}
return false;
}
/** /**
* <p> * <p>
* hasACardGivingHaste. * hasACardGivingHaste.