summaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/dartboat_wasm.c301
-rw-r--r--web/web_control.c257
-rw-r--r--web/web_control.h18
-rw-r--r--web/web_prompt.c57
-rw-r--r--web/web_prompt.h5
5 files changed, 329 insertions, 309 deletions
diff --git a/web/dartboat_wasm.c b/web/dartboat_wasm.c
index c245771..42535aa 100644
--- a/web/dartboat_wasm.c
+++ b/web/dartboat_wasm.c
@@ -1,314 +1,15 @@
-#include "web_match.h"
+#include "web_control.h"
#include "web_opts.h"
#include "web_prompt.h"
#include "web_svg.h"
-#include "web_ui.h"
-#include "checkouts.h"
#include "comp.h"
-#include <math.h>
#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
#include <time.h>
#include <emscripten/emscripten.h>
-#include "web_match.h"
-
-void set_prompt_mode(enum prompt_mode mode)
-{
- pm = mode;
-
- if (pm != PM_DARTBOARD)
- EM_ASM(setPromptActive());
- else
- EM_ASM(setPromptInactive());
-
- EM_ASM({setKeypad($0)}, pm == PM_DARTBOARD ? "dartboard" :
- pm == PM_SELECT_MODE ? "select_mode" : "default");
-}
-
-void set_active_player(int pn)
-{
- state->active_player = pn;
- state->active_leg = state->legs[pn-1];
- EM_ASM({setPlayerActive($0)}, pn);
-
- if (state->mode == M_PVC && pn == 2) {
- EM_ASM({promptMsgL($0)}, "Bot is throwing…");
- set_prompt_mode(PM_DARTBOARD);
- } else {
- EM_ASM({promptMsgL($0)}, "Enter points:");
- EM_ASM({setKeyLabel($0, $1)}, "submit", "OK");
- EM_ASM({setKeyLabel($0, $1)}, "rem", "REMAINING");
- set_prompt_mode(PM_VISIT);
- }
- EM_ASM({promptMsgR($0)}, "");
-}
-
-void toggle_active_player()
-{
- set_active_player(3 - state->active_player);
-}
-
-EMSCRIPTEN_KEEPALIVE
-void update_user_rem_from_pts(int pts)
-{
- update_player_rem(state->active_player, state->active_leg->rem - pts);
-}
-
-void handle_next();
-EMSCRIPTEN_KEEPALIVE
-void end_boat_visit(int rem, double avg)
-{
- EM_ASM(svgClearPoints());
- update_player_rem(2, rem);
- EM_ASM({updatePlayerAvg($0, $1)}, 2, avg);
- EM_ASM({setPromptInput($0)}, "");
- EM_ASM({promptMsgR($0)}, "");
-
- draw_visits();
- handle_next();
-}
-
-EMSCRIPTEN_KEEPALIVE
-void boat_visit()
-{
- struct leg *l = state->legs[1];
- if (state->boat_undone) {
- --state->boat_undone;
- l->rem = l->visits[l->n_visits++].rem;
- } else {
- comp_visit(l);
- }
-
- struct visit *v = l->visits + l->n_visits - 1;
- double avg = v->rem > 0 ?
- (double)(l->start - l->rem) / l->n_visits :
- (double)l->start / (((l->n_visits - 1) * 3) + v->n_darts) * 3;
-
- if (!delay_ms) {
- end_boat_visit(l->rem, avg);
- return;
- }
-
- int pts = 0;
- char str[15] = {0};
- size_t len_str = 0;
-
- for (int i = 0; i < v->n_darts; ++i) {
- pts += segment_points(v->darts[i]);
- char *seg_name = segment_name(v->darts[i]);
- len_str += sprintf(str + len_str, i ? "-%s" : "%s", seg_name);
- free(seg_name);
-
- struct ccoords c = v->ccoords[i];
-
- char *tmp = malloc(len_str + 1); // free in draw_boat_throwing
- memcpy(tmp, str, len_str + 1);
- EM_ASM({scheduleCCall($0, $1, $2, $3, $4, $5)}, "draw_boat_throwing",
- delay_ms * (i+1), pts, tmp, c.x, c.y);
- }
-
- EM_ASM({scheduleCCall($0, $1, $2, $3)}, "end_boat_visit",
- delay_ms * (v->n_darts + 1), l->rem, avg);
-}
-
-void prompt_num_darts()
-{
- set_prompt_mode(PM_NUM_DARTS);
- EM_ASM({promptMsgL($0)}, "Darts needed?");
- EM_ASM({promptMsgR($0)}, "");
- EM_ASM({setKeyLabel($0, $1)}, "submit", "OK");
- EM_ASM({setKeyLabel($0, $1)}, "rem", "REMAINING");
-}
-
-void prompt_end_match()
-{
- EM_ASM(setPlayerActive()); // sets all inactive
- set_prompt_mode(PM_END_MATCH);
- EM_ASM({promptMsgL($0)},
- state->mode == M_PVC && state->legs[1]->rem <= 0 ? "Bot wins. :(" :
- "You win! :)");
- EM_ASM({promptMsgR($0)}, "");
- EM_ASM({setKeyLabel($0, $1)}, "submit", "END MATCH");
- EM_ASM({setKeyLabel($0, $1)}, "rem", "REMATCH");
-}
-
-void prompt_select_mode()
-{
- for (int pn = 1; pn < 3; ++pn) {
- EM_ASM({hidePlayerInfo($0)}, pn);
- clear_player_info(pn);
- }
- EM_ASM(clearVisits());
-
- set_prompt_mode(PM_SELECT_MODE);
- EM_ASM({promptMsgL($0)}, "Select match mode:");
- EM_ASM({promptMsgR($0)}, "");
-}
-
-void handle_next()
-{
- if (!state) {
- prompt_select_mode();
- } else if (is_match_over()) {
- if (state->num_darts ||
- (state->mode == M_PVC && state->legs[1]->rem <= 0))
- prompt_end_match();
- else
- prompt_num_darts();
- } else {
- if (state->mode == M_P) {
- set_active_player(1);
- } else {
- if (state->active_player)
- toggle_active_player();
- else
- set_active_player(1);
-
- if (state->mode == M_PVC && state->active_player == 2)
- boat_visit();
- }
- }
-}
-
-EMSCRIPTEN_KEEPALIVE
-void user_visit(int points)
-{
- if (!is_points_valid(points, state->active_leg->rem)) {
- EM_ASM(oi());
- return;
- }
-
- struct leg *l = state->active_leg;
- if (l->n_visits == l->size_visits)
- leg_grow_visits(l);
- struct visit *v = l->visits + l->n_visits++;
- v->points = points;
- l->rem -= points;
- v->rem = l->rem;
- update_player_rem(state->active_player, l->rem);
-
- if (v->rem > 0)
- update_player_avg(state->active_player, 0);
-
- draw_visits();
- handle_next();
-}
-
-EMSCRIPTEN_KEEPALIVE
-void user_visit_to_rem(int rem)
-{
- user_visit(state->legs[0]->rem - rem);
-}
-
-EMSCRIPTEN_KEEPALIVE
-void user_undo()
-{
- if (!state->legs[0]->n_visits) {
- EM_ASM(oi());
- return;
- }
-
- if (state->num_darts) {
- state->num_darts = 0;
- EM_ASM({updatePlayerAvg($0, $1)}, state->active_player,
- ((double)(state->active_leg->start -
- state->active_leg->visits[
- state->active_leg->n_visits-2].rem) /
- (state->active_leg->n_visits-1)));
- handle_next();
- return;
- }
-
- if (state->mode == M_PVC) {
- set_active_player(1);
- } else if (state->mode == M_PVP) {
- if (is_match_over())
- set_active_player(state->active_player);
- else
- toggle_active_player();
- }
-
- struct leg *l = state->active_leg;
- struct visit *v = l->visits + --l->n_visits;
- l->rem += v->points;
- memcpy(v, 0, sizeof(*v));
-
- if (state->mode == M_PVC && state->legs[1]->n_visits > l->n_visits) {
- state->legs[1]->rem +=
- state->legs[1]->visits[--state->legs[1]->n_visits].points;
- ++state->boat_undone;
- }
-
- update_player_avg(state->active_player, 0);
- update_player_rem(state->active_player, l->rem);
- if (state->mode == M_PVC) {
- update_player_avg(2, 0);
- update_player_rem(2, state->legs[1]->rem);
- }
-
- draw_visits();
-
- if (state->mode != M_P) // FIXME avoid double toggle?
- toggle_active_player();
- handle_next();
-}
-
-EMSCRIPTEN_KEEPALIVE
-void user_num_darts(int n)
-{
- if (n < 1 || n > 3) {
- EM_ASM(oi());
- return;
- }
-
- state->num_darts = n;
- update_player_avg(state->active_player, n);
-
- handle_next();
-}
-
-EMSCRIPTEN_KEEPALIVE
-void start_match(int mode)
-{
- if (mode < M_FIRST || mode > M_LAST) {
- EM_ASM(oi());
- return;
- }
-
- if (state) free_state(); // rematch gets us here
- state = calloc(1, sizeof(*state));
- state->mode = mode;
- state->legs[0] = leg_init(501, mode == M_PVP ? "Player 1" : "User");
- state->legs[1] = leg_init(501, mode == M_PVC ? "Bot" : "Player 2");
-
- EM_ASM({showPlayerInfo($0)}, 1);
- EM_ASM({updatePlayerName($0, $1)}, 1, state->legs[0]->name);
- update_player_rem(1, state->legs[0]->rem);
- EM_ASM({updatePlayerAvg($0, $1)}, 1, 0);
-
- if (mode != M_P) {
- EM_ASM({showPlayerInfo($0)}, 2);
- EM_ASM({updatePlayerName($0, $1)}, 2, state->legs[1]->name);
- update_player_rem(2, state->legs[1]->rem);
- EM_ASM({updatePlayerAvg($0, $1)}, 2, 0);
- }
-
- draw_visits();
- handle_next();
-}
-
-EMSCRIPTEN_KEEPALIVE
-void end_match()
-{
- if (state) free_state();
- handle_next();
-}
-
EMSCRIPTEN_KEEPALIVE
void init()
{
diff --git a/web/web_control.c b/web/web_control.c
new file mode 100644
index 0000000..b1e20bc
--- /dev/null
+++ b/web/web_control.c
@@ -0,0 +1,257 @@
+#include "web_control.h"
+#include "web_match.h"
+#include "web_opts.h"
+#include "web_prompt.h"
+#include "web_ui.h"
+
+#include "comp.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <emscripten/emscripten.h>
+
+void set_active_player(int pn)
+{
+ state->active_player = pn;
+ state->active_leg = state->legs[pn-1];
+ EM_ASM({setPlayerActive($0)}, pn);
+
+ if (state->mode == M_PVC && pn == 2) {
+ EM_ASM({promptMsgL($0)}, "Bot is throwing…");
+ set_prompt_mode(PM_DARTBOARD);
+ } else {
+ EM_ASM({promptMsgL($0)}, "Enter points:");
+ EM_ASM({setKeyLabel($0, $1)}, "submit", "OK");
+ EM_ASM({setKeyLabel($0, $1)}, "rem", "REMAINING");
+ set_prompt_mode(PM_VISIT);
+ }
+ EM_ASM({promptMsgR($0)}, "");
+}
+
+void toggle_active_player()
+{
+ set_active_player(3 - state->active_player);
+}
+
+EMSCRIPTEN_KEEPALIVE
+void update_user_rem_from_pts(int pts)
+{
+ update_player_rem(state->active_player, state->active_leg->rem - pts);
+}
+
+EMSCRIPTEN_KEEPALIVE
+void end_boat_visit(int rem, double avg)
+{
+ EM_ASM(svgClearPoints());
+ update_player_rem(2, rem);
+ EM_ASM({updatePlayerAvg($0, $1)}, 2, avg);
+ EM_ASM({setPromptInput($0)}, "");
+ EM_ASM({promptMsgR($0)}, "");
+
+ draw_visits();
+ handle_next();
+}
+
+EMSCRIPTEN_KEEPALIVE
+void boat_visit()
+{
+ struct leg *l = state->legs[1];
+ if (state->boat_undone) {
+ --state->boat_undone;
+ l->rem = l->visits[l->n_visits++].rem;
+ } else {
+ comp_visit(l);
+ }
+
+ struct visit *v = l->visits + l->n_visits - 1;
+ double avg = v->rem > 0 ?
+ (double)(l->start - l->rem) / l->n_visits :
+ (double)l->start / (((l->n_visits - 1) * 3) + v->n_darts) * 3;
+
+ if (!delay_ms) {
+ end_boat_visit(l->rem, avg);
+ return;
+ }
+
+ int pts = 0;
+ char str[15] = {0};
+ size_t len_str = 0;
+
+ for (int i = 0; i < v->n_darts; ++i) {
+ pts += segment_points(v->darts[i]);
+ char *seg_name = segment_name(v->darts[i]);
+ len_str += sprintf(str + len_str, i ? "-%s" : "%s", seg_name);
+ free(seg_name);
+
+ struct ccoords c = v->ccoords[i];
+
+ char *tmp = malloc(len_str + 1); // free in draw_boat_throwing
+ memcpy(tmp, str, len_str + 1);
+ EM_ASM({scheduleCCall($0, $1, $2, $3, $4, $5)}, "draw_boat_throwing",
+ delay_ms * (i+1), pts, tmp, c.x, c.y);
+ }
+
+ EM_ASM({scheduleCCall($0, $1, $2, $3)}, "end_boat_visit",
+ delay_ms * (v->n_darts + 1), l->rem, avg);
+}
+
+void handle_next()
+{
+ if (!state) {
+ prompt_select_mode();
+ } else if (is_match_over()) {
+ if (state->num_darts ||
+ (state->mode == M_PVC && state->legs[1]->rem <= 0))
+ prompt_end_match();
+ else
+ prompt_num_darts();
+ } else {
+ if (state->mode == M_P) {
+ set_active_player(1);
+ } else {
+ if (state->active_player)
+ toggle_active_player();
+ else
+ set_active_player(1);
+
+ if (state->mode == M_PVC && state->active_player == 2)
+ boat_visit();
+ }
+ }
+}
+
+EMSCRIPTEN_KEEPALIVE
+void user_visit(int points)
+{
+ if (!is_points_valid(points, state->active_leg->rem)) {
+ EM_ASM(oi());
+ return;
+ }
+
+ struct leg *l = state->active_leg;
+ if (l->n_visits == l->size_visits)
+ leg_grow_visits(l);
+ struct visit *v = l->visits + l->n_visits++;
+ v->points = points;
+ l->rem -= points;
+ v->rem = l->rem;
+ update_player_rem(state->active_player, l->rem);
+
+ if (v->rem > 0)
+ update_player_avg(state->active_player, 0);
+
+ draw_visits();
+ handle_next();
+}
+
+EMSCRIPTEN_KEEPALIVE
+void user_visit_to_rem(int rem)
+{
+ user_visit(state->legs[0]->rem - rem);
+}
+
+EMSCRIPTEN_KEEPALIVE
+void user_undo()
+{
+ if (!state->legs[0]->n_visits) {
+ EM_ASM(oi());
+ return;
+ }
+
+ if (state->num_darts) {
+ state->num_darts = 0;
+ EM_ASM({updatePlayerAvg($0, $1)}, state->active_player,
+ ((double)(state->active_leg->start -
+ state->active_leg->visits[
+ state->active_leg->n_visits-2].rem) /
+ (state->active_leg->n_visits-1)));
+ handle_next();
+ return;
+ }
+
+ if (state->mode == M_PVC) {
+ set_active_player(1);
+ } else if (state->mode == M_PVP) {
+ if (is_match_over())
+ set_active_player(state->active_player);
+ else
+ toggle_active_player();
+ }
+
+ struct leg *l = state->active_leg;
+ struct visit *v = l->visits + --l->n_visits;
+ l->rem += v->points;
+ memcpy(v, 0, sizeof(*v));
+
+ if (state->mode == M_PVC && state->legs[1]->n_visits > l->n_visits) {
+ state->legs[1]->rem +=
+ state->legs[1]->visits[--state->legs[1]->n_visits].points;
+ ++state->boat_undone;
+ }
+
+ update_player_avg(state->active_player, 0);
+ update_player_rem(state->active_player, l->rem);
+ if (state->mode == M_PVC) {
+ update_player_avg(2, 0);
+ update_player_rem(2, state->legs[1]->rem);
+ }
+
+ draw_visits();
+
+ if (state->mode != M_P) // FIXME avoid double toggle?
+ toggle_active_player();
+ handle_next();
+}
+
+EMSCRIPTEN_KEEPALIVE
+void user_num_darts(int n)
+{
+ if (n < 1 || n > 3) {
+ EM_ASM(oi());
+ return;
+ }
+
+ state->num_darts = n;
+ update_player_avg(state->active_player, n);
+
+ handle_next();
+}
+
+EMSCRIPTEN_KEEPALIVE
+void start_match(int mode)
+{
+ if (mode < M_FIRST || mode > M_LAST) {
+ EM_ASM(oi());
+ return;
+ }
+
+ if (state) free_state(); // rematch gets us here
+ state = calloc(1, sizeof(*state));
+ state->mode = mode;
+ state->legs[0] = leg_init(501, mode == M_PVP ? "Player 1" : "User");
+ state->legs[1] = leg_init(501, mode == M_PVC ? "Bot" : "Player 2");
+
+ EM_ASM({showPlayerInfo($0)}, 1);
+ EM_ASM({updatePlayerName($0, $1)}, 1, state->legs[0]->name);
+ update_player_rem(1, state->legs[0]->rem);
+ EM_ASM({updatePlayerAvg($0, $1)}, 1, 0);
+
+ if (mode != M_P) {
+ EM_ASM({showPlayerInfo($0)}, 2);
+ EM_ASM({updatePlayerName($0, $1)}, 2, state->legs[1]->name);
+ update_player_rem(2, state->legs[1]->rem);
+ EM_ASM({updatePlayerAvg($0, $1)}, 2, 0);
+ }
+
+ draw_visits();
+ handle_next();
+}
+
+EMSCRIPTEN_KEEPALIVE
+void end_match()
+{
+ if (state) free_state();
+ handle_next();
+}
diff --git a/web/web_control.h b/web/web_control.h
new file mode 100644
index 0000000..33cbd2c
--- /dev/null
+++ b/web/web_control.h
@@ -0,0 +1,18 @@
+#ifndef WEB_CONTROL_H
+#define WEB_CONTROL_H
+
+void set_active_player(int pn);
+void toggle_active_player();
+
+void start_match(int mode);
+void end_match();
+void user_visit(int points);
+void user_num_darts(int n);
+void user_undo();
+void user_visit_to_rem(int rem);
+void update_user_rem_from_pts(int pts);
+void end_boat_visit(int rem, double avg);
+
+void handle_next();
+
+#endif
diff --git a/web/web_prompt.c b/web/web_prompt.c
index 64a23fd..abc5a05 100644
--- a/web/web_prompt.c
+++ b/web/web_prompt.c
@@ -1,3 +1,4 @@
+#include "web_control.h"
#include "web_prompt.h"
#include "web_match.h"
#include "web_ui.h"
@@ -7,17 +8,55 @@
#include <emscripten/emscripten.h>
-// FIXME forward declaring these until the code is better modularised
-void start_match(int mode);
-void user_num_darts(int n);
-void user_visit(int points);
-void user_visit_to_rem(int rem);
-void end_match();
-void update_user_rem_from_pts(int pts);
-void user_undo();
-
enum prompt_mode pm;
+void set_prompt_mode(enum prompt_mode mode)
+{
+ pm = mode;
+
+ if (pm != PM_DARTBOARD)
+ EM_ASM(setPromptActive());
+ else
+ EM_ASM(setPromptInactive());
+
+ EM_ASM({setKeypad($0)}, pm == PM_DARTBOARD ? "dartboard" :
+ pm == PM_SELECT_MODE ? "select_mode" : "default");
+}
+
+void prompt_num_darts()
+{
+ set_prompt_mode(PM_NUM_DARTS);
+ EM_ASM({promptMsgL($0)}, "Darts needed?");
+ EM_ASM({promptMsgR($0)}, "");
+ EM_ASM({setKeyLabel($0, $1)}, "submit", "OK");
+ EM_ASM({setKeyLabel($0, $1)}, "rem", "REMAINING");
+}
+
+void prompt_end_match()
+{
+ EM_ASM(setPlayerActive()); // sets all inactive
+ set_prompt_mode(PM_END_MATCH);
+ EM_ASM({promptMsgL($0)},
+ state->mode == M_PVC && state->legs[1]->rem <= 0 ? "Bot wins. :(" :
+ "You win! :)");
+ EM_ASM({promptMsgR($0)}, "");
+ EM_ASM({setKeyLabel($0, $1)}, "submit", "END MATCH");
+ EM_ASM({setKeyLabel($0, $1)}, "rem", "REMATCH");
+}
+
+void prompt_select_mode()
+{
+ for (int pn = 1; pn < 3; ++pn) {
+ EM_ASM({hidePlayerInfo($0)}, pn);
+ clear_player_info(pn);
+ }
+ EM_ASM(clearVisits());
+
+ set_prompt_mode(PM_SELECT_MODE);
+ EM_ASM({promptMsgL($0)}, "Select match mode:");
+ EM_ASM({promptMsgR($0)}, "");
+}
+
char *prompt_get()
{
return (char *)EM_ASM_INT({return promptGet()});
diff --git a/web/web_prompt.h b/web/web_prompt.h
index b416f2a..e70f779 100644
--- a/web/web_prompt.h
+++ b/web/web_prompt.h
@@ -11,6 +11,11 @@ enum prompt_mode {
extern enum prompt_mode pm;
+void set_prompt_mode(enum prompt_mode mode);
void prompt_handle(char *command, char *data);
+void prompt_num_darts();
+void prompt_end_match();
+void prompt_select_mode();
+
#endif