- Cleanup and updates of AI blocking.

This commit is contained in:
jendave
2011-08-06 12:33:52 +00:00
parent f66dadffcb
commit 35a1b9a265
3 changed files with 77 additions and 47 deletions

View File

@@ -453,6 +453,56 @@ public class CombatUtil {
return i;
}
//This function take Doran and Double Strike into account
public static int getAttack(Card c)
{
int n = c.getNetAttack();
if(CombatUtil.isDoranInPlay())
n = c.getNetDefense();
if(c.hasDoubleStrike())
n *= 2;
return n;
}
//Checks if the life of the attacked Player/Planeswalker is in danger
public static boolean lifeInDanger(Combat combat) {
int damage = 0;
int poison = 0;
CardList attackers = new CardList(combat.getAttackers());
CardList unblocked = new CardList(combat.getAttackers());
CardList blockers = new CardList();
Card attacker = new Card();
for(int i = 0; i < attackers.size(); i++) {
attacker = attackers.get(i);
blockers = combat.getBlockers(attacker);
if(blockers.size() == 0) unblocked.add(attacker);
else if(attacker.hasKeyword("Trample") && getAttack(attacker) > CombatUtil.totalShieldDamage(attacker,blockers)) {
if(!attacker.hasKeyword("Infect"))
damage += getAttack(attacker) - CombatUtil.totalShieldDamage(attacker,blockers);
if(attacker.hasKeyword("Infect"))
poison += getAttack(attacker) - CombatUtil.totalShieldDamage(attacker,blockers);
if(attacker.hasKeyword("Poisonous"))
poison += attacker.getKeywordMagnitude("Poisonous");
}
}
if (combat.getPlaneswalker() == null) {
if (damage + 3 > AllZone.ComputerPlayer.getLife() || poison + 2 > 10 - AllZone.ComputerPlayer.getPoisonCounters())
return true;
} else {
if (damage + 1 > combat.getPlaneswalker().getCounters(Counters.LOYALTY))
return true;
}
return false;
}
public static int totalDamageOfBlockers(Card attacker, CardList defenders) {
int damage = 0;

View File

@@ -198,6 +198,15 @@ public class ComputerAI_General implements Computer {
public void declare_blockers() {
CardList blockers = AllZoneUtil.getCreaturesInPlay(AllZone.ComputerPlayer);
//If Player life is in danger protect it first
if(CombatUtil.lifeInDanger(AllZone.Combat)) {
AllZone.Combat = ComputerUtil_Block2.getBlockers(AllZone.Combat, blockers);
CardList remove = AllZone.Combat.getAllBlockers();
for(int i = 0; i < remove.size(); i++)
blockers.remove(remove.get(i));
AllZone.pwCombat = ComputerUtil_Block2.getBlockers(AllZone.pwCombat, blockers);
} else { // Otherwise protect Planeswalkers first
AllZone.pwCombat = ComputerUtil_Block2.getBlockers(AllZone.pwCombat, blockers);
CardList remove = AllZone.pwCombat.getAllBlockers();
@@ -205,6 +214,7 @@ public class ComputerAI_General implements Computer {
blockers.remove(remove.get(i));
AllZone.Combat = ComputerUtil_Block2.getBlockers(AllZone.Combat, blockers);
}
CombatUtil.showCombat();

View File

@@ -409,7 +409,7 @@ public class ComputerUtil_Block2
{
return c.getNetDefense();
}
*/
//this doesn't take into account first strike,
//use CombatUtil.canDestroyAttacker()
@@ -468,7 +468,7 @@ public class ComputerUtil_Block2
return sum;
}
*/
//finds the creatures able to block the attacker
private static CardList getPossibleBlockers(Card attacker, CardList blockersLeft) {
@@ -506,22 +506,6 @@ public class ComputerUtil_Block2
return blockers;
}
//Checks if the life of the Player/Planeswalker is in danger
private static boolean lifeInDanger(Combat combat, int anticipatedDamage, int anticipatedPoison , CardList attackersLeft) {
if (combat.getPlaneswalker() == null) {
if (anticipatedDamage + sumAttack(attackersLeft) + 3 > AllZone.ComputerPlayer.getLife()
|| anticipatedPoison + sumPoison(attackersLeft) + 2 > 10 - AllZone.ComputerPlayer.getPoisonCounters())
return true;
} else {
if (anticipatedDamage + sumAttack(attackersLeft) +1 > combat.getPlaneswalker().getCounters(Counters.LOYALTY))
return true;
}
return false;
}
public static Combat getBlockers(Combat originalCombat, CardList possibleBlockers) {
Combat combat = originalCombat;
@@ -531,13 +515,6 @@ public class ComputerUtil_Block2
if (attackers.size() == 0)
return combat;
/*
for(int i = 0; i < attackers.size(); i++) {
Card a = attackers.get(i);
combat.addAttacker(a);
}
*/
CardList attackersLeft = attackers; //keeps track of all currently unblocked attackers
CardList blockedButUnkilled = new CardList(); //keeps track of all blocked attackers that currently wouldn't be destroyed
CardList tramplingAttackers = new CardList();
@@ -546,8 +523,6 @@ public class ComputerUtil_Block2
CardList safeBlockers = new CardList();
CardList killingBlockers = new CardList();
CardList chumpBlockers = new CardList();
int anticipatedDamage = 0; //this is the anticipated damage to the computer player
int anticipatedPoison = 0; //this is the anticipated poison to the computer player
int diff = AllZone.ComputerPlayer.getLife() * 2 + 5; //This is the minimal gain for an unnecessary trade
Card a = new Card();
Card b = new Card();
@@ -560,8 +535,6 @@ public class ComputerUtil_Block2
a = attackers.get(i);
if(!CombatUtil.canBeBlocked(a)) {
attackersLeft.remove(a);
anticipatedDamage += getAttack(a);
//anticipatedPoison += a.getNetAttack(); //TODO Poison
}
}
@@ -580,6 +553,9 @@ public class ComputerUtil_Block2
//Begin with the attackers that pose the biggest thread
CardListUtil.sortAttack(attackersLeft);
//Begin with the weakest blockers
CardListUtil.sortAttackLowFirst(blockersLeft);
CardList currentAttackers = attackersLeft;
//first choose good blocks only
@@ -611,8 +587,6 @@ public class ComputerUtil_Block2
if(CardFactoryUtil.evaluateCreature(worst) + diff < CardFactoryUtil.evaluateCreature(attacker)) {
blocker = worst;
anticipatedDamage += anticipateDamage(attacker, blocker);
anticipatedPoison += anticipatePoison(attacker, blocker);
}
// TODO: 4.good Gangblocks
}
@@ -629,14 +603,12 @@ public class ComputerUtil_Block2
if(blockersLeft.size() == 0) return combat;
//choose necessary trade blocks if life is in danger
if (lifeInDanger(combat, anticipatedDamage, anticipatedPoison, attackersLeft))
if (CombatUtil.lifeInDanger(combat))
for(int i = 0; i < attackersLeft.size(); i++) {
attacker = attackersLeft.get(i);
killingBlockers = getKillingBlockers(attacker, getPossibleBlockers(attacker, blockersLeft));
if(killingBlockers.size() > 0) {
blocker = CardFactoryUtil.AI_getWorstCreature(killingBlockers);
if (attacker.hasKeyword("Trample") && getAttack(attacker) > blocker.getNetDefense())
anticipatedDamage += getAttack(attacker) - blocker.getNetDefense();
combat.addBlocker(attacker, blocker);
currentAttackers.remove(attacker);
blockersLeft.remove(blocker);
@@ -646,14 +618,12 @@ public class ComputerUtil_Block2
attackersLeft = currentAttackers;
//choose necessary chump blocks if life is still in danger
if (lifeInDanger(combat, anticipatedDamage, anticipatedPoison, attackersLeft))
if (CombatUtil.lifeInDanger(combat))
for(int i = 0; i < attackersLeft.size(); i++) {
attacker = attackersLeft.get(i);
chumpBlockers = getPossibleBlockers(attacker, blockersLeft);
if(chumpBlockers.size() > 0) {
blocker = CardFactoryUtil.AI_getWorstCreature(chumpBlockers);
if (attacker.hasKeyword("Trample") && getAttack(attacker) > blocker.getNetDefense())
anticipatedDamage += getAttack(attacker) - blocker.getNetDefense();
combat.addBlocker(attacker, blocker);
currentAttackers.remove(attacker);
blockedButUnkilled.add(attacker);
@@ -664,7 +634,7 @@ public class ComputerUtil_Block2
attackersLeft = currentAttackers;
//Reinforce blockers blocking attackers with trample if life is still in danger
if (lifeInDanger(combat, anticipatedDamage, anticipatedPoison, attackersLeft)) {
if (CombatUtil.lifeInDanger(combat)) {
tramplingAttackers = attackers.getKeyword("Trample");
tramplingAttackers = tramplingAttackers.getKeywordsDontContain("Rampage"); //Don't make it worse
for(int i = 0; i < tramplingAttackers.size(); i++) {
@@ -673,7 +643,7 @@ public class ComputerUtil_Block2
for(int j = 0; j < chumpBlockers.size(); j++) {
blocker = chumpBlockers.get(j);
//Add an additional blocker if the current blockers are not enough and the new one would suck some of the damage
if(getAttack(attacker) > CombatUtil.totalShieldDamage(attacker,combat.getBlockers(attacker))
if(CombatUtil.getAttack(attacker) > CombatUtil.totalShieldDamage(attacker,combat.getBlockers(attacker))
&& CombatUtil.shieldDamage(attacker, blocker) > 0) {
combat.addBlocker(attacker, blocker);
blockersLeft.remove(blocker);