From 89c2130ff6f8c23addbd38518257fd5ff996781a Mon Sep 17 00:00:00 2001 From: moomarc Date: Mon, 17 Feb 2014 15:47:04 +0000 Subject: [PATCH] - Attempt to stop AI players in multiplayer games from always only attacking the human until dead. They will now gang up on an opponent with less than 8 life but otherwise attack a random opponent. Feel free to improve the ai. --- .../java/forge/ai/AiAttackController.java | 38 +++++++++++++------ .../main/java/forge/game/player/Player.java | 12 +++--- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiAttackController.java b/forge-ai/src/main/java/forge/ai/AiAttackController.java index 372a94a4a8d..c94639ee2a1 100644 --- a/forge-ai/src/main/java/forge/ai/AiAttackController.java +++ b/forge-ai/src/main/java/forge/ai/AiAttackController.java @@ -19,6 +19,7 @@ package forge.ai; import com.google.common.base.Predicate; import com.google.common.collect.Lists; + import forge.game.GameEntity; import forge.game.card.Card; import forge.game.card.CardLists; @@ -29,6 +30,7 @@ import forge.game.player.Player; import forge.game.trigger.Trigger; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; +import forge.util.MyRandom; import java.util.ArrayList; import java.util.List; @@ -57,6 +59,7 @@ public class AiAttackController { private List myList; // holds computer creatures private final Player ai; + private Player defendingOpponent; private int aiAggression = 0; // added by Masher, how aggressive the ai is // attack will be depending on circumstances @@ -74,22 +77,34 @@ public class AiAttackController { */ public AiAttackController(final Player ai) { this.ai = ai; - Player opponent = ai.getOpponent(); + this.defendingOpponent = choosePreferredDefenderPlayer(); this.oppList = Lists.newArrayList(); - this.oppList.addAll(opponent.getCreaturesInPlay()); + this.oppList.addAll(this.defendingOpponent.getCreaturesInPlay()); this.myList = ai.getCreaturesInPlay(); this.attackers = new ArrayList(); for (Card c : myList) { - if (CombatUtil.canAttack(c, opponent)) { + if (CombatUtil.canAttack(c, this.defendingOpponent)) { attackers.add(c); } } this.blockers = this.getPossibleBlockers(oppList, this.attackers); } // constructor + /** Choose opponent for AI to attack here. Expand as necessary. */ + private Player choosePreferredDefenderPlayer() { + Player defender = ai.getWeakestOpponent(); //Gets opponent with the least life + + if (defender.getLife() < 8) { //Concentrate on opponent within easy kill range + return defender; + } else { //Otherwise choose a random opponent to ensure no ganging up on players + defender = ai.getOpponents().get(MyRandom.getRandom().nextInt(ai.getOpponents().size())); + } + return defender; + } + /** *

* sortAttackers. @@ -140,7 +155,7 @@ public class AiAttackController { return false; } - final Player opp = ai.getOpponent(); + final Player opp = this.defendingOpponent; if (ComputerUtilCombat.damageIfUnblocked(attacker, opp, combat) > 0) { return true; } @@ -276,7 +291,7 @@ public class AiAttackController { return notNeededAsBlockers; } - final Player opp = ai.getOpponent(); + final Player opp = this.defendingOpponent; // Increase the total number of blockers needed by 1 if Finest Hour in // play @@ -384,7 +399,7 @@ public class AiAttackController { final List unblockedAttackers = new ArrayList(); final List remainingAttackers = new ArrayList(this.attackers); final List remainingBlockers = new ArrayList(this.blockers); - final Player opp = ai.getOpponent(); + final Player opp = this.defendingOpponent; for (Card attacker : attackers) { @@ -448,27 +463,28 @@ public class AiAttackController { if (defs.size() == 1) { return defs.get(0); } + Player prefDefender = (Player) (defs.contains(this.defendingOpponent) ? this.defendingOpponent : defs.get(0)); final GameEntity entity = ai.getMustAttackEntity(); if (null != entity) { int n = defs.indexOf(entity); if (-1 == n) { System.out.println("getMustAttackEntity() returned something not in defenders."); - return defs.get(0); + return prefDefender; } else { return entity; } } else { // 1. assault the opponent if you can kill him if (bAssault) { - return getDefendingPlayers(c).get(0); + return prefDefender; } // 2. attack planeswalkers List pwDefending = c.getDefendingPlaneswalkers(); if (!pwDefending.isEmpty()) { return pwDefending.get(0); } else { - return defs.get(0); + return prefDefender; } } } @@ -622,7 +638,7 @@ public class AiAttackController { aiLifeToPlayerDamageRatio = (double) ai.getLife() / candidateCounterAttackDamage; } - final Player opp = ai.getOpponent(); + final Player opp = this.defendingOpponent; // get the potential damage and strength of the AI forces final List candidateAttackers = new ArrayList(); int candidateUnblockedDamage = 0; @@ -791,7 +807,7 @@ public class AiAttackController { for (int i = 0; i < attackersLeft.size(); i++) { final Card attacker = attackersLeft.get(i); if (this.aiAggression < 5 && !attacker.hasFirstStrike() && !attacker.hasDoubleStrike() - && ComputerUtilCombat.getTotalFirstStrikeBlockPower(attacker, ai.getOpponent()) + && ComputerUtilCombat.getTotalFirstStrikeBlockPower(attacker, this.defendingOpponent) >= ComputerUtilCombat.getDamageToKill(attacker)) { continue; } diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 8ac220e2957..fe78b09cb24 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -323,18 +323,18 @@ public class Player extends GameEntity implements Comparable { * @return */ public final Player getWeakestOpponent() { - List opponnets = this.getOpponents(); - Player weakest = opponnets.get(0); - for (int i = 1; i < opponnets.size(); i++) { - if (weakest.getLife() > opponnets.get(i).getLife()) { - weakest = opponnets.get(i); + List opponents = this.getOpponents(); + Player weakest = opponents.get(0); + for (int i = 1; i < opponents.size(); i++) { + if (weakest.getLife() > opponents.get(i).getLife()) { + weakest = opponents.get(i); } } return weakest; } public boolean isOpponentOf(Player other) { - return other != this && other != null && ( other.teamNumber < 0 || other.teamNumber != this.teamNumber ); + return other != this && other != null && ( other.teamNumber < 0 || other.teamNumber != this.teamNumber ); }