- AI will now predict battle cry boni.

This commit is contained in:
jendave
2011-08-06 22:13:37 +00:00
parent 1877ff7e62
commit cae9ebdef2
5 changed files with 123 additions and 73 deletions

View File

@@ -601,7 +601,7 @@ public class CombatUtil {
{ {
int damage = attacker.getNetCombatDamage(); int damage = attacker.getNetCombatDamage();
int sum = 0; int sum = 0;
damage += predictPowerBonusOfAttacker(attacker,null); damage += predictPowerBonusOfAttacker(attacker,null,null);
if (!attacker.hasKeyword("Infect")) { if (!attacker.hasKeyword("Infect")) {
sum = attacked.predictDamage(damage, attacker, true); sum = attacked.predictDamage(damage, attacker, true);
if (attacker.hasKeyword("Double Strike")) sum += attacked.predictDamage(damage, attacker, true); if (attacker.hasKeyword("Double Strike")) sum += attacked.predictDamage(damage, attacker, true);
@@ -614,7 +614,7 @@ public class CombatUtil {
{ {
int damage = attacker.getNetCombatDamage(); int damage = attacker.getNetCombatDamage();
int poison = 0; int poison = 0;
damage += predictPowerBonusOfAttacker(attacker,null); damage += predictPowerBonusOfAttacker(attacker, null, null);
if (attacker.hasKeyword("Infect")) { if (attacker.hasKeyword("Infect")) {
poison += attacked.predictDamage(damage, attacker, true); poison += attacked.predictDamage(damage, attacker, true);
if (attacker.hasKeyword("Double Strike")) poison += attacked.predictDamage(damage, attacker, true); if (attacker.hasKeyword("Double Strike")) poison += attacked.predictDamage(damage, attacker, true);
@@ -761,7 +761,7 @@ public class CombatUtil {
// This calculates the amount of damage a blocker in a blockgang can take from the attacker (for trampling attackers) // This calculates the amount of damage a blocker in a blockgang can take from the attacker (for trampling attackers)
public static int shieldDamage(Card attacker, Card defender) { public static int shieldDamage(Card attacker, Card defender) {
if (!canDestroyBlocker(defender,attacker)) return 100; if (!canDestroyBlocker(defender,attacker, null)) return 100;
int flankingMagnitude = 0; int flankingMagnitude = 0;
if(attacker.getKeyword().contains("Flanking") && !defender.getKeyword().contains("Flanking")) { if(attacker.getKeyword().contains("Flanking") && !defender.getKeyword().contains("Flanking")) {
@@ -796,7 +796,7 @@ public class CombatUtil {
CardList blockers = AllZone.Combat.getBlockers(attacker); CardList blockers = AllZone.Combat.getBlockers(attacker);
for (Card defender:blockers) { for (Card defender:blockers) {
if(CombatUtil.canDestroyAttacker(attacker, defender) && if(CombatUtil.canDestroyAttacker(attacker, defender, AllZone.Combat) &&
!(defender.getKeyword().contains("Wither") || defender.getKeyword().contains("Infect"))) !(defender.getKeyword().contains("Wither") || defender.getKeyword().contains("Infect")))
return true; return true;
} }
@@ -805,21 +805,25 @@ public class CombatUtil {
} }
//Will this trigger trigger? //Will this trigger trigger?
public static boolean combatTriggerWillTrigger(Card attacker, Card defender, Trigger trigger) { public static boolean combatTriggerWillTrigger(Card attacker, Card defender, Trigger trigger, Combat combat) {
HashMap<String,String> trigParams = trigger.getMapParams(); HashMap<String,String> trigParams = trigger.getMapParams();
boolean willTrigger = false; boolean willTrigger = false;
Card source = trigger.getHostCard(); Card source = trigger.getHostCard();
if (combat == null) combat = AllZone.Combat;
if (!trigger.zonesCheck()) return false; if (!trigger.zonesCheck()) return false;
if (!trigger.requirementsCheck()) return false; if (!trigger.requirementsCheck()) return false;
if (trigParams.get("Mode").equals("Attacks")) { if (trigParams.get("Mode").equals("Attacks")) {
willTrigger = true; willTrigger = true;
if (attacker.isAttacking()) return false; //The trigger should have triggered already if(attacker.isAttacking()) return false; //The trigger should have triggered already
if(trigParams.containsKey("ValidCard")) if(trigParams.containsKey("ValidCard")) {
if(!trigger.matchesValid(attacker, trigParams.get("ValidCard").split(","), source)) if(!trigger.matchesValid(attacker, trigParams.get("ValidCard").split(","), source)
&& !(combat.isAttacking(source) &&
trigger.matchesValid(source, trigParams.get("ValidCard").split(","), source)))
return false; return false;
} }
}
// defender == null means unblocked // defender == null means unblocked
if (defender == null && trigParams.get("Mode").equals("AttackerUnblocked")) { if (defender == null && trigParams.get("Mode").equals("AttackerUnblocked")) {
@@ -876,14 +880,14 @@ public class CombatUtil {
HashMap<String,String> trigParams = trigger.getMapParams(); HashMap<String,String> trigParams = trigger.getMapParams();
Card source = trigger.getHostCard(); Card source = trigger.getHostCard();
if(combatTriggerWillTrigger(attacker, defender, trigger) && trigParams.containsKey("Execute")) { if(combatTriggerWillTrigger(attacker, defender, trigger, null) && trigParams.containsKey("Execute")) {
String ability = source.getSVar(trigParams.get("Execute")); String ability = source.getSVar(trigParams.get("Execute"));
AbilityFactory AF = new AbilityFactory(); AbilityFactory AF = new AbilityFactory();
HashMap<String,String> abilityParams = AF.getMapParams(ability, source); HashMap<String,String> abilityParams = AF.getMapParams(ability, source);
if (abilityParams.containsKey("AB")) { if (abilityParams.containsKey("AB")) {
if (abilityParams.get("AB").equals("Pump")) if (abilityParams.get("AB").equals("Pump"))
if (!abilityParams.containsKey("ValidTgts") && !abilityParams.containsKey("Tgt")) if (!abilityParams.containsKey("ValidTgts") && !abilityParams.containsKey("Tgt"))
if (AbilityFactory.getDefinedCards(source, trigParams.get("Defined"), null).contains(defender)) if (AbilityFactory.getDefinedCards(source, abilityParams.get("Defined"), null).contains(defender))
if (abilityParams.containsKey("NumAtt")){ if (abilityParams.containsKey("NumAtt")){
String att = abilityParams.get("NumAtt"); String att = abilityParams.get("NumAtt");
if (att.startsWith("+")) if (att.startsWith("+"))
@@ -911,14 +915,14 @@ public class CombatUtil {
HashMap<String,String> trigParams = trigger.getMapParams(); HashMap<String,String> trigParams = trigger.getMapParams();
Card source = trigger.getHostCard(); Card source = trigger.getHostCard();
if(combatTriggerWillTrigger(attacker, defender, trigger) && trigParams.containsKey("Execute")) { if(combatTriggerWillTrigger(attacker, defender, trigger, null) && trigParams.containsKey("Execute")) {
String ability = source.getSVar(trigParams.get("Execute")); String ability = source.getSVar(trigParams.get("Execute"));
AbilityFactory AF = new AbilityFactory(); AbilityFactory AF = new AbilityFactory();
HashMap<String,String> abilityParams = AF.getMapParams(ability, source); HashMap<String,String> abilityParams = AF.getMapParams(ability, source);
if (abilityParams.containsKey("AB")) { if (abilityParams.containsKey("AB")) {
if (abilityParams.get("AB").equals("Pump")) if (abilityParams.get("AB").equals("Pump"))
if (!abilityParams.containsKey("ValidTgts") && !abilityParams.containsKey("Tgt")) if (!abilityParams.containsKey("ValidTgts") && !abilityParams.containsKey("Tgt"))
if (AbilityFactory.getDefinedCards(source, trigParams.get("Defined"), null).contains(defender)) if (AbilityFactory.getDefinedCards(source, abilityParams.get("Defined"), null).contains(defender))
if (abilityParams.containsKey("NumDef")) { if (abilityParams.containsKey("NumDef")) {
String def = abilityParams.get("NumDef"); String def = abilityParams.get("NumDef");
if (def.startsWith("+")) if (def.startsWith("+"))
@@ -932,7 +936,7 @@ public class CombatUtil {
} }
//Predict the Power bonus of the blocker if blocking the attacker (Flanking, Bushido and other triggered abilities) //Predict the Power bonus of the blocker if blocking the attacker (Flanking, Bushido and other triggered abilities)
public static int predictPowerBonusOfAttacker(Card attacker, Card defender) { public static int predictPowerBonusOfAttacker(Card attacker, Card defender, Combat combat) {
int power = 0; int power = 0;
power += attacker.getKeywordMagnitude("Bushido"); power += attacker.getKeywordMagnitude("Bushido");
@@ -952,15 +956,27 @@ public class CombatUtil {
HashMap<String,String> trigParams = trigger.getMapParams(); HashMap<String,String> trigParams = trigger.getMapParams();
Card source = trigger.getHostCard(); Card source = trigger.getHostCard();
if(combatTriggerWillTrigger(attacker, defender, trigger) && trigParams.containsKey("Execute")) { if(combatTriggerWillTrigger(attacker, defender, trigger, combat) && trigParams.containsKey("Execute")) {
String ability = source.getSVar(trigParams.get("Execute")); String ability = source.getSVar(trigParams.get("Execute"));
AbilityFactory AF = new AbilityFactory(); AbilityFactory AF = new AbilityFactory();
HashMap<String,String> abilityParams = AF.getMapParams(ability, source); HashMap<String,String> abilityParams = AF.getMapParams(ability, source);
if (abilityParams.containsKey("AB")) { if (abilityParams.containsKey("AB")) {
boolean isValid = false;
//Pump
if (abilityParams.get("AB").equals("Pump")) if (abilityParams.get("AB").equals("Pump"))
if (!abilityParams.containsKey("ValidTgts") && !abilityParams.containsKey("Tgt")) if (!abilityParams.containsKey("ValidTgts") && !abilityParams.containsKey("Tgt")) //not targeted
if (AbilityFactory.getDefinedCards(source, trigParams.get("Defined"), null).contains(attacker)) if (AbilityFactory.getDefinedCards(source, abilityParams.get("Defined"), null).contains(attacker))
if (abilityParams.containsKey("NumAtt")){ isValid = true;
//PumpAll
if (abilityParams.get("AB").equals("PumpAll") && abilityParams.containsKey("ValidCards"))
if (attacker.isValidCard(abilityParams.get("ValidCards").split(","), source.getController(), source)
|| attacker.isValidCard(abilityParams.get("ValidCards").replace("attacking+", "").split(",")
, source.getController(), source))
isValid = true;
if (abilityParams.containsKey("NumAtt") && isValid){
String att = abilityParams.get("NumAtt"); String att = abilityParams.get("NumAtt");
if (att.startsWith("+")) if (att.startsWith("+"))
att = att.substring(1); att = att.substring(1);
@@ -979,7 +995,7 @@ public class CombatUtil {
} }
//Predict the Toughness bonus of the blocker if blocking the attacker (Flanking, Bushido and other triggered abilities) //Predict the Toughness bonus of the blocker if blocking the attacker (Flanking, Bushido and other triggered abilities)
public static int predictToughnessBonusOfAttacker(Card attacker, Card defender) { public static int predictToughnessBonusOfAttacker(Card attacker, Card defender, Combat combat) {
int toughness = 0; int toughness = 0;
toughness += attacker.getKeywordMagnitude("Bushido"); toughness += attacker.getKeywordMagnitude("Bushido");
@@ -990,15 +1006,27 @@ public class CombatUtil {
HashMap<String,String> trigParams = trigger.getMapParams(); HashMap<String,String> trigParams = trigger.getMapParams();
Card source = trigger.getHostCard(); Card source = trigger.getHostCard();
if(combatTriggerWillTrigger(attacker, defender, trigger) && trigParams.containsKey("Execute")) { if(combatTriggerWillTrigger(attacker, defender, trigger, combat) && trigParams.containsKey("Execute")) {
String ability = source.getSVar(trigParams.get("Execute")); String ability = source.getSVar(trigParams.get("Execute"));
AbilityFactory AF = new AbilityFactory(); AbilityFactory AF = new AbilityFactory();
HashMap<String,String> abilityParams = AF.getMapParams(ability, source); HashMap<String,String> abilityParams = AF.getMapParams(ability, source);
if (abilityParams.containsKey("AB")) { if (abilityParams.containsKey("AB")) {
boolean isValid = false;
//Pump
if (abilityParams.get("AB").equals("Pump")) if (abilityParams.get("AB").equals("Pump"))
if (!abilityParams.containsKey("ValidTgts") && !abilityParams.containsKey("Tgt")) if (!abilityParams.containsKey("ValidTgts") && !abilityParams.containsKey("Tgt")) //not targeted
if (AbilityFactory.getDefinedCards(source, trigParams.get("Defined"), null).contains(attacker)) if (AbilityFactory.getDefinedCards(source, abilityParams.get("Defined"), null).contains(attacker))
if (abilityParams.containsKey("NumDef")) { isValid = true;
//PumpAll
if (abilityParams.get("AB").equals("PumpAll") && abilityParams.containsKey("ValidCards"))
if (attacker.isValidCard(abilityParams.get("ValidCards").split(","), source.getController(), source)
|| attacker.isValidCard(abilityParams.get("ValidCards").replace("attacking+", "").split(",")
, source.getController(), source))
isValid = true;
if (abilityParams.containsKey("NumDef") && isValid){
String def = abilityParams.get("NumDef"); String def = abilityParams.get("NumDef");
if (def.startsWith("+")) if (def.startsWith("+"))
def = def.substring(1); def = def.substring(1);
@@ -1017,7 +1045,7 @@ public class CombatUtil {
} }
//can the blocker destroy the attacker? //can the blocker destroy the attacker?
public static boolean canDestroyAttacker(Card attacker, Card defender) { public static boolean canDestroyAttacker(Card attacker, Card defender, Combat combat) {
if(attacker.getName().equals("Sylvan Basilisk") && !defender.getKeyword().contains("Indestructible")) return false; if(attacker.getName().equals("Sylvan Basilisk") && !defender.getKeyword().contains("Indestructible")) return false;
@@ -1039,10 +1067,10 @@ public class CombatUtil {
//int attBushidoMagnitude = attacker.getKeywordMagnitude("Bushido"); //int attBushidoMagnitude = attacker.getKeywordMagnitude("Bushido");
int defenderDamage = defender.getNetAttack() + predictPowerBonusOfBlocker(attacker, defender); int defenderDamage = defender.getNetAttack() + predictPowerBonusOfBlocker(attacker, defender);
int attackerDamage = attacker.getNetAttack() + predictPowerBonusOfAttacker(attacker, defender); int attackerDamage = attacker.getNetAttack() + predictPowerBonusOfAttacker(attacker, defender, combat);
if (AllZoneUtil.isCardInPlay("Doran, the Siege Tower")) { if (AllZoneUtil.isCardInPlay("Doran, the Siege Tower")) {
defenderDamage = defender.getNetDefense() + predictToughnessBonusOfBlocker(attacker, defender); defenderDamage = defender.getNetDefense() + predictToughnessBonusOfBlocker(attacker, defender);
attackerDamage = attacker.getNetDefense() + predictToughnessBonusOfAttacker(attacker, defender); attackerDamage = attacker.getNetDefense() + predictToughnessBonusOfAttacker(attacker, defender, combat);
} }
// consider Damage Prevention/Replacement // consider Damage Prevention/Replacement
@@ -1050,7 +1078,7 @@ public class CombatUtil {
attackerDamage = defender.predictDamage(attackerDamage, attacker, true); attackerDamage = defender.predictDamage(attackerDamage, attacker, true);
int defenderLife = defender.getKillDamage() + predictToughnessBonusOfBlocker(attacker, defender); int defenderLife = defender.getKillDamage() + predictToughnessBonusOfBlocker(attacker, defender);
int attackerLife = attacker.getKillDamage() + predictToughnessBonusOfAttacker(attacker, defender); int attackerLife = attacker.getKillDamage() + predictToughnessBonusOfAttacker(attacker, defender, combat);
if(defender.getKeyword().contains("Double Strike") ) { if(defender.getKeyword().contains("Double Strike") ) {
if(defender.getKeyword().contains("Deathtouch") && defenderDamage > 0) return true; if(defender.getKeyword().contains("Deathtouch") && defenderDamage > 0) return true;
@@ -1088,14 +1116,14 @@ public class CombatUtil {
public static boolean blockerWouldBeDestroyed(Card blocker) { public static boolean blockerWouldBeDestroyed(Card blocker) {
Card attacker = AllZone.Combat.getAttackerBlockedBy(blocker); Card attacker = AllZone.Combat.getAttackerBlockedBy(blocker);
if(canDestroyBlocker(blocker, attacker) && if(canDestroyBlocker(blocker, attacker, AllZone.Combat) &&
!(attacker.getKeyword().contains("Wither") || attacker.getKeyword().contains("Infect"))) !(attacker.getKeyword().contains("Wither") || attacker.getKeyword().contains("Infect")))
return true; return true;
return false; return false;
} }
//can the attacker destroy this blocker? //can the attacker destroy this blocker?
public static boolean canDestroyBlocker(Card defender, Card attacker) { public static boolean canDestroyBlocker(Card defender, Card attacker, Combat combat) {
int flankingMagnitude = 0; int flankingMagnitude = 0;
if(attacker.getKeyword().contains("Flanking") && !defender.getKeyword().contains("Flanking")) { if(attacker.getKeyword().contains("Flanking") && !defender.getKeyword().contains("Flanking")) {
@@ -1112,10 +1140,10 @@ public class CombatUtil {
if(attacker.getName().equals("Sylvan Basilisk") && !defender.getKeyword().contains("Indestructible")) return true; if(attacker.getName().equals("Sylvan Basilisk") && !defender.getKeyword().contains("Indestructible")) return true;
int defenderDamage = defender.getNetAttack() + predictPowerBonusOfBlocker(attacker, defender); int defenderDamage = defender.getNetAttack() + predictPowerBonusOfBlocker(attacker, defender);
int attackerDamage = attacker.getNetAttack() + predictPowerBonusOfAttacker(attacker, defender); int attackerDamage = attacker.getNetAttack() + predictPowerBonusOfAttacker(attacker, defender, combat);
if (AllZoneUtil.isCardInPlay("Doran, the Siege Tower")) { if (AllZoneUtil.isCardInPlay("Doran, the Siege Tower")) {
defenderDamage = defender.getNetDefense() + predictToughnessBonusOfBlocker(attacker, defender); defenderDamage = defender.getNetDefense() + predictToughnessBonusOfBlocker(attacker, defender);
attackerDamage = attacker.getNetDefense() + predictToughnessBonusOfAttacker(attacker, defender); attackerDamage = attacker.getNetDefense() + predictToughnessBonusOfAttacker(attacker, defender, combat);
} }
// consider Damage Prevention/Replacement // consider Damage Prevention/Replacement
@@ -1123,7 +1151,7 @@ public class CombatUtil {
attackerDamage = defender.predictDamage(attackerDamage, attacker, true); attackerDamage = defender.predictDamage(attackerDamage, attacker, true);
int defenderLife = defender.getKillDamage() + predictToughnessBonusOfBlocker(attacker, defender); int defenderLife = defender.getKillDamage() + predictToughnessBonusOfBlocker(attacker, defender);
int attackerLife = attacker.getKillDamage() + predictToughnessBonusOfAttacker(attacker, defender); int attackerLife = attacker.getKillDamage() + predictToughnessBonusOfAttacker(attacker, defender, combat);
if(attacker.getKeyword().contains("Double Strike") ) { if(attacker.getKeyword().contains("Double Strike") ) {
if(attacker.getKeyword().contains("Deathtouch") && attackerDamage > 0) return true; if(attacker.getKeyword().contains("Deathtouch") && attackerDamage > 0) return true;

View File

@@ -1,9 +1,11 @@
package forge; package forge;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random; import java.util.Random;
import forge.card.cardFactory.CardFactoryUtil; import forge.card.cardFactory.CardFactoryUtil;
import forge.card.trigger.Trigger;
//doesHumanAttackAndWin() uses the global variable AllZone.ComputerPlayer //doesHumanAttackAndWin() uses the global variable AllZone.ComputerPlayer
public class ComputerUtil_Attack2 { public class ComputerUtil_Attack2 {
@@ -42,6 +44,28 @@ public class ComputerUtil_Attack2 {
this.blockerLife = blockerLife; this.blockerLife = blockerLife;
}//constructor }//constructor
public CardList sortAttackers(CardList in)
{
CardList list = new CardList();
//Cards with triggers should come first (for Battle Cry)
for(Card attacker:in) {
ArrayList<Trigger> registeredTriggers = AllZone.TriggerHandler.getRegisteredTriggers();
for(Trigger trigger : registeredTriggers)
{
HashMap<String,String> trigParams = trigger.getMapParams();
if (trigParams.get("Mode").equals("Attacks") && trigger.getHostCard().equals(attacker))
list.add(attacker);
}
}
for(Card attacker:in) {
if(!list.contains(attacker)) list.add(attacker);
}
return list;
}//sortAttackers()
public CardList getPossibleAttackers(CardList in) public CardList getPossibleAttackers(CardList in)
{ {
CardList list = new CardList(in.toArray()); CardList list = new CardList(in.toArray());
@@ -358,7 +382,8 @@ public class ComputerUtil_Attack2 {
aiAggression = 5; // attack at all costs aiAggression = 5; // attack at all costs
}else if((playerLifeToDamageRatio < 2 && ratioDiff >= 0) || ratioDiff > 3 || (ratioDiff > 0 && outNumber > 0)){ }else if((playerLifeToDamageRatio < 2 && ratioDiff >= 0) || ratioDiff > 3 || (ratioDiff > 0 && outNumber > 0)){
aiAggression = 3; // attack expecting to kill creatures or damage player. aiAggression = 3; // attack expecting to kill creatures or damage player.
}else if(ratioDiff >= 0 || ratioDiff + outNumber >= -1){ // at 0 ratio expect to potentially gain an advantage by attacking first }else if(ratioDiff >= 0 || ratioDiff + outNumber >= -1){
// at 0 ratio expect to potentially gain an advantage by attacking first
// if the ai has a slight advantage // if the ai has a slight advantage
// or the ai has a significant advantage numerically but only a slight disadvantage damage/life // or the ai has a significant advantage numerically but only a slight disadvantage damage/life
aiAggression = 2; // attack expecting to destroy creatures/be unblockable aiAggression = 2; // attack expecting to destroy creatures/be unblockable
@@ -412,15 +437,12 @@ public class ComputerUtil_Attack2 {
else else
{ {
System.out.println("Normal attack"); System.out.println("Normal attack");
//so the biggest creature will usually attack
//I think this works, not sure, may have to change it
//sortNonFlyingFirst has to be done first, because it reverses everything
CardListUtil.sortNonFlyingFirst(attackersLeft);
CardListUtil.sortAttackLowFirst(attackersLeft);
attackersLeft = notNeededAsBlockers(attackersLeft, combat); attackersLeft = notNeededAsBlockers(attackersLeft, combat);
System.out.println(attackersLeft.size()); System.out.println(attackersLeft.size());
attackersLeft = sortAttackers(attackersLeft);
for(int i = 0; i < attackersLeft.size(); i++) for(int i = 0; i < attackersLeft.size(); i++)
{ {
Card attacker = attackersLeft.get(i); Card attacker = attackersLeft.get(i);
@@ -428,7 +450,7 @@ public class ComputerUtil_Attack2 {
if (!attacker.hasFirstStrike() && !attacker.hasDoubleStrike()) if (!attacker.hasFirstStrike() && !attacker.hasDoubleStrike())
totalFirstStrikeBlockPower = CombatUtil.getTotalFirstStrikeBlockPower(attacker, AllZone.HumanPlayer); totalFirstStrikeBlockPower = CombatUtil.getTotalFirstStrikeBlockPower(attacker, AllZone.HumanPlayer);
if ( shouldAttack(attacker,blockers, combat) && (totalFirstStrikeBlockPower < attacker.getKillDamage() || aiAggression == 5) if (shouldAttack(attacker,blockers,combat) && (totalFirstStrikeBlockPower < attacker.getKillDamage() || aiAggression == 5)
&& CombatUtil.canAttack(attacker, combat)) && CombatUtil.canAttack(attacker, combat))
combat.addAttacker(attacker); combat.addAttacker(attacker);
} }
@@ -474,7 +496,7 @@ public class ComputerUtil_Attack2 {
for (Card defender:defenders) { for (Card defender:defenders) {
if(CombatUtil.canBlock(attacker, defender)){ //, combat )) { if(CombatUtil.canBlock(attacker, defender)){ //, combat )) {
canBeBlocked = true; canBeBlocked = true;
if(CombatUtil.canDestroyAttacker(attacker, defender)) { if(CombatUtil.canDestroyAttacker(attacker, defender, combat)) {
canBeKilledByOne = true; // there is a single creature on the battlefield that can kill the creature canBeKilledByOne = true; // there is a single creature on the battlefield that can kill the creature
// see if the defending creature is of higher or lower value. We don't want to attack only to lose value // see if the defending creature is of higher or lower value. We don't want to attack only to lose value
if(CardFactoryUtil.evaluateCreature(defender) <= CardFactoryUtil.evaluateCreature(attacker)){ if(CardFactoryUtil.evaluateCreature(defender) <= CardFactoryUtil.evaluateCreature(attacker)){
@@ -482,7 +504,7 @@ public class ComputerUtil_Attack2 {
} }
} }
// see if this attacking creature can destroy this defender, if not record that it can't kill everything // see if this attacking creature can destroy this defender, if not record that it can't kill everything
if(!CombatUtil.canDestroyBlocker(defender, attacker)){ if(!CombatUtil.canDestroyBlocker(defender, attacker, combat)){
canKillAll = false; canKillAll = false;
if(defender.getKeyword().contains("Wither") || defender.getKeyword().contains("Infect")){ if(defender.getKeyword().contains("Wither") || defender.getKeyword().contains("Infect")){
canKillAllDangerous = false; // there is a dangerous creature that can survive an attack from this creature canKillAllDangerous = false; // there is a dangerous creature that can survive an attack from this creature

View File

@@ -28,22 +28,22 @@ public class ComputerUtil_Block2
} }
//finds blockers that won't be destroyed //finds blockers that won't be destroyed
private static CardList getSafeBlockers(Card attacker, CardList blockersLeft) { private static CardList getSafeBlockers(Card attacker, CardList blockersLeft, Combat combat) {
CardList blockers = new CardList(); CardList blockers = new CardList();
for(Card b : blockersLeft) { for(Card b : blockersLeft) {
if(!CombatUtil.canDestroyBlocker(b,attacker)) blockers.add(b); if(!CombatUtil.canDestroyBlocker(b,attacker, combat)) blockers.add(b);
} }
return blockers; return blockers;
} }
//finds blockers that destroy the attacker //finds blockers that destroy the attacker
private static CardList getKillingBlockers(Card attacker, CardList blockersLeft) { private static CardList getKillingBlockers(Card attacker, CardList blockersLeft, Combat combat) {
CardList blockers = new CardList(); CardList blockers = new CardList();
for(Card b : blockersLeft) { for(Card b : blockersLeft) {
if(CombatUtil.canDestroyAttacker(attacker,b)) blockers.add(b); if(CombatUtil.canDestroyAttacker(attacker,b,combat)) blockers.add(b);
} }
return blockers; return blockers;
@@ -102,12 +102,12 @@ public class ComputerUtil_Block2
CardList blockers = getPossibleBlockers(attacker, blockersLeft, combat); CardList blockers = getPossibleBlockers(attacker, blockersLeft, combat);
CardList safeBlockers = getSafeBlockers(attacker, blockers); CardList safeBlockers = getSafeBlockers(attacker, blockers, combat);
CardList killingBlockers = new CardList(); CardList killingBlockers = new CardList();
if(safeBlockers.size() > 0) { if(safeBlockers.size() > 0) {
// 1.Blockers that can destroy the attacker but won't get destroyed // 1.Blockers that can destroy the attacker but won't get destroyed
killingBlockers = getKillingBlockers(attacker, safeBlockers); killingBlockers = getKillingBlockers(attacker, safeBlockers, combat);
if(killingBlockers.size() > 0) blocker = CardFactoryUtil.AI_getWorstCreature(killingBlockers); if(killingBlockers.size() > 0) blocker = CardFactoryUtil.AI_getWorstCreature(killingBlockers);
// 2.Blockers that won't get destroyed // 2.Blockers that won't get destroyed
@@ -117,7 +117,7 @@ public class ComputerUtil_Block2
} }
} // no safe blockers } // no safe blockers
else { else {
killingBlockers = getKillingBlockers(attacker, blockers); killingBlockers = getKillingBlockers(attacker, blockers, combat);
if(killingBlockers.size() > 0) { if(killingBlockers.size() > 0) {
// 3.Blockers that can destroy the attacker and are worth less // 3.Blockers that can destroy the attacker and are worth less
Card worst = CardFactoryUtil.AI_getWorstCreature(killingBlockers); Card worst = CardFactoryUtil.AI_getWorstCreature(killingBlockers);
@@ -183,7 +183,7 @@ public class ComputerUtil_Block2
for(Card attacker : attackersLeft) { for(Card attacker : attackersLeft) {
killingBlockers = killingBlockers =
getKillingBlockers(attacker, getPossibleBlockers(attacker, blockersLeft, combat)); getKillingBlockers(attacker, getPossibleBlockers(attacker, blockersLeft, combat), combat);
if(killingBlockers.size() > 0 && CombatUtil.lifeInDanger(combat)) { if(killingBlockers.size() > 0 && CombatUtil.lifeInDanger(combat)) {
Card blocker = CardFactoryUtil.AI_getWorstCreature(killingBlockers); Card blocker = CardFactoryUtil.AI_getWorstCreature(killingBlockers);
combat.addBlocker(attacker, blocker); combat.addBlocker(attacker, blocker);
@@ -254,7 +254,7 @@ public class ComputerUtil_Block2
blockers = getPossibleBlockers(attacker, blockersLeft, combat); blockers = getPossibleBlockers(attacker, blockersLeft, combat);
//Try to use safe blockers first //Try to use safe blockers first
safeBlockers = getSafeBlockers(attacker, blockers); safeBlockers = getSafeBlockers(attacker, blockers, combat);
for(Card blocker : safeBlockers) { for(Card blocker : safeBlockers) {
//Add an additional blocker if the current blockers are not enough and the new one would deal additional damage //Add an additional blocker if the current blockers are not enough and the new one would deal additional damage
if(attacker.getKillDamage() > CombatUtil.totalDamageOfBlockers(attacker,combat.getBlockers(attacker)) if(attacker.getKillDamage() > CombatUtil.totalDamageOfBlockers(attacker,combat.getBlockers(attacker))
@@ -358,8 +358,8 @@ public class ComputerUtil_Block2
if (CombatUtil.lifeInDanger(combat)) combat = makeChumpBlocks(combat); //choose necessary chump blocks if life is still in danger if (CombatUtil.lifeInDanger(combat)) combat = makeChumpBlocks(combat); //choose necessary chump blocks if life is still in danger
//Reinforce blockers blocking attackers with trample if life is still in danger //Reinforce blockers blocking attackers with trample if life is still in danger
if (CombatUtil.lifeInDanger(combat)) combat = reinforceBlockersAgainstTrample(combat); if (CombatUtil.lifeInDanger(combat)) combat = reinforceBlockersAgainstTrample(combat);
if (!CombatUtil.lifeInDanger(combat)) combat = makeGangBlocks(combat); combat = makeGangBlocks(combat);
if (!CombatUtil.lifeInDanger(combat)) combat = reinforceBlockersToKill(combat); combat = reinforceBlockersToKill(combat);
} }
//== 3. If the AI life would be in serious danger make an even safer approach == //== 3. If the AI life would be in serious danger make an even safer approach ==
@@ -370,9 +370,9 @@ public class ComputerUtil_Block2
if (!CombatUtil.lifeInDanger(combat)) combat = makeGoodBlocks(combat); if (!CombatUtil.lifeInDanger(combat)) combat = makeGoodBlocks(combat);
//Reinforce blockers blocking attackers with trample if life is still in danger //Reinforce blockers blocking attackers with trample if life is still in danger
if (CombatUtil.lifeInDanger(combat)) combat = reinforceBlockersAgainstTrample(combat); if (CombatUtil.lifeInDanger(combat)) combat = reinforceBlockersAgainstTrample(combat);
if (!CombatUtil.lifeInDanger(combat)) combat = makeGangBlocks(combat); combat = makeGangBlocks(combat);
//Support blockers not destroying the attacker with more blockers to try to kill the attacker //Support blockers not destroying the attacker with more blockers to try to kill the attacker
if (!CombatUtil.lifeInDanger(combat)) combat = reinforceBlockersToKill(combat); combat = reinforceBlockersToKill(combat);
} }
// assign blockers that have to block // assign blockers that have to block

View File

@@ -91,8 +91,8 @@ public class Computer_Race
CardList c = blockList; CardList c = blockList;
for(int i = 0; i < c.size(); i++) for(int i = 0; i < c.size(); i++)
if(CombatUtil.canDestroyAttacker(attacker, c.get(i)) && if(CombatUtil.canDestroyAttacker(attacker, c.get(i), null) &&
(! CombatUtil.canDestroyBlocker(c.get(i), attacker))) (! CombatUtil.canDestroyBlocker(c.get(i), attacker, null)))
return c.get(i); return c.get(i);
return null; return null;
@@ -105,7 +105,7 @@ public class Computer_Race
CardList c = blockList; CardList c = blockList;
for(int i = 0; i < c.size(); i++) for(int i = 0; i < c.size(); i++)
if(CombatUtil.canDestroyAttacker(attacker, c.get(i))) if(CombatUtil.canDestroyAttacker(attacker, c.get(i), null))
return c.get(i); return c.get(i);
return null; return null;
@@ -118,7 +118,7 @@ public class Computer_Race
CardList c = blockList; CardList c = blockList;
for(int i = 0; i < c.size(); i++) for(int i = 0; i < c.size(); i++)
if(! CombatUtil.canDestroyBlocker(c.get(i), attacker)) if(! CombatUtil.canDestroyBlocker(c.get(i), attacker, null))
return c.get(i); return c.get(i);
return null; return null;

View File

@@ -300,7 +300,7 @@ public class RunTest
Card card = cf.getCard("Sylvan Basilisk", null); Card card = cf.getCard("Sylvan Basilisk", null);
Card card2 = cf.getCard("Exalted Angel", null); Card card2 = cf.getCard("Exalted Angel", null);
check("121a", !CombatUtil.canDestroyAttacker(card, card2)); check("121a", !CombatUtil.canDestroyAttacker(card, card2, null));
} }
{ {
check("122", CardUtil.getConvertedManaCost("0") == 0); check("122", CardUtil.getConvertedManaCost("0") == 0);