summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-05-09 23:39:12 -0700
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-05-09 23:39:12 -0700
commit90b5ca5e47f0fda21f8da6cb9857a35e0f4730a3 (patch)
tree05c3bae5829fcdcc5df2bebd36c504efea974494
parent1def0d71449f95c1fb609053b84a92e8adbb0eb1 (diff)
downloaddartboat-90b5ca5e47f0fda21f8da6cb9857a35e0f4730a3.tar.gz
dartboat-90b5ca5e47f0fda21f8da6cb9857a35e0f4730a3.tar.xz
web: allow selection of starting points and user to throw first
This new option selection code is a bit messy for now. It requires the options and their order to be in sync between the prompt functions and the corresponding submit functions. There's also a bit too much repetition of generic code that's applicable to all options.
-rw-r--r--web/web_control.c44
-rw-r--r--web/web_control.h3
-rw-r--r--web/web_match.c7
-rw-r--r--web/web_match.h9
-rw-r--r--web/web_prompt.c136
-rw-r--r--web/web_prompt.h1
-rw-r--r--web/web_scoreboard.c7
7 files changed, 184 insertions, 23 deletions
diff --git a/web/web_control.c b/web/web_control.c
index 0c220a5..2890308 100644
--- a/web/web_control.c
+++ b/web/web_control.c
@@ -30,7 +30,6 @@ 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);
@@ -70,7 +69,6 @@ void draw_boat_throwing(int pts, char *str, double x, double y)
scoreboard_flush_player_info(2); // FIXME bot hard-coded as player 2
}
-EMSCRIPTEN_KEEPALIVE
void boat_visit()
{
struct leg *l = state->legs[1];
@@ -131,7 +129,7 @@ void handle_next()
if (state->active_player)
toggle_active_player();
else
- set_active_player(1);
+ set_active_player(match_opts->throws_first);
if (state->mode == M_PVC && state->active_player == 2)
boat_visit();
@@ -142,7 +140,6 @@ void handle_next()
scoreboard_flush();
}
-EMSCRIPTEN_KEEPALIVE
void user_visit(int points)
{
if (!is_points_valid(points, state->active_leg->rem)) {
@@ -166,13 +163,11 @@ void user_visit(int points)
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) {
@@ -225,7 +220,6 @@ void user_undo()
handle_next();
}
-EMSCRIPTEN_KEEPALIVE
void user_num_darts(int n)
{
if (n < 1 || n > 3) {
@@ -239,26 +233,49 @@ void user_num_darts(int n)
handle_next();
}
-EMSCRIPTEN_KEEPALIVE
-void start_match(int mode)
+void match_mode_selected(int mode)
{
if (mode < M_FIRST || mode > M_LAST) {
oi();
return;
}
+ if (match_opts) match_opts_free();
+ match_opts = calloc(1, sizeof(*match_opts));
+ match_opts->mode = mode;
+ match_opts->start_pts = 501;
+ match_opts->throws_first = 1;
+ // names need to be freed if we stop using string literals
+ if (mode == M_PVC) {
+ match_opts->p1_name = "User";
+ match_opts->p2_name = "Bot";
+ } else if (mode == M_P) {
+ match_opts->p1_name = "Player 1";
+ match_opts->p2_name = NULL;
+ } else if (mode == M_PVP) {
+ match_opts->p1_name = "Player 1";
+ match_opts->p2_name = "Player 2";
+ }
+
+ prompt_match_opts();
+ prompt_flush();
+}
+
+void start_match()
+{
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");
+ state->mode = match_opts->mode;
+ state->legs[0] = leg_init(match_opts->start_pts, match_opts->p1_name);
+ state->legs[1] = leg_init(match_opts->start_pts,
+ match_opts->p2_name ? match_opts->p2_name : "oi");
show_player_info(1);
update_player_name(1, state->legs[0]->name);
update_player_rem(1, state->legs[0]->rem);
update_player_avg(1, 0);
- if (mode != M_P) {
+ if (state->mode != M_P) {
show_player_info(2);
update_player_name(2, state->legs[1]->name);
update_player_rem(2, state->legs[1]->rem);
@@ -269,7 +286,6 @@ void start_match(int mode)
handle_next();
}
-EMSCRIPTEN_KEEPALIVE
void end_match()
{
if (state) free_state();
diff --git a/web/web_control.h b/web/web_control.h
index ddecac0..19c8719 100644
--- a/web/web_control.h
+++ b/web/web_control.h
@@ -1,7 +1,8 @@
#ifndef WEB_CONTROL_H
#define WEB_CONTROL_H
-void start_match(int mode);
+void start_match();
+void match_mode_selected(int mode);
void end_match();
void user_visit(int points);
void user_num_darts(int n);
diff --git a/web/web_match.c b/web/web_match.c
index 5f87f28..d05efa5 100644
--- a/web/web_match.c
+++ b/web/web_match.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
struct match_state *state;
+struct match_opts *match_opts;
void free_state()
{
@@ -14,6 +15,12 @@ void free_state()
state = NULL;
}
+void match_opts_free()
+{
+ free(match_opts);
+ match_opts = NULL;
+}
+
bool match_is_over()
{
return state->legs[0]->rem <= 0 || state->legs[1]->rem <= 0;
diff --git a/web/web_match.h b/web/web_match.h
index 478ad88..56117b5 100644
--- a/web/web_match.h
+++ b/web/web_match.h
@@ -20,9 +20,18 @@ struct match_state {
int num_darts;
};
+struct match_opts {
+ enum match_mode mode;
+ char *p1_name, *p2_name;
+ int start_pts;
+ int throws_first;
+};
+
extern struct match_state *state;
+extern struct match_opts *match_opts;
void free_state();
+void match_opts_free();
bool match_is_over();
diff --git a/web/web_prompt.c b/web/web_prompt.c
index 3f5521a..9db4fdd 100644
--- a/web/web_prompt.c
+++ b/web/web_prompt.c
@@ -18,7 +18,10 @@ enum prompt_mode {
PM_VISIT,
PM_NUM_DARTS,
PM_END_MATCH,
- PM_SELECT_MODE
+ PM_SELECT_MODE,
+ PM_MATCH_OPTS,
+ PM_MATCH_OPT_START_PTS,
+ PM_MATCH_OPT_THROWS_FIRST
};
enum prompt_mode pm;
@@ -128,6 +131,9 @@ void set_prompt_mode(enum prompt_mode mode)
dom_set_uniq_class(
pm == PM_DARTBOARD ? "#keypad-dartboard" :
pm == PM_SELECT_MODE ? "#keypad-list" :
+ pm == PM_MATCH_OPTS ? "#keypad-list" :
+ pm == PM_MATCH_OPT_START_PTS ? "#keypad-list" :
+ pm == PM_MATCH_OPT_THROWS_FIRST ? "#keypad-list" :
"#keypad-default",
"visible", ".keypad");
}
@@ -137,6 +143,7 @@ void prompt_visit()
set_prompt_mode(PM_VISIT);
prompt_set_msgl("Enter points:");
prompt_set_msgr(NULL);
+
dom_set_content("#key-submit", "OK");
dom_set_content("#key-rem", "REMAINING");
}
@@ -160,11 +167,13 @@ void prompt_num_darts()
void prompt_end_match()
{
scoreboard_set_player_active(-1); // sets all inactive
+
set_prompt_mode(PM_END_MATCH);
prompt_set_msgl(
state->mode == M_PVC && state->legs[1]->rem <= 0 ?
"Bot wins. :(" : "You win! :)");
prompt_set_msgr(NULL);
+
dom_set_content("#key-submit", "END MATCH");
dom_set_content("#key-rem", "REMATCH");
}
@@ -176,14 +185,111 @@ void prompt_select_mode()
clear_player_info(pn);
dom_set_content("#visits", NULL);
+ set_prompt_mode(PM_SELECT_MODE);
+ prompt_set_msgl("Select match mode:");
+ prompt_set_msgr(NULL);
+
clear_list_opts();
add_list_opt("Play against bot");
add_list_opt("One-player scoreboard");
add_list_opt("Two-player scoreboard");
flush_list_opts();
- set_prompt_mode(PM_SELECT_MODE);
- prompt_set_msgl("Select match mode:");
+}
+
+void prompt_match_opts()
+{
+ set_prompt_mode(PM_MATCH_OPTS);
+ prompt_set_msgl("Match options:");
prompt_set_msgr(NULL);
+
+ char buf[64];
+ clear_list_opts();
+ add_list_opt("Start match");
+ sprintf(buf, "Starting points: %d", match_opts->start_pts);
+ add_list_opt(buf);
+ sprintf(buf, "Throws first: %s",
+ match_opts->throws_first == 1 ?
+ match_opts->p1_name :
+ match_opts->p2_name);
+ add_list_opt(buf);
+ flush_list_opts();
+}
+
+void prompt_match_opt_start_pts()
+{
+ set_prompt_mode(PM_MATCH_OPT_START_PTS);
+ prompt_set_msgl("Starting points:");
+ prompt_set_msgr(NULL);
+ prompt_flush();
+
+ clear_list_opts();
+ add_list_opt("301");
+ add_list_opt("501");
+ add_list_opt("701");
+ add_list_opt("901");
+ flush_list_opts();
+}
+
+static void match_opt_start_pts_submit(int val)
+{
+ if (val < 1 || val > list_optc) {
+ oi();
+ return;
+ }
+
+ if (val == 1)
+ match_opts->start_pts = 301;
+ else if (val == 2)
+ match_opts->start_pts = 501;
+ else if (val == 3)
+ match_opts->start_pts = 701;
+ else if (val == 4)
+ match_opts->start_pts = 901;
+
+ prompt_match_opts();
+ prompt_flush();
+}
+
+void prompt_match_opt_throws_first()
+{
+ set_prompt_mode(PM_MATCH_OPT_THROWS_FIRST);
+ prompt_set_msgl("Throws first:");
+ prompt_set_msgr(NULL);
+ prompt_flush();
+
+ clear_list_opts();
+ add_list_opt(match_opts->p1_name);
+ if (match_opts->p2_name)
+ add_list_opt(match_opts->p2_name);
+ flush_list_opts();
+}
+
+static void match_opt_throws_first_submit(int val)
+{
+ if (val < 1 || val > list_optc) {
+ oi();
+ return;
+ }
+
+ match_opts->throws_first = val;
+
+ prompt_match_opts();
+ prompt_flush();
+}
+
+static void match_opts_submit(int val)
+{
+ if (val < 1 || val > list_optc) {
+ oi();
+ return;
+ }
+
+ if (val == 1)
+ start_match();
+ else if (val == 2)
+ prompt_match_opt_start_pts();
+ else if (val == 3)
+ prompt_match_opt_throws_first();
}
bool key_is_active(char *k)
@@ -244,7 +350,12 @@ void prompt_handle_on_change()
void prompt_handle_append(char *data)
{
- if (pm != PM_SELECT_MODE && pm != PM_VISIT && pm != PM_NUM_DARTS)
+ if (pm != PM_MATCH_OPTS &&
+ pm != PM_MATCH_OPT_START_PTS &&
+ pm != PM_MATCH_OPT_THROWS_FIRST &&
+ pm != PM_SELECT_MODE &&
+ pm != PM_VISIT &&
+ pm != PM_NUM_DARTS)
return;
char *str = prompt_get();
@@ -292,7 +403,12 @@ void prompt_handle_submit()
return;
}
- if (pm != PM_VISIT && pm != PM_NUM_DARTS && pm != PM_SELECT_MODE)
+ if (pm != PM_VISIT &&
+ pm != PM_NUM_DARTS &&
+ pm != PM_SELECT_MODE &&
+ pm != PM_MATCH_OPTS &&
+ pm != PM_MATCH_OPT_START_PTS &&
+ pm != PM_MATCH_OPT_THROWS_FIRST)
return;
char *str = prompt_get();
@@ -303,7 +419,13 @@ void prompt_handle_submit()
else if (pm == PM_NUM_DARTS)
user_num_darts(atoi(str));
else if (pm == PM_SELECT_MODE)
- start_match(atoi(str));
+ match_mode_selected(atoi(str));
+ else if (pm == PM_MATCH_OPTS)
+ match_opts_submit(atoi(str));
+ else if (pm == PM_MATCH_OPT_START_PTS)
+ match_opt_start_pts_submit(atoi(str));
+ else if (pm == PM_MATCH_OPT_THROWS_FIRST)
+ match_opt_throws_first_submit(atoi(str));
}
free(str);
@@ -313,7 +435,7 @@ void prompt_handle_rem()
{
if (pm == PM_END_MATCH) {
if (key_is_active("rem"))
- start_match(state->mode);
+ start_match();
toggle_key("rem");
return;
}
diff --git a/web/web_prompt.h b/web/web_prompt.h
index 7887c34..2e4430b 100644
--- a/web/web_prompt.h
+++ b/web/web_prompt.h
@@ -13,5 +13,6 @@ void prompt_bot_visit();
void prompt_num_darts();
void prompt_end_match();
void prompt_select_mode();
+void prompt_match_opts();
#endif
diff --git a/web/web_scoreboard.c b/web/web_scoreboard.c
index 495a7b6..8a6def0 100644
--- a/web/web_scoreboard.c
+++ b/web/web_scoreboard.c
@@ -192,7 +192,11 @@ void draw_visits()
}
for (int i = 0; i < n_visits; ++i) {
- struct visit *v = state->legs[0]->visits + i;
+ struct visit *v;
+
+ if (i >= state->legs[0]->n_visits)
+ goto p2;
+ v = state->legs[0]->visits + i;
snprintf(buf, sizeof(buf), "%d", v->points);
snprintf(buf2, sizeof(buf2), "%s %s",
@@ -205,6 +209,7 @@ void draw_visits()
snprintf(buf, sizeof(buf), "%d", i + 1);
elemv[elemc++] = create_div(buf, "visit-n");
+p2:
if (i >= state->legs[1]->n_visits)
continue;
v = state->legs[1]->visits + i;