1
package games.strategy.triplea.baseAI;
4
import java.util.logging.*;
6
import games.strategy.engine.data.*;
7
import games.strategy.engine.gamePlayer.IPlayerBridge;
8
import games.strategy.net.GUID;
9
import games.strategy.triplea.Constants;
10
import games.strategy.triplea.Properties;
11
import games.strategy.triplea.delegate.DiceRoll;
12
import games.strategy.triplea.delegate.dataObjects.BattleListing;
13
import games.strategy.triplea.delegate.remote.*;
14
import games.strategy.triplea.player.ITripleaPlayer;
15
import games.strategy.triplea.ui.UIContext;
18
* Base class for ais.<p>
20
* Control pausing with the AI pause menu option
22
* AI's should note that any data that is stored in the ai instance, will be lost when
23
* the game is restarted. We cannot save data with an AI, since the player
24
* may choose to restart the game with a different ai, or with a human player.<p>
26
* If an ai finds itself starting in the middle of a move phase, or the middle of a purchase phase,
27
* (as would happen if a player saved the game during the middle of an AI's move phase)
28
* it is acceptable for the ai to play badly for a turn, but the ai should recover, and play
29
* correctly when the next phase of the game starts.<p>
34
public abstract class AbstractAI implements ITripleaPlayer
36
private final static Logger s_logger = Logger.getLogger(AbstractAI.class.getName());
39
* Pause the game to allow the human player to see what is going on.
42
protected void pause()
47
Thread.sleep(UIContext.getAIPauseDuration());
48
} catch (InterruptedException e)
57
private final String m_name;
58
private IPlayerBridge m_bridge;
59
private PlayerID m_id;
63
* @param name - the name of the player.
65
public AbstractAI(String name)
71
public final void initialize(IPlayerBridge bridge, PlayerID id)
77
/************************
78
* Allow the AI to get game data, playerID
79
*************************/
82
* Get the GameData for the game.
84
protected final GameData getGameData()
86
return m_bridge.getGameData();
90
* Get the IPlayerBridge for this game player.
92
protected final IPlayerBridge getPlayerBridge()
98
* What player are we playing.
100
protected final PlayerID getWhoAmI()
105
/************************
106
* The following methods are called when the AI starts a phase.
107
*************************/
110
* It is the AI's turn to purchase units.
112
* @param purcahseForBid - is this a bid purchase, or a normal purchase
113
* @param PUsToSpend - how many PUs we have to spend
114
* @param purchaseDelegate - the purchase delgate to buy things with
115
* @param data - the GameData
116
* @param player - the player to buy for
118
protected abstract void purchase(boolean purcahseForBid, int PUsToSpend, IPurchaseDelegate purchaseDelegate, GameData data, PlayerID player);
121
* It is the AI's turn to roll for technology.
123
* @param techDelegate - the tech delegate to roll for
124
* @param data - the game data
125
* @param player - the player to roll tech for
127
protected abstract void tech(ITechDelegate techDelegate, GameData data, PlayerID player);
130
* It is the AI's turn to move. Make all moves before returning from this method.
132
* @param nonCombat - are we moving in combat, or non combat
133
* @param moveDel - the move delegate to make moves with
134
* @param data - the current game data
135
* @param player - the player to move with
137
protected abstract void move(boolean nonCombat, IMoveDelegate moveDel, GameData data, PlayerID player);
140
* It is the AI's turn to place units. get the units available to place with player.getUnits()
142
* @param placeForBid - is this a placement for bid
143
* @param placeDelegate - the place delegate to place with
144
* @param data - the current Game Data
145
* @param player - the player to place for
147
protected abstract void place(boolean placeForBid, IAbstractPlaceDelegate placeDelegate, GameData data, PlayerID player);
151
* It is the AI's turn to fight. Subclasses may override this if they want, but
152
* generally the AI does not need to worry about the order of fighting battles.
154
* @param battleDelegate the battle delegate to query for battles not fought and the
155
* @param data - the current GameData
156
* @param player - the player to fight for
158
protected void battle(IBattleDelegate battleDelegate, GameData data, PlayerID player)
160
//generally all AI's will follow the same logic.
162
//loop until all battles are fought.
163
//rather than try to analyze battles to figure out which must be fought before others
164
//as in the case of a naval battle preceding an amphibious attack,
165
//keep trying to fight every battle
169
BattleListing listing = battleDelegate.getBattles();
172
if(listing.getBattles().isEmpty() && listing.getStrategicRaids().isEmpty())
175
Iterator<Territory> raidBattles = listing.getStrategicRaids().iterator();
177
//fight strategic bombing raids
178
while(raidBattles.hasNext())
180
Territory current = raidBattles.next();
181
String error = battleDelegate.fightBattle(current, true);
183
s_logger.fine(error);
187
Iterator<Territory> nonRaidBattles = listing.getBattles().iterator();
189
//fight normal battles
190
while(nonRaidBattles.hasNext())
192
Territory current = nonRaidBattles.next();
193
String error = battleDelegate.fightBattle(current, false);
195
s_logger.fine(error);
200
/******************************************
201
* The following methods the AI may choose to implemenmt,
202
* but in general won't
204
*******************************************/
206
public Territory selectBombardingTerritory(Unit unit, Territory unitTerritory, Collection<Territory> territories, boolean noneAvailable)
208
//return the first one
209
return (Territory) territories.iterator().next();
212
public boolean selectAttackSubs(Territory unitTerritory)
217
public boolean selectAttackTransports(Territory unitTerritory)
222
public boolean selectAttackUnits(Territory unitTerritory)
227
public boolean selectShoreBombard(Territory unitTerritory)
232
public Territory whereShouldRocketsAttack(Collection<Territory> candidates, Territory from)
234
//just use the first one
235
return candidates.iterator().next();
238
public boolean confirmMoveKamikaze()
243
public boolean confirmMoveHariKari()
249
/*****************************************
250
* The following methods are more for the ui, and the
251
* ai will generally not care
253
*****************************************/
255
public void battleInfoMessage(String shortMessage, DiceRoll dice)
258
public void confirmEnemyCasualties(GUID battleId, String message, PlayerID hitPlayer)
261
public void retreatNotificationMessage(Collection<Unit> units)
264
public void reportError(String error)
267
public void reportMessage(String message)
271
public void confirmOwnCasualties(GUID battleId, String message)
277
/*****************************************
278
* Game Player Methods
280
*****************************************/
283
* The given phase has started. We parse the phase name and call the apropiate method.
285
public final void start(String name)
287
if (name.endsWith("Bid"))
289
String propertyName = m_id.getName() + " bid";
290
int bidAmount = Integer.parseInt(m_bridge.getGameData().getProperties().get(propertyName).toString());
292
purchase(true,bidAmount, (IPurchaseDelegate) m_bridge.getRemote(), m_bridge.getGameData(), m_id);
294
else if (name.endsWith("Tech")) {
295
if(!Properties.getTechDevelopment(getGameData())) {
298
tech((ITechDelegate) m_bridge.getRemote() , m_bridge.getGameData(), m_id);
300
else if (name.endsWith("Purchase"))
303
Resource PUs = m_bridge.getGameData().getResourceList().getResource(Constants.PUS);
304
int leftToSpend = m_id.getResources().getQuantity(PUs );
306
purchase(false,leftToSpend, (IPurchaseDelegate) m_bridge.getRemote(), m_bridge.getGameData(), m_id);
308
else if (name.endsWith("Move"))
309
move(name.endsWith("NonCombatMove"), (IMoveDelegate) m_bridge.getRemote(), m_bridge.getGameData(), m_id);
310
else if (name.endsWith("Battle"))
311
battle((IBattleDelegate) m_bridge.getRemote(), m_bridge.getGameData(), m_id);
312
else if (name.endsWith("Place"))
313
place(name.indexOf("Bid") != -1, (IAbstractPlaceDelegate) m_bridge.getRemote(), m_bridge.getGameData(), m_id );
314
else if (name.endsWith("EndTurn"))
318
public final Class<ITripleaPlayer> getRemotePlayerType()
320
return ITripleaPlayer.class;
323
public final String getName()
328
public final PlayerID getID()