From b7827f47e3df809ced6a8b0d719566d686835e85 Mon Sep 17 00:00:00 2001 From: jendave Date: Sat, 6 Aug 2011 13:32:26 +0000 Subject: [PATCH] - More little improvements to AI attack decisions. --- src/forge/CombatUtil.java | 16 +---- src/forge/ComputerUtil_Attack2.java | 106 +++++++++++++++------------- 2 files changed, 58 insertions(+), 64 deletions(-) diff --git a/src/forge/CombatUtil.java b/src/forge/CombatUtil.java index 77f22800911..1b8d114d18f 100644 --- a/src/forge/CombatUtil.java +++ b/src/forge/CombatUtil.java @@ -483,22 +483,8 @@ public class CombatUtil { } }); - int flankingMagnitude = 0; - if(attacker.getKeyword().contains("Flanking")) flankingMagnitude = attacker.getAmountOfKeyword("Flanking"); + return totalDamageOfBlockers(attacker, list); - for (Card c:list) - { - int flankingOffset = 0; - if (!c.getKeyword().contains("Flanking")) - flankingOffset = flankingMagnitude; - - if (!isDoranInPlay()) - i+= c.getNetAttack() - flankingOffset; - else - i+= c.getNetDefense() - flankingOffset; - } - - return i; } //This function take Doran and Double Strike into account diff --git a/src/forge/ComputerUtil_Attack2.java b/src/forge/ComputerUtil_Attack2.java index 55b03e7add1..8d2dbfa1382 100644 --- a/src/forge/ComputerUtil_Attack2.java +++ b/src/forge/ComputerUtil_Attack2.java @@ -69,23 +69,25 @@ public class ComputerUtil_Attack2 { //this checks to make sure that the computer player //doesn't lose when the human player attacks //this method is used by getAttackers() - public int blockersNeeded(Combat combat) + public CardList notNeededAsBlockers(CardList attackers, Combat combat) { - CardListUtil.sortAttack(humanList); - int blockersNeeded = computerList.size(); + CardList notNeededAsBlockers = new CardList(attackers.toArray()); + CardListUtil.sortAttackLowFirst(attackers); + int blockersNeeded = attackers.size(); - CardList list = getPossibleBlockers(computerList); + CardList list = getPossibleBlockers(attackers); for(int i = 0; i < list.size(); i++) { if(!doesHumanAttackAndWin(i)) { blockersNeeded= i; break; } + else notNeededAsBlockers.remove(list.get(i)); } if (blockersNeeded == list.size()) { // Human will win unless everything is kept back to block - return blockersNeeded; + return notNeededAsBlockers; } // Increase the total number of blockers needed by 1 if Finest Hour in play @@ -93,6 +95,7 @@ public class ComputerUtil_Attack2 { // In addition, if the computer guesses it needs no blockers, make sure that // it won't be surprised by Exalted int humanExaltedBonus = countExaltedBonus(AllZone.HumanPlayer); + if (humanExaltedBonus > 0) { int nFinestHours = AllZoneUtil.getPlayerCardsInPlay(AllZone.HumanPlayer, "Finest Hour").size(); @@ -108,19 +111,24 @@ public class ComputerUtil_Attack2 { 2 * humanBaseAttack: humanBaseAttack; if ((AllZone.ComputerPlayer.getLife() - 3) <= totalExaltedAttack) { // We will lose if there is an Exalted attack -- keep one blocker - if (blockersNeeded == 0) - blockersNeeded++; + if (blockersNeeded == 0 && notNeededAsBlockers.size() > 0) + notNeededAsBlockers.remove(0); // Finest Hour allows a second Exalted attack: keep a blocker for that too - if (nFinestHours > 0) - blockersNeeded++; + if (nFinestHours > 0 && notNeededAsBlockers.size() > 0) + notNeededAsBlockers.remove(0); } } } + + //re-add creatures with vigilance + for (Card c:attackers) + { + if (c.getKeyword().contains("Vigilance")) + notNeededAsBlockers.add(c); + } - if (blockersNeeded > list.size()) - blockersNeeded = list.size(); - return blockersNeeded; + return notNeededAsBlockers; } //this uses a global variable, which isn't perfect @@ -162,17 +170,22 @@ public class ComputerUtil_Attack2 { Combat combat = new Combat(); + CardList attackersLeft = new CardList(attackers.toArray()); + //Atackers that don't really have a choice - for (int i=0; i biggest) { - biggest = getAttack(attackers.get(i)); - att = attackers.get(i); + for(int i=0; i biggest) { + biggest = getAttack(attackersLeft.get(i)); + att = attackersLeft.get(i); } } if (att!= null && CombatUtil.canAttack(att, combat)) @@ -198,9 +211,9 @@ public class ComputerUtil_Attack2 { //or if the computer has 4 creatures and the player has 1 else if(doAssault() || (humanList.size() == 1 && 3 < attackers.size())) { - CardListUtil.sortAttack(attackers); - for(int i = 0; i < attackers.size(); i++) - if (CombatUtil.canAttack(attackers.get(i), combat)) combat.addAttacker(attackers.get(i)); + CardListUtil.sortAttack(attackersLeft); + for(int i = 0; i < attackersLeft.size(); i++) + if (CombatUtil.canAttack(attackersLeft.get(i), combat)) combat.addAttacker(attackersLeft.get(i)); } else @@ -209,40 +222,35 @@ public class ComputerUtil_Attack2 { //this should only happen 10% of the time when the computer //has at least 3 creatures boolean notAttack = (Math.abs(random.nextInt(100)) <= 10); - if(notAttack && 3 <= attackers.size()) + if(notAttack && 3 <= attackersLeft.size()) { - attackers.shuffle(); - attackers.remove(0); + attackersLeft.shuffle(); + attackersLeft.remove(0); } //this has to be before the sorting below //because this sorts attackers - int i = blockersNeeded(combat); //new + //int i = blockersNeeded(combat); //new //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(attackers); - CardListUtil.sortAttackLowFirst(attackers); - - for (Card c:attackers) - { - if (c.getKeyword().contains("Vigilance")) - i--; - } - if (i < 0) - i = 0; + CardListUtil.sortNonFlyingFirst(attackersLeft); + CardListUtil.sortAttackLowFirst(attackersLeft); - for(; i < attackers.size(); i++) + attackersLeft = notNeededAsBlockers(attackersLeft, combat); + + + for(int i = 0; i < attackersLeft.size(); i++) { + Card attacker = attackersLeft.get(i); int totalFirstStrikeBlockPower = 0; - if (!attackers.get(i).hasFirstStrike() && !attackers.get(i).hasDoubleStrike()) - totalFirstStrikeBlockPower = CombatUtil.getTotalFirstStrikeBlockPower(attackers.get(i), AllZone.HumanPlayer); + if (!attacker.hasFirstStrike() && !attacker.hasDoubleStrike()) + totalFirstStrikeBlockPower = CombatUtil.getTotalFirstStrikeBlockPower(attacker, AllZone.HumanPlayer); - if ( shouldAttack(attackers.get(i),blockers, combat) && totalFirstStrikeBlockPower < attackers.get(i).getKillDamage() - && CombatUtil.canAttack(attackers.get(i), combat)) - combat.addAttacker(attackers.get(i)); - + if ( shouldAttack(attacker,blockers, combat) && totalFirstStrikeBlockPower < attacker.getKillDamage() + && CombatUtil.canAttack(attacker, combat)) + combat.addAttacker(attacker); } }//getAttackers()