package org.pixelgaffer.turnierserver.gamelogic; import java.io.IOException; import org.pixelgaffer.turnierserver.gamelogic.interfaces.Ai; import org.pixelgaffer.turnierserver.gamelogic.interfaces.AiObject; import org.pixelgaffer.turnierserver.gamelogic.interfaces.Game; /** * @param <E> * Das AiObject * @param <R> * Die Antwort der Ai */ public abstract class AlternatingTurnBasedGameLogic<E extends AiObject, R> extends GameStateLogic<E, R> { /** * Die Ai, die gerade am Zug ist */ private Ai turn; private AbortableTimer responseTimer = new AbortableTimer(maxResponseTime(), () -> { aiAnswerTimeout(turn); if(!gameEnded) turn(); }); /** * Wird aufgerufen, wenn eine AI geantwortet hat * * @return Das Objekt für den renderer, wenn null wird nichts gesendet */ protected abstract Object update(); /** * @return Die maximale Zeit die eine KI zum antworten hat, bevor aiAnswerTimeout aufgerufen wird */ protected abstract int maxResponseTime(); /** * Wird aufgerufen wenn eine KI zu lange zum Antworten braucht * * @param ai Die KI die zu lange zum Antworten gebraucht hat */ protected abstract void aiAnswerTimeout(Ai ai); @Override protected final void receive(R response, Ai ai, int passedMikros) { logger.debug("got message from " + ai.getId()); if (turn == null || turn != ai) { logger.critical("Die AI ist nicht an der Reihe, und hat trotzdem etwas gesendet"); return; } responseTimer.abort(); if(getUserObject(ai).subtractMikros(passedMikros)) { logger.debug("timeout"); return; } logger.debug("applying changes"); gamestate.applyChanges(response, ai); logger.debug("applied changes"); Object update = update(); logger.debug("updated"); if(gameEnded) { logger.debug("game ended"); return; } if (update != null) { sendRenderData(update); } turn(); } private void turn(Ai ai) { logger.debug("turn(" + ai.getId() + ")"); turn = ai; if(getUserObject(ai).lost) { turn(); return; } try { sendGameState(ai); responseTimer.restart(); } catch (IOException e) { getUserObject(ai).loose("Es gab ein Problem bei der Kommunikation mit der KI"); } } private void turn() { logger.debug("turn()"); if (turn == null) { turn(game.getAis().get(0)); return; } if (turn.getIndex() == game.getAis().size() - 1) { if (allRoundsPlayed()) { endGame("Die maximale Anzahl an Runden (" + maxTurns + ") wurde gespielt"); return; } round(); } turn(game.getAis().get((turn.getIndex() + 1) % game.getAis().size())); } /** * super.lost(Ai ai) MUSS AUFGERUFEN WERDEN!! Es ist möglich, dass das Spiel vorbei ist, sobald diese Methode zurückgibt */ @Override public void lost(Ai ai) { logger.debug("ai " + ai.getId() + " hat verloren"); logger.debug("Ai " + ai.getId() + " ist momentan am zug"); if (ai.getIndex() == turn.getIndex()) { logger.debug("calling turn"); turn(); } } @Override public void startGame(Game game) { super.startGame(game); turn(); } }