]> git.seodisparate.com - RockPaperScissorsDuel/commitdiff
Refactorings, fix ? color, fix spectator mode
authorStephen Seo <seo.disparate@gmail.com>
Wed, 18 Jan 2023 05:49:24 +0000 (14:49 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 18 Jan 2023 05:49:24 +0000 (14:49 +0900)
20 files changed:
src/3d/anim_concurrent.cc
src/3d/anim_model_attack.cc
src/3d/anim_model_attack.h
src/3d/anim_model_grow.cc
src/3d/anim_model_grow.h
src/3d/anim_model_shrink.cc
src/3d/anim_model_shrink.h
src/3d/anim_model_still.cc
src/3d/anim_model_still.h
src/3d/anim_sequence.cc
src/3d/anims.cc
src/3d/anims.h
src/3d_renderer.cc
src/3d_renderer.h
src/basic_renderer.cc
src/basic_renderer.h
src/game_renderer.h
src/main.cc
wasm_build/client.js
wasm_build/logic.js

index 3d9c5d89e38b84d7c4b5f4f946f29564da79de87..05bf24781dc2bc2300a30a47efa8818cf1c6b409 100644 (file)
@@ -1,6 +1,7 @@
 #include "anim_concurrent.h"
 
-AnimConcurrent::AnimConcurrent(Model *model) : Anims(model) {}
+AnimConcurrent::AnimConcurrent(Model *model)
+    : Anims(model, {0.0F, 0.0F, 0.0F}, {255, 255, 255, 255}) {}
 
 AnimConcurrent::~AnimConcurrent() {}
 
index 950cddf9bfe5139806f19e570aa396f834179077..bb93a887d1bcfb840fe9a7f28904fabb8a6c06a3 100644 (file)
@@ -8,9 +8,8 @@
 #include "../helpers.h"
 #include "a3f_conv.h"
 
-AnimModelAttack::AnimModelAttack(Model *model, A3F pos, bool is_p1)
-    : Anims(model),
-      pos(pos),
+AnimModelAttack::AnimModelAttack(Model *model, A3F pos, A4C color, bool is_p1)
+    : Anims(model, pos, color),
       offset{0.0F, 0.0F, 0.0F},
       timer(MODEL_ATTACK_TIME_0),
       state(0),
@@ -63,7 +62,7 @@ void AnimModelAttack::do_update(float dt) {
 }
 
 void AnimModelAttack::do_draw() {
-  DrawModel(*model, A3FToRV3(pos + offset), 1.0F, WHITE);
+  DrawModel(*model, A3FToRV3(pos + offset), 1.0F, A4CToC(color));
 }
 
 bool AnimModelAttack::is_done_impl() { return state == 3; }
index c07e8ce62a5fec9b273b125b2e117f00dd0a7963..f5bcf7c0f1b41975979813e35de14a2104071161 100644 (file)
@@ -6,7 +6,7 @@
 
 class AnimModelAttack : public Anims {
  public:
-  AnimModelAttack(Model *model, A3F pos, bool is_p1);
+  AnimModelAttack(Model *model, A3F pos, A4C color, bool is_p1);
   ~AnimModelAttack() override;
 
   void do_update(float dt) override;
@@ -15,7 +15,6 @@ class AnimModelAttack : public Anims {
  private:
   bool is_done_impl() override;
 
-  A3F pos;
   A3F offset;
   float timer;
   /*
index f06fb79412ac446c182c469d699feda10245f5a2..469366ae28cc5578f483f7e8d62463e1917c53aa 100644 (file)
@@ -7,8 +7,8 @@
 #include "../constants.h"
 #include "a3f_conv.h"
 
-AnimModelGrow::AnimModelGrow(Model *model, A3F pos)
-    : Anims(model), pos(pos), timer(MODEL_GROW_TIME) {}
+AnimModelGrow::AnimModelGrow(Model *model, A3F pos, A4C color)
+    : Anims(model, pos, color), timer(MODEL_GROW_TIME) {}
 
 AnimModelGrow::~AnimModelGrow() {}
 
@@ -16,7 +16,8 @@ void AnimModelGrow::do_update(float dt) { timer -= dt; }
 
 void AnimModelGrow::do_draw() {
   DrawModel(*model, A3FToRV3(pos),
-            timer >= 0.0F ? (1.0F - timer / MODEL_GROW_TIME) : 1.0F, WHITE);
+            timer >= 0.0F ? (1.0F - timer / MODEL_GROW_TIME) : 1.0F,
+            A4CToC(color));
 }
 
 bool AnimModelGrow::is_done_impl() { return timer <= 0.0F; }
index f881e4fd6db2e1dc75b42fcf7220db81feff1920..faf98eca94de86a17839dd5809413923eee7f6ad 100644 (file)
@@ -6,7 +6,7 @@
 
 class AnimModelGrow : public Anims {
  public:
-  AnimModelGrow(Model *model, A3F pos);
+  AnimModelGrow(Model *model, A3F pos, A4C color);
   ~AnimModelGrow() override;
 
   void do_update(float dt) override;
@@ -15,7 +15,6 @@ class AnimModelGrow : public Anims {
  private:
   bool is_done_impl() override;
 
-  A3F pos;
   float timer;
 };
 
index 5924b82f04a26b94972bdbc945cbe3c827ffef7b..1459efe2ab98e18657deaaf0812924a677ad6896 100644 (file)
@@ -7,8 +7,8 @@
 #include "../constants.h"
 #include "a3f_conv.h"
 
-AnimModelShrink::AnimModelShrink(Model *model, A3F pos)
-    : Anims(model), pos(pos), timer(MODEL_SHRINK_TIME) {}
+AnimModelShrink::AnimModelShrink(Model *model, A3F pos, A4C color)
+    : Anims(model, pos, color), timer(MODEL_SHRINK_TIME) {}
 
 AnimModelShrink::~AnimModelShrink() {}
 
@@ -16,7 +16,7 @@ void AnimModelShrink::do_update(float dt) { timer -= dt; }
 
 void AnimModelShrink::do_draw() {
   DrawModel(*model, A3FToRV3(pos),
-            timer >= 0.0F ? (timer / MODEL_SHRINK_TIME) : 0.0F, WHITE);
+            timer >= 0.0F ? (timer / MODEL_SHRINK_TIME) : 0.0F, A4CToC(color));
 }
 
 bool AnimModelShrink::is_done_impl() { return timer <= 0.0F; }
index 4af0e7deb417ba93a3ac16f81539e36760796a89..89a458e757334de3b00eb6c9647c4facd73b1ee3 100644 (file)
@@ -6,7 +6,7 @@
 
 class AnimModelShrink : public Anims {
  public:
-  AnimModelShrink(Model *model, A3F pos);
+  AnimModelShrink(Model *model, A3F pos, A4C color);
   ~AnimModelShrink() override;
 
   void do_update(float dt) override;
@@ -15,7 +15,6 @@ class AnimModelShrink : public Anims {
  private:
   bool is_done_impl() override;
 
-  A3F pos;
   float timer;
 };
 
index 87f9d37434af2f1d33612dfcab55e17cf93d2c53..eba90e8a743720f27eeeda30877fc7c4b44cff30 100644 (file)
@@ -1,19 +1,20 @@
 #include "anim_model_still.h"
 
-#include "a3f_conv.h"
-
 // third party includes
 #include <raylib.h>
 
-AnimModelStill::AnimModelStill(Model *model, A3F pos, float time)
-    : Anims(model), pos(pos), timer(time) {}
+// local includes
+#include "a3f_conv.h"
+
+AnimModelStill::AnimModelStill(Model *model, A3F pos, A4C color, float time)
+    : Anims(model, pos, color), timer(time) {}
 
 AnimModelStill::~AnimModelStill() {}
 
 void AnimModelStill::do_update(float dt) { timer -= dt; }
 
 void AnimModelStill::do_draw() {
-  DrawModel(*model, A3FToRV3(pos), 1.0F, WHITE);
+  DrawModel(*model, A3FToRV3(pos), 1.0F, A4CToC(color));
 }
 
 bool AnimModelStill::is_done_impl() { return timer <= 0.0F; }
index b59505f223719a23e8f85bbd2f7c4d3516906798..664a8c54c59651f6a335162e84f97862e67eb3f6 100644 (file)
@@ -6,7 +6,7 @@
 
 class AnimModelStill : public Anims {
  public:
-  AnimModelStill(Model *model, A3F pos, float time);
+  AnimModelStill(Model *model, A3F pos, A4C color, float time);
   ~AnimModelStill() override;
 
   void do_update(float dt) override;
@@ -15,7 +15,6 @@ class AnimModelStill : public Anims {
  private:
   bool is_done_impl() override;
 
-  A3F pos;
   float timer;
 };
 
index 6695475fb3523e41ed019912bcee15641824e5ca..ad5a7ab7212c828ec08625fdc9dc73326ac74ee6 100644 (file)
@@ -1,6 +1,7 @@
 #include "anim_sequence.h"
 
-AnimSequence::AnimSequence(Model *model) : Anims(model) {}
+AnimSequence::AnimSequence(Model *model)
+    : Anims(model, {0.0F, 0.0F, 0.0F}, {255, 255, 255, 255}) {}
 
 AnimSequence::~AnimSequence() {}
 
index 57d765d0fa506d59bb7bb3ae75cf8f91c4f79795..e9ef0b7a2cb33f9efa9ea92bbbd8de2bcbb164a2 100644 (file)
@@ -1,7 +1,9 @@
 #include "anims.h"
 
-Anims::Anims(Model *model)
-    : model(model),
+Anims::Anims(Model *model, A3F pos, A4C color)
+    : pos(pos),
+      color(color),
+      model(model),
       userdata(nullptr),
       function_ptr(nullptr),
       is_done_finished(false) {}
index d24efc0377aa7fff8729eb1d45f99bafd16047fc..ec9661545ed5c565cdebc735da2ec5d0ad42c584 100644 (file)
@@ -4,6 +4,9 @@
 // standard library includes
 #include <memory>
 
+// local includes
+#include "a3f.h"
+
 // forward declarations
 struct Model;
 
@@ -14,7 +17,7 @@ class Anims {
 
   using FP = void (*)(void *);
 
-  Anims(Model *model);
+  Anims(Model *model, A3F pos, A4C color);
   virtual ~Anims() {}
 
   bool is_done();
@@ -28,6 +31,8 @@ class Anims {
  protected:
   virtual bool is_done_impl() = 0;
 
+  A3F pos;
+  A4C color;
   Model *model;
   void *userdata;
   FP function_ptr;
index 7947c7a72f02dec51d5567b90b540479a8a69372..249273b814a0eb4cc9419866502349568dfa81df 100644 (file)
@@ -4,12 +4,11 @@
 #include <cmath>
 #include <cstring>
 #include <iostream>
+#include <memory>
 
 // third party includes
 #include <raylib.h>
 
-#include <memory>
-
 // local includes
 #include "3d/a3f_conv.h"
 #include "3d/anim_concurrent.h"
@@ -114,7 +113,7 @@ void Renderer3D::update_state(const char *playerOne, const char *playerTwo,
                               char second_first, char second_second,
                               char second_third, bool first_ready,
                               bool second_ready, bool first_matchup_done,
-                              bool second_matchup_done, int pos,
+                              bool second_matchup_done, int pos, int prev_pos,
                               bool gameover_called, bool matchup_started) {
   if (std::strcmp(playerOne, currentPlayer) == 0) {
     flags.set(2);
@@ -143,8 +142,11 @@ void Renderer3D::update_state(const char *playerOne, const char *playerTwo,
               << (second_ready ? "ready" : "NOT ready") << std::endl;
   }
 
-  if (!flags.test(13)) {
+  this->prev_pos = prev_pos;
+  if (!flags.test(13) && anims.is_done()) {
     received_pos = pos;
+  } else if (flags.test(3) && anims.is_done()) {
+    received_pos = prev_pos;
   }
 
   if (second_first != '?') {
@@ -166,33 +168,13 @@ void Renderer3D::update_state(const char *playerOne, const char *playerTwo,
     opponent_choices.at(0) = second_first;
     opponent_choices.at(1) = second_second;
     opponent_choices.at(2) = second_third;
-    flags.set(0, flags.test(13));
   }
 
-  if ((flags.test(11) || flags.test(3)) && first_first == '?' &&
-      second_first == '?' && flags.test(15) && !flags.test(13)) {
-    choices.at(0) = '?';
-    choices.at(1) = '?';
-    choices.at(2) = '?';
-    opponent_choices.at(0) = '?';
-    opponent_choices.at(1) = '?';
-    opponent_choices.at(2) = '?';
-    flags.reset(11);
-    flags.reset(8);
-    flags.reset(0);
-    flags.reset(15);
-    flags.reset(7);
-    overview_timer = OVERVIEW_TIMER_MAX;
-    set_random_overview();
-    camera.target.x = received_pos * 2.0F;
-    if (flags.test(3)) {
-      std::cerr << "RESET STATE for next round" << std::endl;
-    }
+  if (flags.test(11) && first_first == '?' && second_first == '?' &&
+      flags.test(15) && !flags.test(13)) {
+    reset_for_next();
   }
 
-  qms.at(0).set_pos_x(received_pos * 2.0F - 1.0F);
-  qms.at(1).set_pos_x(received_pos * 2.0F + 1.0F);
-
   if (flags.test(3)) {
     std::cout << flags.to_string().substr(64 - 16) << std::endl;
   }
@@ -382,6 +364,20 @@ void Renderer3D::update_impl() {
   }
 
   anims.do_update(dt);
+
+  if (flags.test(3)) {
+    if (flags.test(0)) {
+      if (anims.is_done()) {
+        reset_for_next();
+        received_pos = prev_pos;
+      }
+    } else if (flags.test(13)) {
+      flags.set(0);
+    }
+  }
+
+  qms.at(0).set_pos_x(received_pos * 2.0F - 1.0F);
+  qms.at(1).set_pos_x(received_pos * 2.0F + 1.0F);
 }
 
 void Renderer3D::draw_impl() {
@@ -567,9 +563,9 @@ int Renderer3D::setup_anims(int idx, int score) {
 
   auto newAnim = std::make_unique<AnimConcurrent>(nullptr);
   newAnim->push_anim(std::make_unique<AnimModelShrink>(
-      &qm_model, A3F{score * 2.0F - 1.0F, 0.0F, 0.0F}));
+      &qm_model, A3F{score * 2.0F - 1.0F, 0.0F, 0.0F}, A4C{255, 0, 0, 255}));
   newAnim->push_anim(std::make_unique<AnimModelShrink>(
-      &qm_model, A3F{score * 2.0F + 1.0F, 0.0F, 0.0F}));
+      &qm_model, A3F{score * 2.0F + 1.0F, 0.0F, 0.0F}, A4C{0, 0, 255, 255}));
   anims.push_anim(std::move(newAnim));
 
   newAnim = std::make_unique<AnimConcurrent>(nullptr);
@@ -622,9 +618,9 @@ int Renderer3D::setup_anims(int idx, int score) {
       break;
   }
   newAnim->push_anim(std::make_unique<AnimModelGrow>(
-      p1_model, A3F{score * 2.0F - 1.0F, 0.0F, 0.0F}));
+      p1_model, A3F{score * 2.0F - 1.0F, 0.0F, 0.0F}, A4C{255, 255, 255, 255}));
   newAnim->push_anim(std::make_unique<AnimModelGrow>(
-      p2_model, A3F{score * 2.0F + 1.0F, 0.0F, 0.0F}));
+      p2_model, A3F{score * 2.0F + 1.0F, 0.0F, 0.0F}, A4C{255, 255, 255, 255}));
   anims.push_anim(std::move(newAnim));
 
   newAnim = std::make_unique<AnimConcurrent>(nullptr);
@@ -639,15 +635,19 @@ int Renderer3D::setup_anims(int idx, int score) {
     case -1:
       newAnim->push_anim(std::make_unique<AnimModelStill>(
           p1_model, A3F{score * 2.0F - 1.0F, 0.0F, 0.0F},
+          A4C{255, 255, 255, 255},
           MODEL_ATTACK_TIME_0 + MODEL_ATTACK_TIME_1 + MODEL_ATTACK_TIME_2));
       newAnim->push_anim(std::make_unique<AnimModelAttack>(
-          p2_model, A3F{score * 2.0F + 1.0F, 0.0F, 0.0F}, false));
+          p2_model, A3F{score * 2.0F + 1.0F, 0.0F, 0.0F},
+          A4C{255, 255, 255, 255}, false));
       break;
     case 1:
       newAnim->push_anim(std::make_unique<AnimModelAttack>(
-          p1_model, A3F{score * 2.0F - 1.0F, 0.0F, 0.0F}, true));
+          p1_model, A3F{score * 2.0F - 1.0F, 0.0F, 0.0F},
+          A4C{255, 255, 255, 255}, true));
       newAnim->push_anim(std::make_unique<AnimModelStill>(
           p2_model, A3F{score * 2.0F + 1.0F, 0.0F, 0.0F},
+          A4C{255, 255, 255, 255},
           MODEL_ATTACK_TIME_0 + MODEL_ATTACK_TIME_1 + MODEL_ATTACK_TIME_2));
       break;
     case 0:
@@ -661,9 +661,9 @@ int Renderer3D::setup_anims(int idx, int score) {
 
   newAnim = std::make_unique<AnimConcurrent>(nullptr);
   newAnim->push_anim(std::make_unique<AnimModelShrink>(
-      p1_model, A3F{score * 2.0F - 1.0F, 0.0F, 0.0F}));
+      p1_model, A3F{score * 2.0F - 1.0F, 0.0F, 0.0F}, A4C{255, 255, 255, 255}));
   newAnim->push_anim(std::make_unique<AnimModelShrink>(
-      p2_model, A3F{score * 2.0F + 1.0F, 0.0F, 0.0F}));
+      p2_model, A3F{score * 2.0F + 1.0F, 0.0F, 0.0F}, A4C{255, 255, 255, 255}));
 
   using DataT = std::tuple<int *, int>;
   DataT *data = new DataT{&received_pos, result};
@@ -679,11 +679,33 @@ int Renderer3D::setup_anims(int idx, int score) {
 
   newAnim = std::make_unique<AnimConcurrent>(nullptr);
   newAnim->push_anim(std::make_unique<AnimModelGrow>(
-      &qm_model, A3F{(result + score) * 2.0F - 1.0F, 0.0F, 0.0F}));
+      &qm_model, A3F{(result + score) * 2.0F - 1.0F, 0.0F, 0.0F},
+      A4C{255, 0, 0, 255}));
   newAnim->push_anim(std::make_unique<AnimModelGrow>(
-      &qm_model, A3F{(result + score) * 2.0F + 1.0F, 0.0F, 0.0F}));
+      &qm_model, A3F{(result + score) * 2.0F + 1.0F, 0.0F, 0.0F},
+      A4C{0, 0, 255, 255}));
 
   anims.push_anim(std::move(newAnim));
 
   return score + result;
 }
+
+void Renderer3D::reset_for_next() {
+  choices.at(0) = '?';
+  choices.at(1) = '?';
+  choices.at(2) = '?';
+  opponent_choices.at(0) = '?';
+  opponent_choices.at(1) = '?';
+  opponent_choices.at(2) = '?';
+  flags.reset(11);
+  flags.reset(8);
+  flags.reset(0);
+  flags.reset(15);
+  flags.reset(7);
+  overview_timer = OVERVIEW_TIMER_MAX;
+  set_random_overview();
+  camera.target.x = received_pos * 2.0F;
+  if (flags.test(3)) {
+    std::cerr << "RESET STATE for next round" << std::endl;
+  }
+}
index b0233440d3e9c2f602150b9e598b5ca2fe6db779..2a4d08bcb1f7d101fd7a37b5354ec50123ffe446 100644 (file)
@@ -26,8 +26,8 @@ class Renderer3D : public GameRenderer {
                     char first_second, char first_third, char second_first,
                     char second_second, char second_third, bool first_ready,
                     bool second_ready, bool first_matchup_done,
-                    bool second_matchup_done, int pos, bool gameover_called,
-                    bool matchup_started) override;
+                    bool second_matchup_done, int pos, int prev_pos,
+                    bool gameover_called, bool matchup_started) override;
 
   void do_update() override;
 
@@ -42,6 +42,8 @@ class Renderer3D : public GameRenderer {
   // Returns score after round "idx"
   int setup_anims(int idx, int score);
 
+  void reset_for_next();
+
   std::array<QuestionMark, 2> qms;
 
   Camera camera;
@@ -97,6 +99,7 @@ class Renderer3D : public GameRenderer {
   float button_color_timer;
 
   int received_pos;
+  int prev_pos;
   // int received_matchup_idx;
 
   std::array<unsigned char, 3> choices;
index d9a6ac73c64468318c1f632dfc8e3ea25ca5ce7b..5fb1157dce22fec82570ebd1db14432deffd61b3 100644 (file)
@@ -33,14 +33,12 @@ BasicRenderer::BasicRenderer()
   opponentPicked[2] = 0;
 }
 
-void BasicRenderer::update_state(const char *playerOne, const char *playerTwo,
-                                 const char *currentPlayer, char first_first,
-                                 char first_second, char first_third,
-                                 char second_first, char second_second,
-                                 char second_third, bool first_ready,
-                                 bool second_ready, bool first_matchup_done,
-                                 bool second_matchup_done, int pos,
-                                 bool gameover_called, bool matchup_started) {
+void BasicRenderer::update_state(
+    const char *playerOne, const char *playerTwo, const char *currentPlayer,
+    char first_first, char first_second, char first_third, char second_first,
+    char second_second, char second_third, bool first_ready, bool second_ready,
+    bool first_matchup_done, bool second_matchup_done, int pos, int prev_pos,
+    bool gameover_called, bool matchup_started) {
   // TODO DEBUG
   // if (std::strcmp(playerOne, currentPlayer) == 0) {
   //  std::clog << "update_state:\n"
index bd2d21d7ea3752e0310e15f55d93e1a85e556efe..10b5aedff7accc5d825cfc80d4147d90da0e17fe 100644 (file)
@@ -22,8 +22,8 @@ class BasicRenderer : public GameRenderer {
                     char first_second, char first_third, char second_first,
                     char second_second, char second_third, bool first_ready,
                     bool second_ready, bool first_matchup_done,
-                    bool second_matchup_done, int pos, bool gameover_called,
-                    bool matchup_started) override;
+                    bool second_matchup_done, int pos, int prev_pos,
+                    bool gameover_called, bool matchup_started) override;
 
   void do_update() override;
 
index 247436d624f9c2bdcbf81ddd23444256947ec3b1..31197c50dbd2b0b524cd411cb5d70884192d2a03 100644 (file)
@@ -12,7 +12,7 @@ class GameRenderer {
                             char second_first, char second_second,
                             char second_third, bool first_ready,
                             bool second_ready, bool first_matchup_done,
-                            bool second_matchup_done, int pos,
+                            bool second_matchup_done, int pos, int prev_pos,
                             bool gameover_called, bool matchup_started) = 0;
 
   virtual void do_update() = 0;
index b947b9d330eb68bc5bac324c9b43263a9fe00355..7dd189912ca1352826180b340ec8f70cf5513a85 100644 (file)
@@ -30,13 +30,13 @@ int EMSCRIPTEN_KEEPALIVE game_visual_update(
     const char *playerOne, const char *playerTwo, const char *currentPlayer,
     char first_first, char first_second, char first_third, char second_first,
     char second_second, char second_third, bool first_ready, bool second_ready,
-    bool first_matchup_done, bool second_matchup_done, int pos,
+    bool first_matchup_done, bool second_matchup_done, int pos, int prev_pos,
     bool gameover_called, bool matchup_started) {
   ((GameRenderer *)global_game_ptr)
       ->update_state(playerOne, playerTwo, currentPlayer, first_first,
                      first_second, first_third, second_first, second_second,
                      second_third, first_ready, second_ready,
-                     first_matchup_done, second_matchup_done, pos,
+                     first_matchup_done, second_matchup_done, pos, prev_pos,
                      gameover_called, matchup_started);
   return 0;
 }
index 071512b4835139fcfd13cb719137b6bc64151b11..51a74f64ebd2672955c351baf67d13b83adbd53d 100644 (file)
@@ -1,6 +1,6 @@
 Rune.initClient({
     visualUpdate: ({ newGame, yourPlayerId}) => {
-        const { player1, player2, first_choices, second_choices, ready, matchup_done, pos, gameover, gameover_called, matchup_started } = newGame;
+        const { player1, player2, first_choices, second_choices, ready, matchup_done, pos, prev_pos, gameover, gameover_called, matchup_started } = newGame;
 
         function is_choices_filled(choices) {
             for (let i = 0; i < 3; ++i) {
@@ -19,7 +19,7 @@ Rune.initClient({
                     'number', 'number', 'number',
                     'boolean', 'boolean',
                     'boolean', 'boolean',
-                    'number', 'boolean', 'boolean'],
+                    'number', 'number', 'boolean', 'boolean'],
                 [player1, player2,
                     yourPlayerId === undefined ? 'undefined' : yourPlayerId,
                     first_choices[0].charCodeAt(0),
@@ -30,7 +30,7 @@ Rune.initClient({
                     second_choices[2].charCodeAt(0),
                     ready[0], ready[1],
                     matchup_done[0], matchup_done[1],
-                    pos, gameover_called, matchup_started]);
+                    pos, prev_pos, gameover_called, matchup_started]);
         } else {
             Module.ccall('game_visual_update',
                 'number',
@@ -39,7 +39,7 @@ Rune.initClient({
                     'number', 'number', 'number',
                     'boolean', 'boolean',
                     'boolean', 'boolean',
-                    'number', 'boolean', 'boolean'],
+                    'number', 'number', 'boolean', 'boolean'],
                 [player1, player2,
                     yourPlayerId === undefined ? 'undefined' : yourPlayerId,
                     '?'.charCodeAt(0),
@@ -50,7 +50,7 @@ Rune.initClient({
                     '?'.charCodeAt(0),
                     ready[0], ready[1],
                     matchup_done[0], matchup_done[1],
-                    pos, gameover_called, matchup_started]);
+                    pos, prev_pos, gameover_called, matchup_started]);
         }
     },
 });
index 24c8cfba21dde32d1ebc7bd5536b0ec6edd588d3..c123121028df4add773c047fa2ff48e62f93f653 100644 (file)
@@ -9,6 +9,7 @@ Rune.initLogic({
         ready: new Array(2).fill(false),
         matchup_done: new Array(2).fill(false),
         pos: 0,
+        prev_pos: 0,
         gameover: false,
         gameover_called: false,
         matchup_started: false,
@@ -94,6 +95,7 @@ Rune.initLogic({
 
             if (is_choices_filled(game.first_choices) && is_choices_filled(game.second_choices)) {
                 game.matchup_started = true;
+                game.prev_pos = game.pos;
                 for (let i = 0; i < 3; ++i) {
                     let result = check_matchup(game.first_choices[i], game.second_choices[i]);
                     if (result > 0) {
@@ -152,6 +154,7 @@ Rune.initLogic({
                 game.second_choices[0] = '?';
                 game.second_choices[1] = '?';
                 game.second_choices[2] = '?';
+                game.prev_pos = game.pos;
             }
         },
     },