mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
- 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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user