summaryrefslogtreecommitdiff
path: root/web/dartboat_wasm.c
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-04-25 03:21:23 -0700
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-04-25 03:22:42 -0700
commit3feb8f5af835f2dac403760bbb7bedb895c45954 (patch)
tree6481feb443e9d19aba846cd8b067413c2e7c452a /web/dartboat_wasm.c
parentd6f25366900245608d364fc5ed0f07f18fd8de27 (diff)
downloaddartboat-3feb8f5af835f2dac403760bbb7bedb895c45954.tar.gz
dartboat-3feb8f5af835f2dac403760bbb7bedb895c45954.tar.xz
web: better separate match control and display logic
Diffstat (limited to 'web/dartboat_wasm.c')
-rw-r--r--web/dartboat_wasm.c321
1 files changed, 164 insertions, 157 deletions
diff --git a/web/dartboat_wasm.c b/web/dartboat_wasm.c
index 989e0c2..1815d53 100644
--- a/web/dartboat_wasm.c
+++ b/web/dartboat_wasm.c
@@ -27,28 +27,27 @@ struct match_state {
struct match_state *state;
-void switch_active_user() {
- state->active_p = 3 - state->active_p;
- if (state->active_p == 1)
- state->active_l = state->l1;
- else
- state->active_l = state->l2;
- EM_ASM({setPlayerActive($0)}, state->active_p);
+void set_active_player(int player)
+{
+ state->active_p = player;
+ state->active_l = player == 1 ? state->l1 : state->l2;
+ EM_ASM({setPlayerActive($0)}, player);
}
-void set_user_active() {
- state->active_p = 1;
- state->active_l = state->l1;
+void toggle_active_player()
+{
+ set_active_player(3 - state->active_p);
+}
- EM_ASM({setPlayerActive($0)}, 1);
+void set_user_active()
+{
+ set_active_player(1);
EM_ASM({setPromptHandler($0)}, "visit");
}
-void set_boat_active() {
- state->active_p = 2;
- state->active_l = state->l2;
-
- EM_ASM({setPlayerActive($0)}, 2);
+void set_boat_active()
+{
+ set_active_player(2);
EM_ASM({setPromptHandler()}, "");
}
@@ -68,43 +67,44 @@ void update_player_sugg(int player, int rem)
EM_ASM({updatePlayerSugg($0, $1)}, player, str);
}
-bool is_match_over() {
+bool is_match_over()
+{
return state->l1->rem <= 0 || state->l2->rem <= 0;
}
-void prompt_match_over() {
+void prompt_match_over()
+{
+ EM_ASM(setPlayerActive()); // sets all inactive
EM_ASM({setPromptHandler($0)}, "match_over");
EM_ASM({promptMsgR($0)}, "Press OK to end match.");
- EM_ASM(setPlayerActive());
}
-EMSCRIPTEN_KEEPALIVE void draw_visits() {
+void draw_visits()
+{
EM_ASM({clearVisits()});
- struct leg *l1 = state->l1;
- struct leg *l2 = state->l2;
-
char visit_no[10], p1_pts[10], p1_rem[10],
p2_pts[10], p2_rem[10], p2_darts[100];
- sprintf(p1_rem, "%d", l1->start);
- sprintf(p2_rem, "%d", l2->start);
+ sprintf(p1_rem, "%d", state->l1->start);
+ sprintf(p2_rem, "%d", state->l2->start);
EM_ASM({drawVisit($0, $1, $2, $3, $4, $5)},
"0", "", p1_rem, "", state->mode == M_P ? "" : p2_rem, "");
- int n_visits = l1->n_visits > l2->n_visits ? l1->n_visits : l2->n_visits;
+ int n_visits = state->l1->n_visits > state->l2->n_visits ?
+ state->l1->n_visits : state->l2->n_visits;
for (int i = 0; i < n_visits; ++i) {
visit_no[0] = p1_pts[0] = p1_rem[0] =
p2_pts[0] = p2_rem[0] = p2_darts[0] = 0;
sprintf(visit_no, "%d", i + 1);
- struct visit *v = l1->visits + i;
+ struct visit *v = state->l1->visits + i;
sprintf(p1_pts, "%d", v->points);
sprintf(p1_rem, "%d", v->rem);
- if (i < l2->n_visits) {
- v = l2->visits + i;
+ if (i < state->l2->n_visits) {
+ v = state->l2->visits + i;
sprintf(p2_pts, "%d", v->points);
sprintf(p2_rem, "%d", v->rem);
@@ -121,45 +121,51 @@ EMSCRIPTEN_KEEPALIVE void draw_visits() {
}
}
-EMSCRIPTEN_KEEPALIVE void draw_match() {
- draw_visits();
-
- if (state->l1->rem <= 0) {
- EM_ASM({promptMsgL($0)}, "Darts needed?");
- EM_ASM({setPromptHandler($0)}, "num_darts");
- } else if (state->l2->rem <= 0) {
- if (state->mode == M_PVC) {
- EM_ASM({promptMsgL($0)}, "Bot wins. :(");
- prompt_match_over();
- } else {
- EM_ASM({promptMsgL($0)}, "Darts needed?");
- EM_ASM({setPromptHandler($0)}, "num_darts");
- }
- } else {
- EM_ASM({promptMsgL($0)}, "Enter points:");
- }
-}
-
-EMSCRIPTEN_KEEPALIVE void update_player_rem(int player, int rem) {
- char str[10];
+void update_player_rem(int player, int rem)
+{
+ char str[5];
if (rem < 0 || rem == 1)
strcpy(str, "BUST");
else
sprintf(str, "%d", rem);
EM_ASM({updatePlayerRem($0, $1)}, player, str);
-
if (player == 1 || state->mode != M_PVC)
update_player_sugg(player, rem);
}
-EMSCRIPTEN_KEEPALIVE void update_user_rem_from_pts(int pts) {
+EMSCRIPTEN_KEEPALIVE void update_user_rem_from_pts(int pts)
+{
update_player_rem(state->active_p, state->active_l->rem - pts);
}
-void end_boat_throwing(int, double); // FIXME
+EMSCRIPTEN_KEEPALIVE void draw_boat_throwing(int pts, char *str)
+{
+ char pts_str[10];
+ sprintf(pts_str, "%d", pts);
-EMSCRIPTEN_KEEPALIVE void boat_visit() {
+ int rem = state->l2->n_visits > 1 ?
+ state->l2->visits[state->l2->n_visits-2].rem : state->l2->start;
+
+ update_player_rem(2, rem - pts);
+ EM_ASM({setPromptInput($0)}, pts_str);
+ EM_ASM({promptMsgR($0)}, str);
+}
+
+void post_visit_checks();
+EMSCRIPTEN_KEEPALIVE void end_boat_throwing(int rem, double avg)
+{
+ update_player_rem(2, rem);
+ EM_ASM({updatePlayerAvg($0, $1)}, 2, avg);
+ EM_ASM({setPromptInput($0)}, "");
+ EM_ASM({promptMsgR($0)}, "");
+
+ draw_visits();
+ post_visit_checks();
+}
+
+EMSCRIPTEN_KEEPALIVE void boat_visit()
+{
if (state->l1->rem <= 0 || state->l2->rem <= 0)
return;
@@ -205,7 +211,36 @@ EMSCRIPTEN_KEEPALIVE void boat_visit() {
"number", l->rem, "number", avg);
}
-EMSCRIPTEN_KEEPALIVE bool user_visit(int points) {
+void post_visit_checks()
+{
+ if (is_match_over()) {
+ if (state->mode == M_PVC && state->l2->rem <= 0) {
+ EM_ASM({promptMsgL($0)}, "Bot wins. :(");
+ prompt_match_over();
+ } else {
+ EM_ASM({setPromptHandler($0)}, "num_darts");
+ EM_ASM({promptMsgL($0)}, "Darts needed?");
+ }
+ } else {
+ if (state->mode == M_PVC) {
+ if (state->active_p == 1) {
+ set_boat_active();
+ boat_visit();
+ } else {
+ set_user_active();
+ EM_ASM({promptMsgL($0)}, "Enter points:");
+ }
+ } else if (state->mode == M_PVP) {
+ toggle_active_player();
+ EM_ASM({promptMsgL($0)}, "Enter points:");
+ } else {
+ EM_ASM({promptMsgL($0)}, "Enter points:");
+ }
+ }
+}
+
+EMSCRIPTEN_KEEPALIVE void user_visit(int points)
+{
if (points < 0 || state->l1->rem <= 0 || state->l2->rem <= 0 ||
points > state->active_l->rem || state->active_l->rem - points == 1 ||
points > 180 || points == 179 || points == 178 || points == 176 ||
@@ -215,7 +250,7 @@ EMSCRIPTEN_KEEPALIVE bool user_visit(int points) {
(points == 168 || points == 165 || points == 162 || points == 159))) {
EM_ASM(oi());
- return false;
+ return;
}
struct leg *l = state->active_l;
@@ -229,39 +264,31 @@ EMSCRIPTEN_KEEPALIVE bool user_visit(int points) {
EM_ASM({updatePlayerAvg($0, $1)}, state->active_p,
(double)(l->start-l->rem)/l->n_visits);
- draw_match();
-
- if (!is_match_over()) {
- if (state->mode == M_PVC) {
- set_boat_active();
- boat_visit();
- } else if (state->mode == M_PVP) {
- switch_active_user();
- }
- }
-
- return true;
+ draw_visits();
+ post_visit_checks();
}
-EMSCRIPTEN_KEEPALIVE void user_visit_to_rem(int rem) {
+EMSCRIPTEN_KEEPALIVE void user_visit_to_rem(int rem)
+{
user_visit(state->l1->rem - rem);
}
-EMSCRIPTEN_KEEPALIVE bool user_undo() {
+EMSCRIPTEN_KEEPALIVE void user_undo()
+{
if (!state->l1->n_visits) {
EM_ASM(oi());
- return false;
+ return;
}
if (state->mode == M_PVP) {
if (is_match_over())
EM_ASM({setPlayerActive($0)}, state->active_p);
else
- switch_active_user();
+ toggle_active_player();
}
if (state->mode == M_PVC)
- EM_ASM({setPlayerActive($0)}, state->active_p);
+ set_user_active();
struct leg *l = state->active_l;
struct visit *v = l->visits + --l->n_visits;
@@ -284,131 +311,111 @@ EMSCRIPTEN_KEEPALIVE bool user_undo() {
EM_ASM({promptMsgR($0)}, "");
EM_ASM({setPromptHandler($0)}, "visit");
- draw_match();
-
- return true;
-}
-
-EMSCRIPTEN_KEEPALIVE void draw_boat_throwing(int pts, char *str) {
- char buf[10];
- sprintf(buf, "%d", pts);
-
- int rem = state->l2->n_visits > 1 ?
- state->l2->visits[state->l2->n_visits-2].rem : state->l2->start;
-
- update_player_rem(2, rem - pts);
- EM_ASM({setPromptInput($0)}, buf);
- EM_ASM({promptMsgR($0)}, str);
-}
-
-EMSCRIPTEN_KEEPALIVE void end_boat_throwing(int rem, double avg) {
- update_player_rem(2, rem);
- EM_ASM({updatePlayerAvg($0, $1)}, 2, avg);
- EM_ASM({setPromptInput($0)}, "");
- EM_ASM({promptMsgR($0)}, "");
- draw_match();
-
- if (!is_match_over())
- set_user_active();
+ EM_ASM({promptMsgL($0)}, "Enter points:");
+ draw_visits();
}
-EMSCRIPTEN_KEEPALIVE void resp_numdarts(int n_darts) {
- if (n_darts < 1 || n_darts > 3) {
+EMSCRIPTEN_KEEPALIVE void user_num_darts(int n)
+{
+ if (n < 1 || n > 3) {
EM_ASM(oi());
return;
}
- struct leg *l = state->l1;
+ struct leg *l = state->active_l;
EM_ASM({updatePlayerAvg($0, $1)}, state->active_p,
- ((double)l->start / (((l->n_visits - 1) * 3) + n_darts)) * 3);
+ ((double)l->start / (((l->n_visits - 1) * 3) + n)) * 3);
EM_ASM({promptMsgL($0)}, "You win! :)");
prompt_match_over();
}
-void init_boat() {
- static int ran;
-
- if (ran) return;
- ran = 1;
-
- srand(time(NULL));
- init_board();
-
- EM_ASM({updateStdev($0)}, horizontal_stdev);
- EM_ASM({updateDelay($0)}, delay_ms);
-}
-
-EMSCRIPTEN_KEEPALIVE void free_match() {
+void free_state()
+{
+ state->l2->n_visits += state->undone_count; // avoid memory leak
leg_free(state->l1);
- state->l2->n_visits += state->undone_count; // FIXME messy way to avoid memory leak
leg_free(state->l2);
free(state);
state = NULL;
}
-EMSCRIPTEN_KEEPALIVE void prompt_match_mode() {
- for (int i = 1; i < 3; ++i) {
- EM_ASM({hidePlayerInfo($0)}, i);
- EM_ASM({updatePlayerName($0, $1)}, i, "");
- EM_ASM({updatePlayerRem($0, $1)}, i, "");
- EM_ASM({updatePlayerSugg($0, $1)}, i, "");
- EM_ASM({updatePlayerAvg($0, $1)}, i, 0);
- }
- EM_ASM(clearVisits());
-
- EM_ASM({setPromptHandler($0)}, "init");
- EM_ASM({promptMsgR($0)}, "");
- EM_ASM({promptMsgL($0)}, "Select match mode:");
-}
-
-EMSCRIPTEN_KEEPALIVE void start_match(int mode) {
+EMSCRIPTEN_KEEPALIVE void start_match(int mode)
+{
if (mode != M_PVP && mode != M_PVC && mode != M_P) {
EM_ASM(oi());
return;
}
- if (state) free_match();
-
- init_boat();
+ if (state) free_state();
state = calloc(1, sizeof(*state));
state->mode = mode;
- if (mode == M_PVC) {
- state->l1 = leg_init(501, "User");
- state->l2 = leg_init(501, "Bot");
- } else {
- state->l1 = leg_init(501, mode == M_PVP ? "Player 1" : "User");
- state->l2 = leg_init(501, "Player 2");
- }
- EM_ASM({showPlayerInfo($0)}, 1);
- if (mode != M_P)
- EM_ASM({showPlayerInfo($0)}, 2);
+ state->l1 = leg_init(501, mode == M_PVP ? "Player 1" : "User");
+ state->l2 = leg_init(501, mode == M_PVC ? "Bot" : "Player 2");
state->active_p = 1;
state->active_l = state->l1;
+ set_user_active();
+ EM_ASM({showPlayerInfo($0)}, 1);
EM_ASM({updatePlayerName($0, $1)}, 1, state->l1->name);
- EM_ASM({updatePlayerName($0, $1)}, 2, state->l2->name);
update_player_rem(1, state->l1->rem);
- update_player_rem(2, state->l2->rem);
EM_ASM({updatePlayerAvg($0, $1)}, 1, 0);
- EM_ASM({updatePlayerAvg($0, $1)}, 2, 0);
- set_user_active();
+ if (mode != M_P) {
+ EM_ASM({showPlayerInfo($0)}, 2);
+ EM_ASM({updatePlayerName($0, $1)}, 2, state->l2->name);
+ update_player_rem(2, state->l2->rem);
+ EM_ASM({updatePlayerAvg($0, $1)}, 2, 0);
+ }
+
+ EM_ASM({promptMsgR($0)}, "");
+ EM_ASM({promptMsgL($0)}, "");
+ draw_visits();
+}
+
+void clear_player_info(int pn)
+{
+ EM_ASM({updatePlayerName($0, $1)}, pn, "");
+ EM_ASM({updatePlayerRem($0, $1)}, pn, "");
+ EM_ASM({updatePlayerSugg($0, $1)}, pn, "");
+ EM_ASM({updatePlayerAvg($0, $1)}, pn, 0);
+}
+
+EMSCRIPTEN_KEEPALIVE void prompt_match_mode()
+{
+ for (int pn = 1; pn < 3; ++pn) {
+ EM_ASM({hidePlayerInfo($0)}, pn);
+ clear_player_info(pn);
+ }
+ EM_ASM(clearVisits());
+
+ EM_ASM({setPromptHandler($0)}, "init");
EM_ASM({promptMsgR($0)}, "");
- draw_match();
+ EM_ASM({promptMsgL($0)}, "Select match mode:");
+}
+
+EMSCRIPTEN_KEEPALIVE void set_delay(int delay)
+{
+ delay_ms = delay;
}
-EMSCRIPTEN_KEEPALIVE void set_stdev(float hstdev, float vstdev) {
+EMSCRIPTEN_KEEPALIVE void set_stdev(float hstdev, float vstdev)
+{
horizontal_stdev = hstdev;
vertical_stdev = vstdev;
}
-EMSCRIPTEN_KEEPALIVE void set_delay(int delay) {
- delay_ms = delay;
+void init_boat()
+{
+ srand(time(NULL));
+ init_board();
+
+ EM_ASM(readOpts());
+ EM_ASM({updateDelay($0)}, delay_ms);
+ EM_ASM({updateStdev($0)}, horizontal_stdev);
}
-int main() {
- EM_ASM(read_opts());
+int main()
+{
init_boat();
prompt_match_mode();
}