From 35a1b9a2655d63c9752476ead6adfb65ab0cf28f Mon Sep 17 00:00:00 2001 From: jendave Date: Sat, 6 Aug 2011 12:33:52 +0000 Subject: [PATCH] - Cleanup and updates of AI blocking. --- src/forge/CombatUtil.java | 50 ++++++++++++++++++++++++++++++ src/forge/ComputerAI_General.java | 24 +++++++++----- src/forge/ComputerUtil_Block2.java | 50 ++++++------------------------ 3 files changed, 77 insertions(+), 47 deletions(-) diff --git a/src/forge/CombatUtil.java b/src/forge/CombatUtil.java index 51d03979d1e..06960417d9c 100644 --- a/src/forge/CombatUtil.java +++ b/src/forge/CombatUtil.java @@ -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; diff --git a/src/forge/ComputerAI_General.java b/src/forge/ComputerAI_General.java index 121a2c550a9..9530bc9543e 100644 --- a/src/forge/ComputerAI_General.java +++ b/src/forge/ComputerAI_General.java @@ -198,13 +198,23 @@ public class ComputerAI_General implements Computer { public void declare_blockers() { CardList blockers = AllZoneUtil.getCreaturesInPlay(AllZone.ComputerPlayer); - AllZone.pwCombat = ComputerUtil_Block2.getBlockers(AllZone.pwCombat, blockers); - - CardList remove = AllZone.pwCombat.getAllBlockers(); - for(int i = 0; i < remove.size(); i++) - blockers.remove(remove.get(i)); - - AllZone.Combat = ComputerUtil_Block2.getBlockers(AllZone.Combat, blockers); + //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(); + for(int i = 0; i < remove.size(); i++) + blockers.remove(remove.get(i)); + + AllZone.Combat = ComputerUtil_Block2.getBlockers(AllZone.Combat, blockers); + } CombatUtil.showCombat(); diff --git a/src/forge/ComputerUtil_Block2.java b/src/forge/ComputerUtil_Block2.java index ab17783f923..ce9db19fe36 100644 --- a/src/forge/ComputerUtil_Block2.java +++ b/src/forge/ComputerUtil_Block2.java @@ -409,7 +409,7 @@ public class ComputerUtil_Block2 { return c.getNetDefense(); } - */ + //this doesn't take into account first strike, //use CombatUtil.canDestroyAttacker() @@ -425,7 +425,7 @@ public class ComputerUtil_Block2 return n; } - + private static int sumAttack(CardList attackers) { int sum = 0; @@ -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; @@ -530,13 +514,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 @@ -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 } } @@ -579,6 +552,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; @@ -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);