From 9656502aaa68fb88bfc0664b0d60e8ed25a9acb0 Mon Sep 17 00:00:00 2001 From: JBM Date: Sun, 7 Jun 2020 18:00:08 +0200 Subject: [PATCH 1/1] Early game termination Game termination is now a frame of its own; castle destruction is pushed to a new "endgame" frame. --- PLAN.org | 4 +- config/statement_en.html | 2 +- src/main/java/com/codingame/game/Model.java | 30 ++++++++----- src/main/java/com/codingame/game/Referee.java | 44 +++++++++++++------ src/main/java/com/codingame/game/View.java | 31 +++++++------ src/test/java/Main.java | 2 +- 6 files changed, 72 insertions(+), 41 deletions(-) diff --git a/PLAN.org b/PLAN.org index b8d16aa..5b3be7f 100644 --- a/PLAN.org +++ b/PLAN.org @@ -49,7 +49,7 @@ ** DONE html for salting the seed ** TODO Leagues (need multiround) ** TODO Multiround (need early termination) -** TODO Early termination (need time rationalization) +** DONE Early termination (need time rationalization) ** DONE Time rationalization (need code reorg) ** TODO Code cleanup @@ -59,6 +59,8 @@ That one's probably never going to be DONE ^^' *** split out what can be +*** factor stone throwing ref/view interface + * BUGS ** viewer goes blank <2020-06-03 mer. 22:58> (22:19:12) Astrobytes: JBM, if you're around, the TVC viewer goes blank after a couple of games. Consistently. In Chrome. Other games not doing the same. diff --git a/config/statement_en.html b/config/statement_en.html index 35242fa..05a95cf 100644 --- a/config/statement_en.html +++ b/config/statement_en.html @@ -301,7 +301,7 @@

This draft's last change is: - demo references still existing sprites. + early game termination.

