From 90b5ca5e47f0fda21f8da6cb9857a35e0f4730a3 Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Mon, 9 May 2022 23:39:12 -0700 Subject: 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. --- web/web_control.c | 44 +++++++++++------ web/web_control.h | 3 +- web/web_match.c | 7 +++ web/web_match.h | 9 ++++ web/web_prompt.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++--- web/web_prompt.h | 1 + web/web_scoreboard.c | 7 ++- 7 files changed, 184 insertions(+), 23 deletions(-) (limited to 'web') 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 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; -- cgit v1.2.3-70-g09d2