]> git.seodisparate.com - RockPaperScissorsDuel/commitdiff
WIP work on game
authorStephen Seo <seo.disparate@gmail.com>
Tue, 3 Jan 2023 09:40:16 +0000 (18:40 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Tue, 3 Jan 2023 09:40:16 +0000 (18:40 +0900)
Bug to fix is that players are stuck in "is ready" state.

12 files changed:
CMakeLists.txt
src/constants.h
src/ems.cc
src/ems.h
src/game.cc
src/game.h
src/helpers.cc [new file with mode: 0644]
src/helpers.h [new file with mode: 0644]
src/main.cc
wasm_build/Makefile
wasm_build/client.js
wasm_build/logic.js

index 02fd6d41af430bb410267b02730a9aa876f97c41..520559efb710c3ccac8e6e2de96c5c3b6895745a 100644 (file)
@@ -17,6 +17,8 @@ endif()
 set(RPSDuelNative_SOURCES
     src/main.cc
     src/game.cc
+    src/ems.cc
+    src/helpers.cc
 )
 
 add_executable(RPSDuelNative ${RPSDuelNative_SOURCES})
index 0707fa031aaef8548ab802b572387b4c06fe083b..58ac1f202947b112e66008e0cac0185ec2040d1b 100644 (file)
@@ -18,4 +18,8 @@ constexpr float READY_TIMER_MAX = 1.0F;
 
 constexpr float RESULTS_TIMER_MAX = 1.0F;
 
+constexpr float SCORE_CHANGE_TIMER_MAX = 1.0F;
+
+constexpr float REQUEST_TIMER_MAX = 2.0F;
+
 #endif
index 975a2c2d08e99fda59f889c5c35fa958e75aa63d..6b1d8ce91ac27a68f90ea05c0e6bf5c6f69e810f 100644 (file)
@@ -4,14 +4,20 @@
 #include <emscripten.h>
 #include <emscripten/html5.h>
 
-EM_JS(void, js_set_ready, (), { Rune.actions.set_ready("unused"); });
+EM_JS(void, js_set_ready, (bool is_ready),
+      { Rune.actions.set_ready({is_ready}); });
 
 EM_JS(void, js_set_choices,
       (const char *first, const char *second, const char *third), {
-        Rune.actions.set_choices(UTF8ToString(first), UTF8ToString(second),
-                                 UTF8ToString(third));
+        Rune.actions.set_choices({
+          first : UTF8ToString(first),
+          second : UTF8ToString(second),
+          third : UTF8ToString(third)
+        });
       });
 
+EM_JS(void, js_request_update, (), { Rune.actions.request_update("unused"); });
+
 EM_JS(int, canvas_get_width, (),
       { return document.getElementById("canvas").clientWidth; });
 
@@ -21,9 +27,9 @@ EM_JS(int, canvas_get_height, (),
 #include <iostream>
 #endif
 
-void call_js_set_ready() {
+void call_js_set_ready(bool ready) {
 #ifdef __EMSCRIPTEN__
-  js_set_ready();
+  js_set_ready(ready);
 #else
   std::clog << "WARNING: emscripten not enabled, cannot call js_set_ready()!"
             << std::endl;
@@ -40,6 +46,16 @@ void call_js_set_choices(const char *first, const char *second,
 #endif
 }
 
+void call_js_request_update() {
+#ifdef __EMSCRIPTEN__
+  js_request_update();
+#else
+  std::clog
+      << "WARNING: emscripten not enabled, cannot call js_request_update()!"
+      << std::endl;
+#endif
+}
+
 int call_js_get_canvas_width() {
 
 #ifdef __EMSCRIPTEN__
index 41209dbaf270519328587a7310d40bc16dc0377d..ee0234508e08704dca91e42c957bde1c2a4f45d6 100644 (file)
--- a/src/ems.h
+++ b/src/ems.h
@@ -1,9 +1,10 @@
 #ifndef ROCK_PAPER_SCISSORS_DUEL_EMSCRIPTEN_H_
 #define ROCK_PAPER_SCISSORS_DUEL_EMSCRIPTEN_H_
 
-extern void call_js_set_ready();
+extern void call_js_set_ready(bool ready = true);
 extern void call_js_set_choices(const char *first, const char *second,
                                 const char *third);
+extern void call_js_request_update();
 extern int call_js_get_canvas_width();
 extern int call_js_get_canvas_height();
 
index e7f992a6b70954b21dbd5021dfa9fe21d4f2cf4d..35f010a9c10596fa77025a1f93312413912433e1 100644 (file)
 // local includes
 #include "constants.h"
 #include "ems.h"
+#include "helpers.h"
 
 Game::Game()
     : spriteSheet(std::nullopt), status("Unknown status"), readyTimer(0.0F),
-      prevPos(0), cachedPos(0) {
+      resultsTimer(RESULTS_TIMER_MAX), scoreChangeTimer(SCORE_CHANGE_TIMER_MAX),
+      requestTimer(REQUEST_TIMER_MAX), prevPos(0), cachedPos(0) {
   spriteSheet = LoadTexture("resources/rockpaperscissorsSpriteSheet.png");
 
   picked[0] = 0;
@@ -29,21 +31,57 @@ void Game::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, int pos) {
+                        bool second_ready, int pos, int matchup_idx) {
+  // TODO DEBUG
+  if (std::strcmp(playerOne, currentPlayer) == 0) {
+    std::clog << "update_state:\n"
+              << "  is p1: "
+              << (std::strcmp(playerOne, currentPlayer) == 0 ? "true" : "false")
+              << std::endl
+              << "  p1: " << first_first << ", " << first_second << ", "
+              << first_third << "\n  p2: " << second_first << ", "
+              << second_second << ", " << second_third << "\nfirst is "
+              << (first_ready ? "ready" : "not ready") << "\nsecond is "
+              << (second_ready ? "ready" : "not ready") << "\npos: " << pos
+              << " matchup_idx: " << matchup_idx << std::endl;
+    std::clog << "flags: " << flags.to_string().substr(32 - 13) << std::endl;
+  }
   // TODO handle changing choices from r/p/s to w/l and etc.
   if (playerOne) {
     this->playerOne = playerOne;
-    opponentPicked[0] = second_first;
-    opponentPicked[1] = second_second;
-    opponentPicked[2] = second_third;
   }
   if (playerTwo) {
     this->playerTwo = playerTwo;
-    opponentPicked[0] = first_first;
-    opponentPicked[1] = first_second;
-    opponentPicked[2] = first_third;
   }
 
+  if (std::strcmp(playerOne, currentPlayer) == 0) {
+    isPlayerOne = true;
+    if (Helpers::isValidChoice(second_first) &&
+        Helpers::isValidChoice(second_second) &&
+        Helpers::isValidChoice(second_third)) {
+      opponentPicked[0] = second_first;
+      opponentPicked[1] = second_second;
+      opponentPicked[2] = second_third;
+    }
+  } else if (std::strcmp(playerTwo, currentPlayer) == 0) {
+    isPlayerOne = false;
+    if (Helpers::isValidChoice(first_first) &&
+        Helpers::isValidChoice(first_second) &&
+        Helpers::isValidChoice(first_third)) {
+      opponentPicked[0] = first_first;
+      opponentPicked[1] = first_second;
+      opponentPicked[2] = first_third;
+    }
+  } else {
+    isPlayerOne = false;
+  }
+
+  if ((!flags.test(10) && first_ready) || (!flags.test(11) && second_ready)) {
+    flags.set(12);
+  }
+  flags.set(10, first_ready);
+  flags.set(11, second_ready);
+
   if (std::strcmp(currentPlayer, "undefined") == 0) {
     status = "Watching a Game...";
     flags.set(2);
@@ -59,12 +97,12 @@ void Game::update_state(const char *playerOne, const char *playerTwo,
     cachedPos = pos;
   }
 
-  if (flags.test(0) && flags.test(3) && first_ready && second_ready) {
-    flags.reset(3);
-    flags.set(4);
-  } else if (flags.test(0) && flags.test(4) && first_first == 0 &&
-             first_second == 0 && first_third == 0 && second_first == 0 &&
-             second_second == 0 && second_third == 0) {
+  if (flags.test(0) && flags.test(4) && flags.test(6) && flags.test(7) &&
+      flags.test(8) && first_first == '?' && first_second == '?' &&
+      first_third == '?' && second_first == '?' && second_second == '?' &&
+      second_third == '?') {
+    std::cout << "Resetting for next round" << (isPlayerOne ? " (1) " : " (2) ")
+              << "..." << std::endl;
     flags.reset(0);
     flags.reset(1);
     flags.reset(3);
@@ -73,13 +111,25 @@ void Game::update_state(const char *playerOne, const char *playerTwo,
     flags.reset(6);
     flags.reset(7);
     flags.reset(8);
+    flags.reset(9);
+    flags.reset(10);
+    flags.reset(11);
+    flags.reset(12);
 
     readyTimer = 0;
-    resultsTimer = 0;
+    resultsTimer = RESULTS_TIMER_MAX;
 
     picked[0] = 0;
     picked[1] = 0;
     picked[2] = 0;
+
+    opponentPicked[0] = 0;
+    opponentPicked[1] = 0;
+    opponentPicked[2] = 0;
+
+    call_js_set_ready(false);
+
+    std::clog << "flags: " << flags.to_string().substr(32 - 13) << std::endl;
   }
 }
 
@@ -93,12 +143,22 @@ void Game::update_impl() {
     return;
   }
 
-  readyTimer -= GetFrameTime();
+  const float dt = GetFrameTime();
+
+  readyTimer -= dt;
   if (readyTimer <= 0.0F) {
     readyTimer = READY_TIMER_MAX;
     flags.flip(1);
   }
 
+  if (prevPos != cachedPos) {
+    scoreChangeTimer -= dt;
+    if (scoreChangeTimer <= 0) {
+      scoreChangeTimer = SCORE_CHANGE_TIMER_MAX;
+      prevPos = cachedPos;
+    }
+  }
+
   if (IsMouseButtonPressed(0) && !flags.test(0)) {
     int triple_single_width = GetScreenWidth() / 3.0F + 0.5F;
     if (triple_single_width > ICON_MAX_WIDTH) {
@@ -181,7 +241,7 @@ void Game::update_impl() {
              GetTouchY() <= GetScreenHeight() - triple_single_width * 2) {
       if (picked[0] != 0 && picked[1] != 0 && picked[2] != 0 &&
           !flags.test(0)) {
-        call_js_set_ready();
+        call_js_set_ready(true);
         flags.set(0);
         flags.set(3);
       }
@@ -202,24 +262,57 @@ void Game::update_impl() {
     status = "Pick Moves!";
   }
 
-  if (flags.test(0) && !flags.test(3) && flags.test(4)) {
+  if (flags.test(0) && flags.test(3) && flags.test(10) && flags.test(11)) {
+    char buf[6] = {picked[0], 0, picked[1], 0, picked[2], 0};
+    call_js_set_choices(&buf[0], &buf[2], &buf[4]);
+    flags.reset(3);
+    flags.set(4);
+  } else if (flags.test(0) && !flags.test(3) && flags.test(4)) {
     // updates for result animations
 
     if (flags.test(5)) {
       flags.reset(5);
+      flags.reset(9);
       resultsTimer = RESULTS_TIMER_MAX;
+    } else if (flags.test(9)) {
+      if (!flags.test(8)) {
+        call_js_set_ready(true);
+        flags.reset(9);
+        flags.set(5);
+      }
+    } else {
+      resultsTimer -= dt;
+      if (resultsTimer <= 0) {
+        resultsTimer = RESULTS_TIMER_MAX;
+        if (!flags.test(6)) {
+          flags.set(6);
+          flags.set(9);
+          call_js_set_ready(true);
+        } else if (!flags.test(7)) {
+          flags.set(7);
+          flags.set(9);
+          call_js_set_ready(true);
+        } else if (!flags.test(8)) {
+          flags.set(8);
+          flags.set(9);
+          call_js_set_ready(true);
+        }
+      }
     }
+  }
 
-    resultsTimer -= GetFrameTime();
-    if (resultsTimer <= 0) {
-      resultsTimer = RESULTS_TIMER_MAX;
-      if (!flags.test(6)) {
-        flags.set(6);
-      } else if (!flags.test(7)) {
-        flags.set(7);
-      } else if (!flags.test(8)) {
-        flags.set(8);
-      }
+  if (flags.test(12) && flags.test(10) && flags.test(11) &&
+      prevPos == cachedPos && is_choices_set() && is_opponent_choices_set()) {
+    flags.reset(12);
+    call_js_request_update();
+    std::cout << "Requesting update..." << std::endl;
+  }
+
+  requestTimer -= dt;
+  if (requestTimer <= 0.0F) {
+    if (flags.test(10) && flags.test(11)) {
+      call_js_request_update();
+      std::cout << "Requesting update (timer)..." << std::endl;
     }
   }
 }
@@ -228,7 +321,8 @@ void Game::draw_impl() {
   if (flags.test(2)) {
     BeginDrawing();
     ClearBackground(BLACK);
-    DrawText(status.c_str(), 0, 0, 30, RAYWHITE);
+    draw_score();
+    DrawText(status.c_str(), 0, 20, 30, RAYWHITE);
     EndDrawing();
     return;
   }
@@ -243,46 +337,59 @@ void Game::draw_impl() {
     }
 
     if (flags.test(0)) {
+      draw_choice(0, picked[0], false, triple_single_width * 2.0F, WHITE);
+      draw_choice(1, picked[1], false, triple_single_width * 2.0F, WHITE);
+      draw_choice(2, picked[2], false, triple_single_width * 2.0F, WHITE);
       float ratio = 1.0F - resultsTimer / RESULTS_TIMER_MAX;
+      char otherPicked =
+          Helpers::isValidChoice(opponentPicked[0]) ? opponentPicked[0] : '?';
       if (!flags.test(6)) {
         if (ratio < 1.0F) {
-          draw_choice(0, opponentPicked[0], false, triple_single_width,
+          draw_choice(0, otherPicked, false, triple_single_width,
                       {255, 255, 255, (unsigned char)(ratio * 255.0F)});
           draw_qm(0, false, triple_single_width,
                   {255, 255, 255, (unsigned char)((1.0F - ratio) * 255.0f)});
         } else {
-          draw_choice(0, opponentPicked[0], false, triple_single_width);
+          draw_choice(0, otherPicked, false, triple_single_width);
         }
       } else {
-        draw_choice(0, opponentPicked[0], false, triple_single_width);
+        draw_choice(0, otherPicked, false, triple_single_width);
       }
 
+      otherPicked =
+          Helpers::isValidChoice(opponentPicked[1]) ? opponentPicked[1] : '?';
       if (!flags.test(7)) {
-        if (ratio < 1.0F) {
-          draw_choice(0, opponentPicked[1], false, triple_single_width,
+        if (!flags.test(6)) {
+          draw_qm(1, false, triple_single_width, WHITE);
+        } else if (ratio < 1.0F) {
+          draw_choice(1, otherPicked, false, triple_single_width,
                       {255, 255, 255, (unsigned char)(ratio * 255.0F)});
-          draw_qm(0, false, triple_single_width,
+          draw_qm(1, false, triple_single_width,
                   {255, 255, 255, (unsigned char)((1.0F - ratio) * 255.0f)});
         } else {
-          draw_choice(0, opponentPicked[1], false, triple_single_width);
+          draw_choice(1, otherPicked, false, triple_single_width);
         }
       } else {
-        draw_choice(0, opponentPicked[1], false, triple_single_width);
+        draw_choice(1, otherPicked, false, triple_single_width);
       }
 
+      otherPicked =
+          Helpers::isValidChoice(opponentPicked[2]) ? opponentPicked[2] : '?';
       if (!flags.test(8)) {
-        if (ratio < 1.0F) {
-          draw_choice(0, opponentPicked[2], false, triple_single_width,
+        if (!flags.test(7)) {
+          draw_qm(2, false, triple_single_width, WHITE);
+        } else if (ratio < 1.0F) {
+          draw_choice(2, otherPicked, false, triple_single_width,
                       {255, 255, 255, (unsigned char)(ratio * 255.0F)});
-          draw_qm(0, false, triple_single_width,
+          draw_qm(2, false, triple_single_width,
                   {255, 255, 255, (unsigned char)((1.0F - ratio) * 255.0f)});
         } else {
-          draw_choice(0, opponentPicked[2], false, triple_single_width);
+          draw_choice(2, otherPicked, false, triple_single_width);
         }
       } else {
-        draw_choice(0, opponentPicked[2], false, triple_single_width);
+        draw_choice(2, otherPicked, false, triple_single_width);
       }
-    } else {
+    } else { // flags.test(0)
       unsigned char value = 0;
       if (flags.test(1)) {
         // fade ready bg to gray
@@ -327,8 +434,10 @@ void Game::draw_impl() {
                     {200, 200, 200, 255});
 
       for (unsigned int i = 0; i < 3; ++i) {
-        draw_choice(i, picked[i], true,
-                    (float)GetScreenHeight() - triple_single_width * 2.0F);
+        if (picked[i] != 0) {
+          draw_choice(i, picked[i], true,
+                      (float)GetScreenHeight() - triple_single_width * 2.0F);
+        }
       }
 
       DrawRectangle(0, GetScreenHeight() - triple_single_width,
@@ -339,7 +448,8 @@ void Game::draw_impl() {
       draw_choice(2, 's', true, (float)GetScreenHeight() - triple_single_width);
     }
   }
-  DrawText(status.c_str(), 0, 0, 20, RAYWHITE);
+  draw_score();
+  DrawText(status.c_str(), 0, 20, 20, RAYWHITE);
   EndDrawing();
 }
 
@@ -379,7 +489,8 @@ void Game::draw_choice(const unsigned int idx, const char choice,
   default:
     // Should never happen.
     std::cerr << "WARNING: Invalid choice passed to draw_choice()!"
-              << std::endl;
+                 " (value is \""
+              << choice << "\" or \"" << (int)choice << "\")" << std::endl;
     break;
   }
 }
@@ -434,13 +545,13 @@ void Game::draw_helper_coord(float *x, float *width, const unsigned int idx,
 
       switch (idx) {
       case 0:
-        *x = (GetScreenWidth() - *width * 4.0F) / 2.0F;
+        *x = GetScreenWidth() - *width * 4.0F;
         break;
       case 1:
-        *x = (GetScreenWidth() - *width * 3.0F) / 2.0F;
+        *x = GetScreenWidth() - *width * 3.0F;
         break;
       case 2:
-        *x = (GetScreenWidth() - *width * 2.0F) / 2.0F;
+        *x = GetScreenWidth() - *width * 2.0F;
         break;
       default:
         // Should never happen.
@@ -451,3 +562,32 @@ void Game::draw_helper_coord(float *x, float *width, const unsigned int idx,
     }
   }
 }
+
+bool Game::is_choices_set() const {
+  return picked[0] != 0 && picked[1] != 0 && picked[2] != 0;
+}
+
+bool Game::is_opponent_choices_set() const {
+  return opponentPicked[0] != 0 && opponentPicked[1] != 0 &&
+         opponentPicked[2] != 0 && opponentPicked[0] != '?' &&
+         opponentPicked[1] != '?' && opponentPicked[2] != '?';
+}
+
+void Game::draw_score() const {
+  char buf[6] = {prevPos < 0 ? '-' : ' ',
+                 prevPos < 0 ? (char)('0' - prevPos) : (char)('0' + prevPos),
+                 0,
+                 cachedPos < 0 ? '-' : ' ',
+                 cachedPos < 0 ? (char)('0' - cachedPos)
+                               : (char)('0' + cachedPos),
+                 0};
+  if (prevPos != cachedPos) {
+    float ratio = 1.0F - scoreChangeTimer / SCORE_CHANGE_TIMER_MAX;
+    DrawText(&buf[3], 0, 0, 20,
+             {255, 255, 255, (unsigned char)(ratio * 255.0F)});
+    DrawText(buf, 0, 0, 20,
+             {255, 255, 255, (unsigned char)((1.0F - ratio) * 255.0F)});
+  } else {
+    DrawText(&buf[3], 0, 0, 20, WHITE);
+  }
+}
index 53732241dc0961daabd8c20bdbb3824973080b46..0d9f6c803176234c4266b3e1f063d5952f6be2b3 100644 (file)
@@ -17,7 +17,7 @@ public:
                     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, int pos);
+                    bool second_ready, int pos, int matchup_idx);
 
   void do_update();
 
@@ -34,6 +34,11 @@ private:
   void draw_helper_coord(float *x, float *width, const unsigned int idx,
                          const bool using_triple);
 
+  bool is_choices_set() const;
+  bool is_opponent_choices_set() const;
+
+  void draw_score() const;
+
   std::optional<Texture2D> spriteSheet;
   std::string playerOne;
   std::string playerTwo;
@@ -48,10 +53,16 @@ private:
    * 6 - revealed first moves
    * 7 - revealed second moves
    * 8 - revealed third moves
+   * 9 - finished revealing a move
+   * 10 - first ready
+   * 11 - second ready
+   * 12 - ready state dirty
    */
   std::bitset<32> flags;
   float readyTimer;
   float resultsTimer;
+  float scoreChangeTimer;
+  float requestTimer;
   int prevPos;
   int cachedPos;
   char picked[3];
diff --git a/src/helpers.cc b/src/helpers.cc
new file mode 100644 (file)
index 0000000..d8c277e
--- /dev/null
@@ -0,0 +1,5 @@
+#include "helpers.h"
+
+bool Helpers::isValidChoice(char choice) {
+  return choice == 'r' || choice == 'p' || choice == 's';
+}
diff --git a/src/helpers.h b/src/helpers.h
new file mode 100644 (file)
index 0000000..9dcc0ce
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef ROCK_PAPER_SCISSORS_DUEL_HELPERS_H_
+#define ROCK_PAPER_SCISSORS_DUEL_HELPERS_H_
+
+namespace Helpers {
+
+extern bool isValidChoice(char choice);
+
+}
+
+#endif
index c90ddccb13f7302466f767d09dc795b83efec78b..0e3c7b6e50dbb3c1b74261a4ef644f6ab7fcfdab 100644 (file)
@@ -25,11 +25,11 @@ void 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,
-    int pos) {
+    int pos, int matchup_idx) {
   ((Game *)global_game_ptr)
       ->update_state(playerOne, playerTwo, currentPlayer, first_first,
                      first_second, first_third, second_first, second_second,
-                     second_third, first_ready, second_ready, pos);
+                     second_third, first_ready, second_ready, pos, matchup_idx);
 }
 
 } // end em exposed functions
index 8ff9c62ab9a2e3a946df02bb23b2af26c5bf8047..4f6f210caadf7d44383a3ff0c6ef12657ecb1fbd 100644 (file)
@@ -7,12 +7,14 @@ endif
 SOURCES = \
                ../src/main.cc \
                ../src/ems.cc \
-               ../src/game.cc
+               ../src/game.cc \
+               ../src/helpers.cc
 
 HEADERS = \
                ../src/constants.h \
                ../src/ems.h \
-               ../src/game.h
+               ../src/game.h \
+               ../src/helpers.h
 
 CXX = source ${HOME}/git/emsdk/emsdk_env.sh && em++
 
@@ -33,10 +35,10 @@ ${OUTDIR}/rock_paper_scissors_duel.html: ${SOURCES} ${HEADERS} ${OUTDIR}/client.
 ${OUTDIR}:
        mkdir ${OUTDIR}
 
-${OUTDIR}/logic.js:
+${OUTDIR}/logic.js: logic.js
        cp logic.js ${OUTDIR}/
 
-${OUTDIR}/client.js:
+${OUTDIR}/client.js: client.js
        cp client.js ${OUTDIR}/
 
 .PHONY: clean format index.html
index 5d35abdf7d1cbee9932cc1eee15454442cc7760c..909813d2fac3fec270dab256d035cec8800b7b23 100644 (file)
@@ -1,6 +1,6 @@
 Rune.initClient({
     visualUpdate: ({ newGame, yourPlayerId}) => {
-        const { player1, player2, first_choices, second_choices, first_ready, second_ready, pos } = newGame;
+        const { player1, player2, first_choices, second_choices, ready, pos, matchup_idx } = newGame;
 
         Module.ccall('game_visual_update',
             undefined,
@@ -8,11 +8,16 @@ Rune.initClient({
                 'number', 'number', 'number',
                 'number', 'number', 'number',
                 'boolean', 'boolean',
-                'number'],
-            [player1, player2, yourPlayerId === undefined ? 'undefined' : yourPlayerId,
-                first_choices[0], first_choices[1], first_choices[2],
-                second_choices[0], second_choices[1], second_choices[2],
-                first_ready, second_ready,
-                pos]);
+                'number', 'number'],
+            [player1, player2,
+                yourPlayerId === undefined ? 'undefined' : yourPlayerId,
+                first_choices[0].charCodeAt(0),
+                first_choices[1].charCodeAt(0),
+                first_choices[2].charCodeAt(0),
+                second_choices[0].charCodeAt(0),
+                second_choices[1].charCodeAt(0),
+                second_choices[2].charCodeAt(0),
+                ready[0], ready[1],
+                pos, matchup_idx]);
     },
 });
index d7250e3efd117cb10b43f31881f2a27699d2704e..e03409cbae883d6889876357e9b318f58a9db068 100644 (file)
@@ -4,15 +4,15 @@ Rune.initLogic({
     setup: (players) => ({
         player1: players[0],
         player2: players[1],
-        first_choices: new Array(3).fill(null),
-        second_choices: new Array(3).fill(null),
-        first_ready: false,
-        second_ready: false,
+        first_choices: new Array(3).fill('?'),
+        second_choices: new Array(3).fill('?'),
+        ready: new Array(2).fill(false),
         pos: 0,
+        matchup_idx: 0,
     }),
     actions: {
-        set_choices: (first, second, third, { game, playerId }) => {
-            if (!game.first_ready || !game.second_ready) {
+        set_choices: ({first, second, third}, { game, playerId }) => {
+            if (!game.ready[0] || !game.ready[1]) {
                 throw Rune.invalidAction();
             }
 
@@ -20,7 +20,7 @@ Rune.initLogic({
 
             function is_choices_filled(choices) {
                 for (let i = 0; i < 3; ++i) {
-                    if (choices[i] === null) {
+                    if (choices[i] === null || choices[i] === '?') {
                         return false;
                     }
                 }
@@ -52,50 +52,67 @@ Rune.initLogic({
                 game.second_choices[1] = second;
                 game.second_choices[2] = third;
             }
+        },
+        set_ready: ({ is_ready }, { game, playerId }) => {
+            let is_first = game.player1 === playerId;
 
+            if (is_first) {
+                game.ready[0] = is_ready;
+            } else {
+                game.ready[1] = is_ready;
+            }
+        },
+        request_update: (unused, {game, playerId}) => {
+            function is_choices_filled(choices) {
+                for (let i = 0; i < 3; ++i) {
+                    if (choices[i] === null || choices[i] === '?') {
+                        return false;
+                    }
+                }
+                return true;
+            }
 
-            if (!is_choices_filled(game.first_choices)
+            if (!game.ready[0]
+                    || !game.ready[1]
+                    || !is_choices_filled(game.first_choices)
                     || !is_choices_filled(game.second_choices)) {
                 return;
             }
 
             // Both sides are ready, iterate through matchups
 
-            let has_remaining = false;
-
-            for (let i = 0; i < 3; ++i) {
-                // Get next matchup
-                if (game.first_choices[i] === 'r'
-                        || game.first_choices[i] === 'p'
-                        || game.first_choices[i] === 's') {
-                    // check if first won the matchup
-                    if ((game.first_choices[i] === 'r' && game.second_choices[i] === 's')
-                            || (game.first_choices[i] === 'p' && game.second_choices[i] === 'r')
-                            || (game.first_choices[i] === 's' && game.second_choices[i] === 'p')) {
-                        game.first_choices[i] = 'w';
-                        game.second_choices[i] = 'l';
-                        game.pos = game.pos + 1;
-                    }
-                    // check if second won the matchup
-                    else if ((game.first_choices[i] === 'r' && game.second_choices[i] === 'p')
-                            || (game.first_choices[i] === 'p' && game.second_choices[i] === 's')
-                            || (game.first_choices[i] === 's' && game.second_choices[i] === 'r')) {
-                        game.first_choices[i] = 'l';
-                        game.second_choices[i] = 'w';
-                        game.pos = game.pos - 1;
-                    }
-                    // matchup was a draw
-                    else {
-                        game.first_choices[i] = 'd';
-                        game.second_choices[i] = 'd';
-                    }
-                    has_remaining = i === 2 ? false : true;
-                }
+            // check if first won the matchup
+            if ((game.first_choices[game.matchup_idx] === 'r'
+                        && game.second_choices[game.matchup_idx] === 's')
+                    || (game.first_choices[game.matchup_idx] === 'p'
+                        && game.second_choices[game.matchup_idx] === 'r')
+                    || (game.first_choices[game.matchup_idx] === 's'
+                        && game.second_choices[game.matchup_idx] === 'p')) {
+                //game.first_choices[game.matchup_idx] = 'w';
+                //game.second_choices[game.matchup_idx] = 'l';
+                game.pos = game.pos + 1;
+            }
+            // check if second won the matchup
+            else if ((game.first_choices[game.matchup_idx] === 'r'
+                        && game.second_choices[game.matchup_idx] === 'p')
+                    || (game.first_choices[game.matchup_idx] === 'p'
+                        && game.second_choices[game.matchup_idx] === 's')
+                    || (game.first_choices[game.matchup_idx] === 's'
+                        && game.second_choices[game.matchup_idx] === 'r')) {
+                //game.first_choices[game.matchup_idx] = 'l';
+                //game.second_choices[game.matchup_idx] = 'w';
+                game.pos = game.pos - 1;
             }
+            // matchup was a draw
+            //else {
+                //game.first_choices[game.matchup_idx] = 'd';
+                //game.second_choices[game.matchup_idx] = 'd';
+            //}
+            game.matchup_idx = game.matchup_idx + 1;
 
-            game.first_ready = false;
-            game.second_ready = false;
-            if (!has_remaining) {
+            game.ready[0] = false;
+            game.ready[1] = false;
+            if (game.matchup_idx >= 3) {
                 if (game.pos <= -3) {
                     // second won
                     Rune.gameOver();
@@ -105,20 +122,12 @@ Rune.initLogic({
                 } else {
                     // game is still going
                     for (let i = 0; i < 3; ++i) {
-                        game.first_choices[i] = null;
-                        game.second_choices[i] = null;
+                        game.first_choices[i] = '?';
+                        game.second_choices[i] = '?';
                     }
+                    game.matchup_idx = 0;
                 }
             }
         },
-        set_ready: (unused, { game, playerId }) => {
-            let is_first = game.player1 === playerId;
-
-            if (is_first) {
-                game.first_ready = true;
-            } else {
-                game.second_ready = true;
-            }
-        },
     },
 })