package me.desht.chesscraft.chess.player;
import chesspresso.Chess;
import chesspresso.move.IllegalMoveException;
import chesspresso.move.Move;
import me.desht.chesscraft.ChessCraft;
import me.desht.chesscraft.Messages;
import me.desht.chesscraft.chess.BoardView;
import me.desht.chesscraft.chess.ChessGame;
import me.desht.chesscraft.chess.ChessGameManager;
import me.desht.chesscraft.chess.TimeControl;
import me.desht.chesscraft.chess.ai.AIFactory;
import me.desht.chesscraft.chess.ai.AIFactory.AIDefinition;
import me.desht.chesscraft.chess.ai.ChessAI;
import me.desht.chesscraft.enums.GameResult;
import me.desht.chesscraft.exceptions.ChessException;
import me.desht.dhutils.LogUtils;
public class AIChessPlayer extends ChessPlayer {
private final ChessAI ai;
public AIChessPlayer(String id, ChessGame game, int colour) {
super(id, id, game, colour);
ai = AIFactory.getInstance().getNewAI(game, id, colour == Chess.WHITE);
}
@Override
public void promptForFirstMove() {
ai.setActive(true);
}
@Override
public void promptForNextMove() {
Move m = getGame().getPosition().getLastMove();
ai.userHasMoved(m.getFromSqi(), m.getToSqi());
}
@Override
public void alert(String message) {
// do nothing here
}
@Override
public void statusMessage(String message) {
// do nothing here
}
@Override
public void replayMoves() {
ai.replayMoves(getGame().getHistory());
}
@Override
public String getDisplayName() {
return ai.getDisplayName();
}
@Override
public String getResultsName() {
return getId();
}
@Override
public void cleanup() {
ai.delete();
}
@Override
public void validateAffordability(String error) {
// nothing to do here - AI's have infinite resources, for now
// (limited AI resources a possible future addition)
}
@Override
public void validateInvited(String error) {
// nothing to do here - AI's do not need invites
}
@Override
public boolean isHuman() {
return false;
}
@Override
public void withdrawFunds(double amount) {
// nothing to do here - AI's have infinite resources, for now
}
@Override
public void depositFunds(double amount) {
// nothing to do here - AI's have infinite resources, for now
}
@Override
public void teleport(BoardView view) {
// nothing to do here
}
@Override
public void cancelOffers() {
// AI doesn't respond to offers right now - possible future addition
}
@Override
public double getPayoutMultiplier() {
AIDefinition aiDef = AIFactory.getInstance().getAIDefinition(getId());
if (aiDef == null) {
LogUtils.warning("can't find AI definition for " + getDisplayName());
return 2.0;
} else {
return 1.0 + aiDef.getPayoutMultiplier();
}
}
@Override
public void drawOffered() {
ai.offerDraw();
}
@Override
public void swapOffered() {
// do nothing here
}
@Override
public void undoOffered() {
// do nothing here
}
@Override
public void undoLastMove() {
ai.setActive(false);
ai.undoLastMove();
}
@Override
public void checkPendingAction() {
ChessGame game = getGame();
ChessPlayer otherPlayer = game.getPlayer(Chess.otherPlayer(getColour()));
if (ai.hasFailed()) {
// this will happen if the AI caught an exception and its state can't be guaranteed anymore
try {
if (ChessCraft.getInstance().getConfig().getBoolean("ai.lose_on_fail", false)) {
game.winByDefault(otherPlayer.getColour());
} else {
game.drawn(GameResult.Abandoned);
}
} catch (ChessException e) {
// should never get here!
LogUtils.severe("Unexpected exception caught while trying to draw game - deleted", e);
ChessGameManager.getManager().deleteGame(game.getName(), true);
}
} else {
// see if the AI has any pending actions from the other thread that we need to pick up
switch (ai.getPendingAction()) {
case MOVED:
int from = ai.getPendingFrom();
int to = ai.getPendingTo();
try {
getGame().doMove(getId(), from, to);
} catch (IllegalMoveException e) {
getGame().alert(Messages.getString("ChessAI.AIunexpectedException", e.getMessage())); //$NON-NLS-1$
ai.setFailed(true);
} catch (ChessException e) {
getGame().alert(Messages.getString("ChessAI.AIunexpectedException", e.getMessage())); //$NON-NLS-1$
ai.setFailed(true);
}
break;
case DRAW_OFFERED:
game.offerDraw(getId());
break;
case DRAW_ACCEPTED:
if (otherPlayer != null) {
otherPlayer.alert(Messages.getString("ExpectYesNoOffer.drawOfferAccepted", getDisplayName()));
}
game.drawn(GameResult.DrawAgreed);
break;
case DRAW_DECLINED:
if (otherPlayer != null) {
otherPlayer.alert(Messages.getString("ExpectYesNoOffer.drawOfferDeclined", getDisplayName()));
}
break;
default:
break;
}
ai.clearPendingAction();
}
}
@Override
public void playEffect(String effect) {
// do nothing
}
@Override
public void notifyTimeControl(TimeControl timeControl) {
ai.notifyTimeControl(timeControl);
}
@Override
public void timeControlCheck() {
ai.notifyTimeControl(getGame().getClock().getTimeControl());
}
}