diff --git a/src/main/java/com/codingame/game/Model.java b/src/main/java/com/codingame/game/Model.java index 00701d1..6eb0546 100644 --- a/src/main/java/com/codingame/game/Model.java +++ b/src/main/java/com/codingame/game/Model.java @@ -66,7 +66,9 @@ class Model { } public void adjustScore(int trollPosition) { - gp.setScore(Math.abs(castlePosition - trollPosition)); + if (gp.isActive()) { + gp.setScore(Math.abs(castlePosition - trollPosition)); + } } public int getTrollDistance() { @@ -149,24 +151,30 @@ class Model { p1.setStones(initialStones); } - private int winner; - boolean haveWinner() { - if (trollPosition == 0) { + void moveTroll(int delta) { + trollPosition += delta; + if (trollPosition <= 0) { + trollPosition = 0; winner = 1; - return true; } - else if (trollPosition == roadLength) { + if (trollPosition >= roadLength) { + trollPosition = roadLength; winner = 0; - return true; - } - else { - return false; } + + p0.adjustScore(trollPosition); + p1.adjustScore(trollPosition); } + + private Integer winner; + boolean haveWinner() { + return winner != null; + } + int getWinner() { return winner; } int getLoser() { return 1 - winner; } boolean exhausted() { - return p0.getStones() <= 0 && p1.getStones() <= 0; + return p0.getStones() <= 0 || p1.getStones() <= 0; } } diff --git a/src/main/java/com/codingame/game/Referee.java b/src/main/java/com/codingame/game/Referee.java index 186ca88..dfa3324 100644 --- a/src/main/java/com/codingame/game/Referee.java +++ b/src/main/java/com/codingame/game/Referee.java @@ -24,6 +24,8 @@ public class Referee extends AbstractReferee { @Inject private View view; @Inject private Model model; + boolean disqual = false; + @Override public void init() { model.init(gameManager.getSeed()); @@ -53,6 +55,11 @@ public class Referee extends AbstractReferee { view.startTurn(); + // Did I mention I hate Java? It didn't *have* to be this ugly! + if (disqual) { endGame(); return; } + if (model.exhausted()) { finishStones(); return ;} + if (model.haveWinner()) { endGame(); return; } + for (Player player : gameManager.getActivePlayers()) { player.sendGameTurn(); } @@ -63,7 +70,6 @@ public class Referee extends AbstractReferee { * is ill-formed it could help them debug. Or shame them, at * least. */ - boolean disqual = false; for (Player player : gameManager.getActivePlayers()) { player.receiveGameTurn(); switch (player.type) { @@ -116,8 +122,6 @@ public class Referee extends AbstractReferee { * exhaustion). */ int delta = 0; - boolean victory = false; - boolean exhausted = false; for (Player player : gameManager.getActivePlayers()) { player.view.throwStones(player.stoneThrow); delta += player.model.getMultiplier() * player.stoneThrow; @@ -150,34 +154,46 @@ public class Referee extends AbstractReferee { else if (cheat1) delta = 1; if (delta > 0) { - model.trollPosition++; + model.moveTroll(+1); view.moveTroll(View.Dir.RIGHT); } else if (delta < 0) { - model.trollPosition--; + model.moveTroll(-1); view.moveTroll(View.Dir.LEFT); } else { view.moveTroll(View.Dir.STILL); // XXX animate } + } + // XXX very similar to main turn pendant + private void finishStones() { + boolean noStones = true; + int delta = 0; for (Player player : gameManager.getActivePlayers()) { - player.model.adjustScore(model.trollPosition); + player.stoneThrow = player.model.getStones(); + player.model.setStones(0); + delta += player.stoneThrow * player.model.getMultiplier(); + player.view.throwStones(player.stoneThrow); + if (player.stoneThrow != 0) { + noStones = false; + player.view.animateStones(player.stoneThrow); + player.view.updateStoneCounter(); + } } + if (noStones) { endGame(); return; } + model.moveTroll(delta); + view.moveTroll(); + } + + private void endGame() { + gameManager.endGame(); if (model.haveWinner()) { int loser = model.getLoser(); gameManager.getPlayer(loser).view.defeat(); - victory = true; } - else if (model.exhausted()) exhausted = true; - - if (disqual || victory || exhausted) endGame(); - } - - private void endGame() { - gameManager.endGame(); Player p0 = gameManager.getPlayer(0); Player p1 = gameManager.getPlayer(1); diff --git a/src/main/java/com/codingame/game/View.java b/src/main/java/com/codingame/game/View.java index 52cfa64..40aae3d 100644 --- a/src/main/java/com/codingame/game/View.java +++ b/src/main/java/com/codingame/game/View.java @@ -26,25 +26,22 @@ class View { * - first half: stone throw * - second half: troll move * The troll message is anchored around the troll move. - * - * The castle destruction is currently ad hoc simultaneously with - * the troll move, but this ought to change if I get some - * lengthened frame system ready. - * - * The endgame message is completely ad hoc, and really ought to - * improve. */ - private final double AVATAR_ANIMATION_START = 0.5; private final double STONE_THROW_START = 0.0; private final double STONE_THROW_PEAK = 0.25; private final double STONE_THROW_END = 0.5; - private final double CASTLE_DESTRUCTION_START = 0.5; - private final double CASTLE_DESTRUCTION_END = 1.0; private final double TROLL_MOVE_START = 0.5; private final double TROLL_MOVE_END = 1.0; private final double TROLL_MESSAGE_START = 0.5; private final double TROLL_MESSAGE_END = 1.0; - private final double ENDGAME_MESSAGE_START = 0.25; + + /* + * Castle destruction and endgame message pertain to an endgame + * frame only. + */ + private final double AVATAR_ANIMATION_START = 0.5; + private final double CASTLE_DESTRUCTION_START = 0.0; + private final double CASTLE_DESTRUCTION_END = 0.5; class Player { Model.Player model; @@ -158,6 +155,7 @@ class View { void victory() { gameManager.addToGameSummary(GameManager.formatSuccessMessage(nicknameToken + " wins.")); + View.this.endgameFrame(); markWinner(); } @@ -221,6 +219,7 @@ class View { else { stoneCounter.setText(stones + " stones"); } + graphicEntityModule.commitEntityState(STONE_THROW_PEAK, stoneCounter); } void animateStones(int stones) { @@ -303,13 +302,19 @@ class View { animateTurnCounter(); } + void endgameFrame() { + gameManager.setFrameDuration(2000); + } + void doubleDefeat() { gameManager.addToGameSummary(GameManager.formatErrorMessage("Everybody loses!")); + endgameFrame(); animateLoss(1920/2, 680, 150, "L0SERZ!"); } void draw() { gameManager.addToGameSummary("Draw."); + endgameFrame(); animateLoss(1920/2, 680, 200, "DRAW"); } @@ -513,7 +518,7 @@ class View { pantsModule.displayOnToggleState(trollMessage, "verboseTrolling", true); } - private void moveTroll() { + void moveTroll() { graphicEntityModule.commitEntityState(TROLL_MOVE_START, troll, trollPositionGauge); int x0 = p0.castle.getX(), x1 = p1.castle.getX(); int y0 = p0.castle.getY(), y1 = p1.castle.getY(); @@ -641,7 +646,7 @@ class View { .setFillColor(0xff7f7f) .setFontWeight(Text.FontWeight.BOLD) .setTextAlign(TextBasedEntity.TextAlign.CENTER); - graphicEntityModule.commitEntityState(ENDGAME_MESSAGE_START, msg); + graphicEntityModule.commitEntityState(0.0, msg); Curve curve = Curve.ELASTIC; msg.setX(x, Curve.EASE_OUT) .setY(y, Curve.ELASTIC) diff --git a/src/test/java/Main.java b/src/test/java/Main.java index cbb15e8..1488dee 100644 --- a/src/test/java/Main.java +++ b/src/test/java/Main.java @@ -12,7 +12,7 @@ public class Main { gameRunner.setGameParameters(props); gameRunner.addAgent(Player1.class); - gameRunner.addAgent(PlayerCheatSmart.class); + gameRunner.addAgent(PlayerRand.class); // gameRunner.addAgent("python3 /home/user/player.py"); -- 2.30.2