Package net.sf.colossus.ai
Class SimpleAI
- java.lang.Object
-
- net.sf.colossus.ai.AbstractAI
-
- net.sf.colossus.ai.SimpleAI
-
- All Implemented Interfaces:
AI
- Direct Known Subclasses:
CowardSimpleAI
,ExperimentalAI
,RationalAI
public class SimpleAI extends AbstractAI
Simple implementation of a Titan AI TODO somehow we call client.getOwningPlayer() a lot -- there should probably be a better link between AI and player, after all the AI either IS_A player or PLAYS_FOR a player- Author:
- Bruce Sherrod, David Ripton, Romain Dolbeau
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description protected class
SimpleAI.PowerSkill
private static class
SimpleAI.TerrainBonuses
Stores the skill and power bonuses for a single terrain.protected class
SimpleAI.TriggerTimeIsUp
-
Nested classes/interfaces inherited from class net.sf.colossus.ai.AbstractAI
AbstractAI.AbstractAIOracle, AbstractAI.CreatureValueConstants, AbstractAI.MoveInfo
-
-
Field Summary
Fields Modifier and Type Field Description private static int
DRAW
private static java.util.logging.Logger
LOGGER
private static int
LOSE
private static int
LOSE_BUT_INFLICT_HEAVY_LOSSES
private int
MAX_LEGION_MOVES
protected static int
MIN_ITERATIONS
private java.util.List<java.lang.String>
remainingMarkers
private int
splitsAcked
private int
splitsDone
private static java.util.Map<java.lang.String,SimpleAI.TerrainBonuses>
TERRAIN_BONUSES
Maps the terrain names to their matching bonuses.(package private) boolean
timeIsUp
protected int
timeLimit
private static int
WIN_WITH_HEAVY_LOSSES
private static int
WIN_WITH_MINIMAL_LOSSES
-
Fields inherited from class net.sf.colossus.ai.AbstractAI
bec, client, cvc, hintSectionUsed, random, variant
-
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description CreatureType
acquireAngel(Legion legion, java.util.List<CreatureType> angels)
choose whether to acquire an angel or archangeljava.util.List<CritterMove>
battleMove()
Return a list of critter moves, in best move order.private SimpleAI.PowerSkill
calcBonus(CreatureType creature, java.lang.String terrain, boolean defender)
private java.util.List<CreatureType>
chooseCreaturesToSplitOut(Legion legion)
Decide how to split this legion, and return a list of Creatures to remove.(package private) CreatureType
chooseRecruit(LegionClientSide legion, MasterHex hex, boolean considerReservations)
private java.util.List<CreatureType>
CMUsplit(boolean favorTitan, CreatureType splitCreature, CreatureType nonsplitCreature, MasterHex hex)
Keep the gargoyles together.boolean
concede(Legion legion, Legion enemy)
choose whether legion should concede to enemy(package private) java.util.List<CreatureType>
doInitialGameSplit(MasterHex hex)
Return a list of exactly four creatures (including one lord) to split out.private boolean
doMove(Legion legion, MasterHex hex)
private int
estimateBattleResults(Legion attacker, boolean attackerSplitsBeforeBattle, Legion defender, MasterHex hex)
private int
estimateBattleResults(Legion attacker, boolean attackerSplitsBeforeBattle, Legion defender, MasterHex hex, CreatureType recruit)
private int
estimateBattleResults(Legion attacker, Legion defender, MasterHex hex)
private int
evaluateCritterMove(BattleCritter critter, java.util.Map<BattleHex,java.lang.Integer> strikeMap, ValueRecorder value)
strikeMap is optionalprivate void
evaluateCritterMove_Attacker(BattleCritter critter, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, LegionClientSide legion, int turn)
this compute for non-titan attacking critterprotected void
evaluateCritterMove_Defender(BattleCritter critter, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, LegionClientSide legion, int turn)
this compute for non-titan defending critterprotected void
evaluateCritterMove_Rangestrike(BattleCritter critter, java.util.Map<BattleHex,java.lang.Integer> strikeMap, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, int power, int skill, LegionClientSide legion, int turn, java.util.Set<BattleHex> targetHexes)
protected void
evaluateCritterMove_Strike(BattleCritter critter, java.util.Map<BattleHex,java.lang.Integer> strikeMap, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, int power, int skill, LegionClientSide legion, int turn, java.util.Set<BattleHex> targetHexes)
private void
evaluateCritterMove_Terrain(BattleCritter critter, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, int power, int skill)
This compute the influence of terrainprotected void
evaluateCritterMove_Titan(BattleCritter critter, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, Legion legion, int turn)
this compute the special case of the Titan critterprivate int
evaluateEngagement(MasterHex hex)
protected int
evaluateLegionBattleMove(LegionMove lm)
protected int
evaluateLegionBattleMoveAsAWhole(LegionMove lm, java.util.Map<BattleHex,java.lang.Integer> strikeMap, ValueRecorder value)
private int
evaluateMove(LegionClientSide legion, MasterHex hex, boolean moved, java.util.Map<MasterHex,java.util.List<Legion>>[] enemyAttackMap, ValueRecorder value)
cheap, inaccurate evaluation function.private java.util.Collection<LegionMove>
findBattleMoves()
private java.util.List<CritterMove>
findBattleMovesOneCritter(BattleCritter critter)
private BattleCritter
findBestAttacker(BattleCritter target)
protected LegionMove
findBestLegionMove(java.util.Collection<LegionMove> legionMoves)
Evaluate all legion moves in the list, and return the best one.private BattleCritter
findBestTarget()
(package private) java.util.Collection<LegionMove>
findLegionMoves(java.util.List<java.util.List<CritterMove>> allCritterMoves)
allCritterMoves is a List of sorted MoveLists.private java.util.List<CritterMove>
findMoveOrder(LegionMove lm)
(package private) java.util.List<CreatureType>
findWeakestTwoCritters(LegionClientSide legion)
Find the two weakest creatures in a legion according toboolean
flee(Legion legion, Legion enemy)
choose whether legion should flee from enemyprivate CreatureType
getBestCreature(java.util.List<CreatureType> creatures)
Return the most important Creature in the list of Creatures.private static int
getCombatValue(BattleCritter battleUnit, MasterBoardTerrain terrain)
private int
getCombatValue(Legion legion, MasterBoardTerrain terrain)
private int
getCombatValue(CreatureType creature, MasterBoardTerrain terrain)
XXX Inaccurate for titans.protected int
getCreatureMoveLimit()
Find the maximum number of moves per creature to test, such that numMobileCreaturesInLegion ^ N <= LEGION_MOVE_LIMIT, but we must have at least as many moves as mobile creatures to ensure that every creature has somewhere to go.protected SimpleAI.PowerSkill
getNativeValue(CreatureType creature, MasterBoardTerrain terrain, boolean defender)
private int
getTitanCombatValue(int power)
void
handleCarries(int carryDamage, java.util.Set<java.lang.String> carryTargets)
Apply carries first to the biggest creature that could be killed with them, then to the biggest creature.private boolean
handleForcedSingleMove(Player player, java.util.Map<Legion,java.util.List<AbstractAI.MoveInfo>> moveMap)
private boolean
handleForcedSplitMoves(Player player, java.util.Map<Legion,java.util.List<AbstractAI.MoveInfo>> moveMap)
Return true if we moved something.(package private) boolean
handleMulligans(Player player)
Take a mulligan if roll is 2 or 5 in first turn, and can still take a mulligan.private boolean
handleVoluntaryMoves(PlayerClientSide player, java.util.Map<Legion,java.util.List<AbstractAI.MoveInfo>> moveMap, java.util.Map<MasterHex,java.util.List<Legion>>[] enemyAttackMap)
Return true if we moved something.boolean
masterMove()
Do a masterboard move (or consider taking mulligan, if feasible).private java.util.List<CreatureType>
MITsplit(boolean favorTitan, CreatureType splitCreature, CreatureType nonsplitCreature, MasterHex hex)
Split the gargoyles.void
muster()
make recruits for current playerPlayerColor
pickColor(java.util.List<PlayerColor> colors, java.util.List<PlayerColor> favoriteColors)
pick a color of legion markersMasterHex
pickEngagement()
pick an engagement to resolveEntrySide
pickEntrySide(MasterHex hex, Legion legion, java.util.Set<EntrySide> entrySides)
pick an entry sidejava.lang.String
pickMarker(java.util.Set<java.lang.String> markerIds, java.lang.String preferredShortColor)
pick a legion markerjava.lang.String
pickStrikePenalty(java.util.List<java.lang.String> choices)
Pick one of the list of String strike penalty options.private java.util.List<java.lang.String>
prepareMarkers(java.util.Set<java.lang.String> markerIds, java.lang.String preferredShortColor)
(package private) double
RATIO_DRAW()
(package private) double
RATIO_LOSE_HEAVY_LOSS()
(package private) double
RATIO_WIN_HEAVY_LOSS()
(package private) double
RATIO_WIN_MINIMAL_LOSS()
void
reinforce(Legion legion)
pick one reinforcement for legionvoid
retryFailedBattleMoves(java.util.List<CritterMove> bestMoveOrder)
Try another move for creatures whose moves failed.(package private) java.util.Timer
setupTimer()
boolean
split()
make splits for current player.boolean
splitCallback(Legion parent, Legion child)
Unused in this AI; just return true to indicate done.private void
splitOneLegion(Player player, Legion legion)
boolean
strike(Legion legion)
Simple one-ply group strike algorithm.SummonInfo
summonAngel(Legion summoner, java.util.List<Legion> donors)
Return a SummonInfo object, containing the summoner, donor and unittype.private int
testMoveOrder(java.util.List<CritterMove> order, java.util.List<CritterMove> newOrder)
Try each of the moves in order.-
Methods inherited from class net.sf.colossus.ai.AbstractAI
buildEnemyAttackMap, cleanupBattle, couldRecruitUp, countCreatureAccrossAllLegionFromPlayer, findStrikeMap, generateDamageMap, generateLegionMoves, getAcqStepValue, getBattleStrike, getBattleUnit, getCaretaker, getHintedRecruitmentValue, getHintedRecruitmentValueNonTitan, getHintedRecruitmentValueNonTitan, getInitialSplitHint, getKillValue, getKillValue, getNumberOfWaysToTerrain, getVariantRecruitHint, hasOpponentNativeCreature, initBattle, isHumanLegion, makeLegionMove, rangeToClosestOpponent, setVariant
-
-
-
-
Field Detail
-
LOGGER
private static final java.util.logging.Logger LOGGER
-
TERRAIN_BONUSES
private static final java.util.Map<java.lang.String,SimpleAI.TerrainBonuses> TERRAIN_BONUSES
Maps the terrain names to their matching bonuses. Only the terrains that have bonuses are in this map, so users have to expect to retrieve null values. Note that the terrain names include names for master board and hazard terrains, so it can be used for lookup up either type. TODO there seems to be some overlap withHazardTerrain.isNativeBonusTerrain()
andHazardTerrain.isNonNativePenaltyTerrain()
. This is a Map. TODO: this shouldn't be here, this is a property of the Variant player (well, not yet for Hazard, but it should be, someday). Actually, this doesn't make sense to me (RD). tower has bonus for both attacker & defender (because of walls, I assume), but is special- cased for attacker & defender. Brush and Jungle assumes Brushes, but Jungle has Tree, too. And the comments themselves makes clear that 'Sand' is actually 'Slope', but mixing up Attacker & Native and Defender & non-native. This and calcBonus should be reviewed thoroughly.
-
timeLimit
protected int timeLimit
-
timeIsUp
boolean timeIsUp
-
splitsDone
private int splitsDone
-
splitsAcked
private int splitsAcked
-
remainingMarkers
private java.util.List<java.lang.String> remainingMarkers
-
WIN_WITH_MINIMAL_LOSSES
private static final int WIN_WITH_MINIMAL_LOSSES
- See Also:
- Constant Field Values
-
WIN_WITH_HEAVY_LOSSES
private static final int WIN_WITH_HEAVY_LOSSES
- See Also:
- Constant Field Values
-
DRAW
private static final int DRAW
- See Also:
- Constant Field Values
-
LOSE_BUT_INFLICT_HEAVY_LOSSES
private static final int LOSE_BUT_INFLICT_HEAVY_LOSSES
- See Also:
- Constant Field Values
-
LOSE
private static final int LOSE
- See Also:
- Constant Field Values
-
MAX_LEGION_MOVES
private final int MAX_LEGION_MOVES
- See Also:
- Constant Field Values
-
MIN_ITERATIONS
protected static final int MIN_ITERATIONS
- See Also:
- Constant Field Values
-
-
Constructor Detail
-
SimpleAI
public SimpleAI(Client client)
-
-
Method Detail
-
pickColor
public PlayerColor pickColor(java.util.List<PlayerColor> colors, java.util.List<PlayerColor> favoriteColors)
Description copied from interface:AI
pick a color of legion markers
-
prepareMarkers
private java.util.List<java.lang.String> prepareMarkers(java.util.Set<java.lang.String> markerIds, java.lang.String preferredShortColor)
-
pickMarker
public java.lang.String pickMarker(java.util.Set<java.lang.String> markerIds, java.lang.String preferredShortColor)
Description copied from interface:AI
pick a legion marker
-
muster
public void muster()
Description copied from interface:AI
make recruits for current player
-
reinforce
public void reinforce(Legion legion)
Description copied from interface:AI
pick one reinforcement for legion
-
chooseRecruit
CreatureType chooseRecruit(LegionClientSide legion, MasterHex hex, boolean considerReservations)
-
split
public boolean split()
Description copied from interface:AI
make splits for current player. Return true if done
-
splitCallback
public boolean splitCallback(Legion parent, Legion child)
Unused in this AI; just return true to indicate done.
-
chooseCreaturesToSplitOut
private java.util.List<CreatureType> chooseCreaturesToSplitOut(Legion legion)
Decide how to split this legion, and return a list of Creatures to remove.
-
findWeakestTwoCritters
java.util.List<CreatureType> findWeakestTwoCritters(LegionClientSide legion)
Find the two weakest creatures in a legion according to
-
doInitialGameSplit
java.util.List<CreatureType> doInitialGameSplit(MasterHex hex)
Return a list of exactly four creatures (including one lord) to split out.
-
CMUsplit
private java.util.List<CreatureType> CMUsplit(boolean favorTitan, CreatureType splitCreature, CreatureType nonsplitCreature, MasterHex hex)
Keep the gargoyles together.
-
MITsplit
private java.util.List<CreatureType> MITsplit(boolean favorTitan, CreatureType splitCreature, CreatureType nonsplitCreature, MasterHex hex)
Split the gargoyles.
-
masterMove
public boolean masterMove()
Do a masterboard move (or consider taking mulligan, if feasible). Returns true if we need to run this method again after the server updates the client with the results of a move or mulligan.
-
handleMulligans
boolean handleMulligans(Player player)
Take a mulligan if roll is 2 or 5 in first turn, and can still take a mulligan. Returns true if AI took a mulligan, false otherwise.
-
handleVoluntaryMoves
private boolean handleVoluntaryMoves(PlayerClientSide player, java.util.Map<Legion,java.util.List<AbstractAI.MoveInfo>> moveMap, java.util.Map<MasterHex,java.util.List<Legion>>[] enemyAttackMap)
Return true if we moved something.
-
handleForcedSplitMoves
private boolean handleForcedSplitMoves(Player player, java.util.Map<Legion,java.util.List<AbstractAI.MoveInfo>> moveMap)
Return true if we moved something.
-
handleForcedSingleMove
private boolean handleForcedSingleMove(Player player, java.util.Map<Legion,java.util.List<AbstractAI.MoveInfo>> moveMap)
-
evaluateMove
private int evaluateMove(LegionClientSide legion, MasterHex hex, boolean moved, java.util.Map<MasterHex,java.util.List<Legion>>[] enemyAttackMap, ValueRecorder value)
cheap, inaccurate evaluation function. Returns a value for moving this legion to this hex. The value defines a distance metric over the set of all possible moves. TODO: should be parameterized with weights TODO: the hex parameter is probably not needed anymore now that we pass the legion instead of just the marker [RD: actually, handleVoluntaryMove sees to call this one with several different hexes, so we probably can't remove it]
-
RATIO_WIN_MINIMAL_LOSS
double RATIO_WIN_MINIMAL_LOSS()
-
RATIO_WIN_HEAVY_LOSS
double RATIO_WIN_HEAVY_LOSS()
-
RATIO_DRAW
double RATIO_DRAW()
-
RATIO_LOSE_HEAVY_LOSS
double RATIO_LOSE_HEAVY_LOSS()
-
estimateBattleResults
private int estimateBattleResults(Legion attacker, Legion defender, MasterHex hex)
-
estimateBattleResults
private int estimateBattleResults(Legion attacker, boolean attackerSplitsBeforeBattle, Legion defender, MasterHex hex)
-
estimateBattleResults
private int estimateBattleResults(Legion attacker, boolean attackerSplitsBeforeBattle, Legion defender, MasterHex hex, CreatureType recruit)
-
pickEntrySide
public EntrySide pickEntrySide(MasterHex hex, Legion legion, java.util.Set<EntrySide> entrySides)
Description copied from interface:AI
pick an entry side
-
pickEngagement
public MasterHex pickEngagement()
Description copied from interface:AI
pick an engagement to resolve
-
evaluateEngagement
private int evaluateEngagement(MasterHex hex)
-
flee
public boolean flee(Legion legion, Legion enemy)
Description copied from interface:AI
choose whether legion should flee from enemy
-
concede
public boolean concede(Legion legion, Legion enemy)
Description copied from interface:AI
choose whether legion should concede to enemy
-
acquireAngel
public CreatureType acquireAngel(Legion legion, java.util.List<CreatureType> angels)
Description copied from interface:AI
choose whether to acquire an angel or archangel
-
getBestCreature
private CreatureType getBestCreature(java.util.List<CreatureType> creatures)
Return the most important Creature in the list of Creatures.
-
summonAngel
public SummonInfo summonAngel(Legion summoner, java.util.List<Legion> donors)
Return a SummonInfo object, containing the summoner, donor and unittype.
-
findBestTarget
private BattleCritter findBestTarget()
-
findBestAttacker
private BattleCritter findBestAttacker(BattleCritter target)
-
handleCarries
public void handleCarries(int carryDamage, java.util.Set<java.lang.String> carryTargets)
Apply carries first to the biggest creature that could be killed with them, then to the biggest creature. carryTargets are hexLabel description strings.
-
pickStrikePenalty
public java.lang.String pickStrikePenalty(java.util.List<java.lang.String> choices)
Pick one of the list of String strike penalty options.
-
strike
public boolean strike(Legion legion)
Simple one-ply group strike algorithm. Return false if there were no strike targets.
-
getCombatValue
private static int getCombatValue(BattleCritter battleUnit, MasterBoardTerrain terrain)
-
getCombatValue
private int getCombatValue(CreatureType creature, MasterBoardTerrain terrain)
XXX Inaccurate for titans.
-
getTitanCombatValue
private int getTitanCombatValue(int power)
-
getCombatValue
private int getCombatValue(Legion legion, MasterBoardTerrain terrain)
-
calcBonus
private SimpleAI.PowerSkill calcBonus(CreatureType creature, java.lang.String terrain, boolean defender)
-
getNativeValue
protected SimpleAI.PowerSkill getNativeValue(CreatureType creature, MasterBoardTerrain terrain, boolean defender)
-
battleMove
public java.util.List<CritterMove> battleMove()
Return a list of critter moves, in best move order.
-
retryFailedBattleMoves
public void retryFailedBattleMoves(java.util.List<CritterMove> bestMoveOrder)
Try another move for creatures whose moves failed.
-
findMoveOrder
private java.util.List<CritterMove> findMoveOrder(LegionMove lm)
-
testMoveOrder
private int testMoveOrder(java.util.List<CritterMove> order, java.util.List<CritterMove> newOrder)
Try each of the moves in order. Return the number that succeed, scaled by the importance of each critter. In newOrder, if not null, place the moves that are valid.
-
getCreatureMoveLimit
protected int getCreatureMoveLimit()
Find the maximum number of moves per creature to test, such that numMobileCreaturesInLegion ^ N <= LEGION_MOVE_LIMIT, but we must have at least as many moves as mobile creatures to ensure that every creature has somewhere to go.
-
findBattleMoves
private java.util.Collection<LegionMove> findBattleMoves()
-
findBattleMovesOneCritter
private java.util.List<CritterMove> findBattleMovesOneCritter(BattleCritter critter)
-
setupTimer
java.util.Timer setupTimer()
-
findBestLegionMove
protected LegionMove findBestLegionMove(java.util.Collection<LegionMove> legionMoves)
Evaluate all legion moves in the list, and return the best one. Break out early if the time limit is exceeded.
-
findLegionMoves
java.util.Collection<LegionMove> findLegionMoves(java.util.List<java.util.List<CritterMove>> allCritterMoves)
allCritterMoves is a List of sorted MoveLists. A MoveList is a sorted List of CritterMoves for one critter. Return a sorted List of LegionMoves. A LegionMove is a List of one CritterMove per mobile critter in the legion, where no two critters move to the same hex.
-
evaluateLegionBattleMoveAsAWhole
protected int evaluateLegionBattleMoveAsAWhole(LegionMove lm, java.util.Map<BattleHex,java.lang.Integer> strikeMap, ValueRecorder value)
-
evaluateCritterMove_Titan
protected void evaluateCritterMove_Titan(BattleCritter critter, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, Legion legion, int turn)
this compute the special case of the Titan critter
-
evaluateCritterMove_Terrain
private void evaluateCritterMove_Terrain(BattleCritter critter, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, int power, int skill)
This compute the influence of terrain
-
evaluateCritterMove_Attacker
private void evaluateCritterMove_Attacker(BattleCritter critter, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, LegionClientSide legion, int turn)
this compute for non-titan attacking critter
-
evaluateCritterMove_Defender
protected void evaluateCritterMove_Defender(BattleCritter critter, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, LegionClientSide legion, int turn)
this compute for non-titan defending critter
-
evaluateCritterMove_Rangestrike
protected void evaluateCritterMove_Rangestrike(BattleCritter critter, java.util.Map<BattleHex,java.lang.Integer> strikeMap, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, int power, int skill, LegionClientSide legion, int turn, java.util.Set<BattleHex> targetHexes)
-
evaluateCritterMove_Strike
protected void evaluateCritterMove_Strike(BattleCritter critter, java.util.Map<BattleHex,java.lang.Integer> strikeMap, ValueRecorder value, MasterBoardTerrain terrain, BattleHex hex, int power, int skill, LegionClientSide legion, int turn, java.util.Set<BattleHex> targetHexes)
-
evaluateCritterMove
private int evaluateCritterMove(BattleCritter critter, java.util.Map<BattleHex,java.lang.Integer> strikeMap, ValueRecorder value)
strikeMap is optional
-
evaluateLegionBattleMove
protected int evaluateLegionBattleMove(LegionMove lm)
-
-