mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
- AI will now predict battle cry boni.
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user