package games.strategy.triplea.ai;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.RelationshipType;
import games.strategy.triplea.attachments.ICondition;
import games.strategy.triplea.attachments.PoliticalActionAttachment;
import games.strategy.triplea.delegate.AbstractEndTurnDelegate;
import games.strategy.triplea.delegate.Matches;
import games.strategy.util.Match;
/**
* Basic utility methods to handle basic AI stuff for Politics this AI always
* tries to get from Neutral to War with state if it is free with everyone this
* AI will not go through a different Neutral state to reach a War state. (ie go
* from NAP to Peace to War)
*/
public class AIPoliticalUtils {
public static List<PoliticalActionAttachment> getPoliticalActionsTowardsWar(final PlayerID id,
final HashMap<ICondition, Boolean> testedConditions, final GameData data) {
final List<PoliticalActionAttachment> acceptableActions = new ArrayList<>();
for (final PoliticalActionAttachment nextAction : PoliticalActionAttachment.getValidActions(id, testedConditions,
data)) {
if (wantToPerFormActionTowardsWar(nextAction, id, data)) {
acceptableActions.add(nextAction);
}
}
return acceptableActions;
}
public static List<PoliticalActionAttachment> getPoliticalActionsOther(final PlayerID id,
final HashMap<ICondition, Boolean> testedConditions, final GameData data) {
final List<PoliticalActionAttachment> warActions = getPoliticalActionsTowardsWar(id, testedConditions, data);
final List<PoliticalActionAttachment> acceptableActions = new ArrayList<>();
final Collection<PoliticalActionAttachment> validActions =
PoliticalActionAttachment.getValidActions(id, testedConditions, data);
validActions.removeAll(warActions);
for (final PoliticalActionAttachment nextAction : validActions) {
if (warActions.contains(nextAction)) {
continue;
}
if (goesTowardsWar(nextAction, id, data) && Math.random() < .5) {
continue;
}
if (awayFromAlly(nextAction, id, data) && Math.random() < .9) {
continue;
}
if (isFree(nextAction)) {
acceptableActions.add(nextAction);
} else if (Match.countMatches(validActions, Matches.PoliticalActionHasCostBetween(0, 0)) > 1) {
if (Math.random() < .9 && isAcceptableCost(nextAction, id, data)) {
acceptableActions.add(nextAction);
}
} else {
if (Math.random() < .4 && isAcceptableCost(nextAction, id, data)) {
acceptableActions.add(nextAction);
}
}
}
return acceptableActions;
}
private static boolean wantToPerFormActionTowardsWar(final PoliticalActionAttachment nextAction, final PlayerID id,
final GameData data) {
return isFree(nextAction) && goesTowardsWar(nextAction, id, data);
}
// this code has a rare risk of circular loop actions.. depending on the map
// designer
// only switches from a Neutral to an War state... won't go through
// in-between neutral states
// TODO have another look at this part.
private static boolean goesTowardsWar(final PoliticalActionAttachment nextAction, final PlayerID p0,
final GameData data) {
for (final String relationshipChangeString : nextAction.getRelationshipChange()) {
final String[] relationshipChange = relationshipChangeString.split(":");
final PlayerID p1 = data.getPlayerList().getPlayerID(relationshipChange[0]);
final PlayerID p2 = data.getPlayerList().getPlayerID(relationshipChange[1]);
// only continue if p1 or p2 is the AI
if (p0.equals(p1) || p0.equals(p2)) {
final RelationshipType currentType = data.getRelationshipTracker().getRelationshipType(p1, p2);
final RelationshipType newType = data.getRelationshipTypeList().getRelationshipType(relationshipChange[2]);
if (currentType.getRelationshipTypeAttachment().isNeutral()
&& newType.getRelationshipTypeAttachment().isWar()) {
return true;
}
}
}
return false;
}
private static boolean awayFromAlly(final PoliticalActionAttachment nextAction, final PlayerID p0,
final GameData data) {
for (final String relationshipChangeString : nextAction.getRelationshipChange()) {
final String[] relationshipChange = relationshipChangeString.split(":");
final PlayerID p1 = data.getPlayerList().getPlayerID(relationshipChange[0]);
final PlayerID p2 = data.getPlayerList().getPlayerID(relationshipChange[1]);
// only continue if p1 or p2 is the AI
if (p0.equals(p1) || p0.equals(p2)) {
final RelationshipType currentType = data.getRelationshipTracker().getRelationshipType(p1, p2);
final RelationshipType newType = data.getRelationshipTypeList().getRelationshipType(relationshipChange[2]);
if (currentType.getRelationshipTypeAttachment().isAllied()
&& (newType.getRelationshipTypeAttachment().isNeutral()
|| newType.getRelationshipTypeAttachment().isWar())) {
return true;
}
}
}
return false;
}
private static boolean isFree(final PoliticalActionAttachment nextAction) {
return nextAction.getCostPU() <= 0;
}
private static boolean isAcceptableCost(final PoliticalActionAttachment nextAction, final PlayerID player,
final GameData data) {
// if we have 21 or more PUs and the cost of the action is l0% or less of our total money, then it is an acceptable
// price.
final float production = AbstractEndTurnDelegate.getProduction(data.getMap().getTerritoriesOwnedBy(player), data);
return production >= 21 && (nextAction.getCostPU()) <= ((production / 10));
}
}