- 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.

This commit is contained in:
moomarc
2014-02-17 15:47:04 +00:00
parent 9d90ca99cb
commit 89c2130ff6
2 changed files with 33 additions and 17 deletions

View File

@@ -19,6 +19,7 @@ package forge.ai;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardLists; import forge.game.card.CardLists;
@@ -29,6 +30,7 @@ import forge.game.player.Player;
import forge.game.trigger.Trigger; import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerType; import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -57,6 +59,7 @@ public class AiAttackController {
private List<Card> myList; // holds computer creatures private List<Card> myList; // holds computer creatures
private final Player ai; private final Player ai;
private Player defendingOpponent;
private int aiAggression = 0; // added by Masher, how aggressive the ai is private int aiAggression = 0; // added by Masher, how aggressive the ai is
// attack will be depending on circumstances // attack will be depending on circumstances
@@ -74,22 +77,34 @@ public class AiAttackController {
*/ */
public AiAttackController(final Player ai) { public AiAttackController(final Player ai) {
this.ai = ai; this.ai = ai;
Player opponent = ai.getOpponent(); this.defendingOpponent = choosePreferredDefenderPlayer();
this.oppList = Lists.newArrayList(); this.oppList = Lists.newArrayList();
this.oppList.addAll(opponent.getCreaturesInPlay()); this.oppList.addAll(this.defendingOpponent.getCreaturesInPlay());
this.myList = ai.getCreaturesInPlay(); this.myList = ai.getCreaturesInPlay();
this.attackers = new ArrayList<Card>(); this.attackers = new ArrayList<Card>();
for (Card c : myList) { for (Card c : myList) {
if (CombatUtil.canAttack(c, opponent)) { if (CombatUtil.canAttack(c, this.defendingOpponent)) {
attackers.add(c); attackers.add(c);
} }
} }
this.blockers = this.getPossibleBlockers(oppList, this.attackers); this.blockers = this.getPossibleBlockers(oppList, this.attackers);
} // constructor } // 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;
}
/** /**
* <p> * <p>
* sortAttackers. * sortAttackers.
@@ -140,7 +155,7 @@ public class AiAttackController {
return false; return false;
} }
final Player opp = ai.getOpponent(); final Player opp = this.defendingOpponent;
if (ComputerUtilCombat.damageIfUnblocked(attacker, opp, combat) > 0) { if (ComputerUtilCombat.damageIfUnblocked(attacker, opp, combat) > 0) {
return true; return true;
} }
@@ -276,7 +291,7 @@ public class AiAttackController {
return notNeededAsBlockers; 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 // Increase the total number of blockers needed by 1 if Finest Hour in
// play // play
@@ -384,7 +399,7 @@ public class AiAttackController {
final List<Card> unblockedAttackers = new ArrayList<Card>(); final List<Card> unblockedAttackers = new ArrayList<Card>();
final List<Card> remainingAttackers = new ArrayList<Card>(this.attackers); final List<Card> remainingAttackers = new ArrayList<Card>(this.attackers);
final List<Card> remainingBlockers = new ArrayList<Card>(this.blockers); final List<Card> remainingBlockers = new ArrayList<Card>(this.blockers);
final Player opp = ai.getOpponent(); final Player opp = this.defendingOpponent;
for (Card attacker : attackers) { for (Card attacker : attackers) {
@@ -448,27 +463,28 @@ public class AiAttackController {
if (defs.size() == 1) { if (defs.size() == 1) {
return defs.get(0); return defs.get(0);
} }
Player prefDefender = (Player) (defs.contains(this.defendingOpponent) ? this.defendingOpponent : defs.get(0));
final GameEntity entity = ai.getMustAttackEntity(); final GameEntity entity = ai.getMustAttackEntity();
if (null != entity) { if (null != entity) {
int n = defs.indexOf(entity); int n = defs.indexOf(entity);
if (-1 == n) { if (-1 == n) {
System.out.println("getMustAttackEntity() returned something not in defenders."); System.out.println("getMustAttackEntity() returned something not in defenders.");
return defs.get(0); return prefDefender;
} else { } else {
return entity; return entity;
} }
} else { } else {
// 1. assault the opponent if you can kill him // 1. assault the opponent if you can kill him
if (bAssault) { if (bAssault) {
return getDefendingPlayers(c).get(0); return prefDefender;
} }
// 2. attack planeswalkers // 2. attack planeswalkers
List<Card> pwDefending = c.getDefendingPlaneswalkers(); List<Card> pwDefending = c.getDefendingPlaneswalkers();
if (!pwDefending.isEmpty()) { if (!pwDefending.isEmpty()) {
return pwDefending.get(0); return pwDefending.get(0);
} else { } else {
return defs.get(0); return prefDefender;
} }
} }
} }
@@ -622,7 +638,7 @@ public class AiAttackController {
aiLifeToPlayerDamageRatio = (double) ai.getLife() / candidateCounterAttackDamage; 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 // get the potential damage and strength of the AI forces
final List<Card> candidateAttackers = new ArrayList<Card>(); final List<Card> candidateAttackers = new ArrayList<Card>();
int candidateUnblockedDamage = 0; int candidateUnblockedDamage = 0;
@@ -791,7 +807,7 @@ public class AiAttackController {
for (int i = 0; i < attackersLeft.size(); i++) { for (int i = 0; i < attackersLeft.size(); i++) {
final Card attacker = attackersLeft.get(i); final Card attacker = attackersLeft.get(i);
if (this.aiAggression < 5 && !attacker.hasFirstStrike() && !attacker.hasDoubleStrike() if (this.aiAggression < 5 && !attacker.hasFirstStrike() && !attacker.hasDoubleStrike()
&& ComputerUtilCombat.getTotalFirstStrikeBlockPower(attacker, ai.getOpponent()) && ComputerUtilCombat.getTotalFirstStrikeBlockPower(attacker, this.defendingOpponent)
>= ComputerUtilCombat.getDamageToKill(attacker)) { >= ComputerUtilCombat.getDamageToKill(attacker)) {
continue; continue;
} }

View File

@@ -323,18 +323,18 @@ public class Player extends GameEntity implements Comparable<Player> {
* @return * @return
*/ */
public final Player getWeakestOpponent() { public final Player getWeakestOpponent() {
List<Player> opponnets = this.getOpponents(); List<Player> opponents = this.getOpponents();
Player weakest = opponnets.get(0); Player weakest = opponents.get(0);
for (int i = 1; i < opponnets.size(); i++) { for (int i = 1; i < opponents.size(); i++) {
if (weakest.getLife() > opponnets.get(i).getLife()) { if (weakest.getLife() > opponents.get(i).getLife()) {
weakest = opponnets.get(i); weakest = opponents.get(i);
} }
} }
return weakest; return weakest;
} }
public boolean isOpponentOf(Player other) { 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 );
} }