package games.strategy.triplea.player;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.gamePlayer.IGamePlayer;
import games.strategy.engine.gamePlayer.IPlayerBridge;
import games.strategy.util.ThreadUtil;
/**
* As a rule, nothing that changes GameData should be in here (it should be in a delegate, and done through an IDelegate
* using a change).
*/
public abstract class AbstractBasePlayer implements IGamePlayer {
private final String name; // what nation are we playing? ex: "Americans"
private final String type; // what are we? ex: "Human" or "AI"
private PlayerID playerID;
private IPlayerBridge playerBridge;
private boolean isStoppedGame = false;
/**
* @param name
* - the name of the player.
*/
public AbstractBasePlayer(final String name, final String type) {
this.name = name;
this.type = type;
}
/**
* Anything that overrides this MUST call super.initialize(iPlayerBridge, playerID);
*/
@Override
public void initialize(final IPlayerBridge iPlayerBridge, final PlayerID playerID) {
playerBridge = iPlayerBridge;
this.playerID = playerID;
}
/**
* Get the GameData for the game.
*/
public GameData getGameData() {
return playerBridge.getGameData();
}
/**
* Get the IPlayerBridge for this game player.
* (This is not a delegate bridge, and we cannot send changes on this. Changes should only be done within a delegate,
* never through a
* player.)
*/
protected final IPlayerBridge getPlayerBridge() {
return playerBridge;
}
@Override
public final String getName() {
return name;
}
@Override
public final String getType() {
return type;
}
@Override
public final PlayerID getPlayerID() {
return playerID;
}
@Override
public String toString() {
return (playerID == null || playerID.getName() == null || !playerID.getName().equals(name))
? (type + ":" + name + ":" + (playerID == null ? "NullID" : playerID.getName())) : (type + ":" + name);
}
/**
* The given phase has started. We parse the phase name and call the appropriate method.
*/
@Override
public void start(final String stepName) {
if (stepName != null) {
// PlayerBridge is on a different thread than this one, and so it will be updated asynchronously. Need to wait for
// it.
String bridgeStep = getPlayerBridge().getStepName();
int i = 0;
boolean shownErrorMessage = false;
while (!stepName.equals(bridgeStep)) {
ThreadUtil.sleep(100);
i++;
if (i > 30 && !shownErrorMessage) {
System.out.println("Start step: " + stepName + " does not match player bridge step: " + bridgeStep
+ ". Player Bridge GameOver=" + getPlayerBridge().isGameOver() + ", PlayerID: " + getPlayerID().getName()
+ ", Game: " + getGameData().getGameName()
+ ". Something wrong or very laggy. Will keep trying for 30 more seconds. ");
shownErrorMessage = true;
}
// TODO: what is the right amount of time to wait before we give up?
if (i > 310) {
System.err.println("Start step: " + stepName + " still does not match player bridge step: " + bridgeStep
+ " even after waiting more than 30 seconds. This will probably result in a ClassCastException very "
+ "soon. Player Bridge GameOver=" + getPlayerBridge().isGameOver()
+ ", PlayerID: " + getPlayerID().getName() + ", Game: " + getGameData().getGameName());
// getPlayerBridge().printErrorStatus();
// waited more than 30 seconds, so just let stuff run (an error will pop up surely...)
break;
}
bridgeStep = getPlayerBridge().getStepName();
}
}
}
@Override
public void stopGame() {
isStoppedGame = true;
}
public boolean isGameStopped() {
return isStoppedGame;
}
// public abstract Class<?> getRemotePlayerType();
}