diff options
author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2022-05-21 04:43:19 -0700 |
---|---|---|
committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2022-05-21 04:43:19 -0700 |
commit | 3e8b8b804e7b30f096e557839eb5cc419a647f78 (patch) | |
tree | d59809a8d0d77d90984ef70e0ba1ae58d7b3dbc9 | |
parent | 35f311f779c039423fc7e2a11f98703c40201846 (diff) | |
download | dartboat-3e8b8b804e7b30f096e557839eb5cc419a647f78.tar.gz dartboat-3e8b8b804e7b30f096e557839eb5cc419a647f78.tar.xz |
web: use function ptrs for menu options
This avoids having to keep the options and their order in sync between
separate display and submit functions.
-rw-r--r-- | web/web_match.c | 9 | ||||
-rw-r--r-- | web/web_prompt.c | 270 | ||||
-rw-r--r-- | web/web_scoreboard.c | 1 |
3 files changed, 150 insertions, 130 deletions
diff --git a/web/web_match.c b/web/web_match.c index 0ebc56e..cd87c5a 100644 --- a/web/web_match.c +++ b/web/web_match.c @@ -60,6 +60,7 @@ void match_opts_new() if (match_opts) match_opts_free(); match_opts = calloc(1, sizeof(*match_opts)); + match_opts->start_pts = 501; match_opts->size_players = 2; match_opts->players = malloc( @@ -77,8 +78,12 @@ void match_opts_add_player(enum player_type type, char *name) sizeof(*(match_opts->players))); } - match_opts->players[match_opts->num_players].type = type; - match_opts->players[match_opts->num_players++].name = name; + int pn = ++match_opts->num_players; + if (!match_opts->throws_first) + match_opts->throws_first = pn; + + match_opts->players[pn - 1].type = type; + match_opts->players[pn - 1].name = name; } void match_opts_free() diff --git a/web/web_prompt.c b/web/web_prompt.c index dc21d62..17383db 100644 --- a/web/web_prompt.c +++ b/web/web_prompt.c @@ -30,9 +30,15 @@ enum menu { }; static enum menu menu_stack[10]; static int menu_depth = 0; -static char *list_optv[10]; -static int list_optc; -static bool list_back; + +struct menu_opt { + char *label; + void (*func)(); + int arg; + bool takes_arg; +}; +static struct menu_opt menu_optv[10]; +static int menu_optc; static struct { bufstr msgl, msgr, input; @@ -96,24 +102,37 @@ void set_prompt_mode(enum prompt_mode mode) "visible", ".keypad"); } -static void clear_list_opts() +static void add_menu_opt(char *label, void (*func)()) { - for (int i = 0; i < list_optc; ++i) - free(list_optv[i]); - list_optc = 0; - list_back = false; + struct menu_opt *m = &menu_optv[menu_optc++]; + + m->label = strdup(label); + m->func = func; + m->takes_arg = false; +} + +static void add_menu_opti(char *label, void (*func)(int), int arg) +{ + struct menu_opt *m = &menu_optv[menu_optc++]; + + m->label = strdup(label); + m->func = func; + m->arg = arg; + m->takes_arg = true; } -static void add_list_opt(char *str) +static void clear_menu_opts() { - list_optv[list_optc++] = strdup(str); + for (int i = 0; i < menu_optc; ++i) + free(menu_optv[i].label); + menu_optc = 0; } -static void flush_list_opts() +static void flush_menu_opts() { - struct dom_elem **elemv = malloc(list_optc * sizeof(*elemv)); + struct dom_elem **elemv = malloc(menu_optc * sizeof(*elemv)); - for (int i = 0; i < list_optc; ++i) { + for (int i = 0; i < menu_optc; ++i) { struct dom_elem *e = dom_elem_init(NULL, "div", 2); dom_elem_add_attr(e, "class", "key"); @@ -127,7 +146,7 @@ static void flush_list_opts() dom_elem_add_attr(child, "class", "keyboard-val"); dom_elem_add_child(e, child); - sprintf(buf, "\u2002%s", list_optv[i]); + sprintf(buf, "\u2002%s", menu_optv[i].label); child = dom_text_init(buf); dom_elem_add_child(e, child); @@ -135,50 +154,132 @@ static void flush_list_opts() } dom_set_content("#keypad-list", NULL); - dom_append_elemv("#keypad-list", list_optc, elemv); + dom_append_elemv("#keypad-list", menu_optc, elemv); - for (int i = 0; i < list_optc; ++i) + for (int i = 0; i < menu_optc; ++i) dom_elem_free(elemv[i]); free(elemv); } +static void menu_push(enum menu m); +static void menu_push_int(int m) { menu_push(m); }; +static void menu_pop(); + +enum match_mode { + MM_1P1C, + MM_1P, + MM_2P, + MM_2C, + MM_3P, + MM_1P3C, + MM_8C +}; + +void select_match_mode(int mode) +{ + match_opts_new(); + + // names need to be freed if we stop using string literals + switch((enum match_mode)mode) { + case MM_1P1C: + match_opts_add_player(PT_USER, "User"); + match_opts_add_player(PT_COMP, "Computer"); + break; + case MM_1P: + match_opts_add_player(PT_USER, "Player 1"); + break; + case MM_2P: + match_opts_add_player(PT_USER, "Player 1"); + match_opts_add_player(PT_USER, "Player 2"); + break; + case MM_2C: + match_opts_add_player(PT_COMP, "Computer 1"); + match_opts_add_player(PT_COMP, "Computer 2"); + break; + case MM_3P: + match_opts_add_player(PT_USER, "Player 1"); + match_opts_add_player(PT_USER, "Player 2"); + match_opts_add_player(PT_USER, "Player 3"); + break; + case MM_1P3C: + match_opts_add_player(PT_USER, "Player 1"); + match_opts_add_player(PT_COMP, "Computer 1"); + match_opts_add_player(PT_COMP, "Computer 2"); + match_opts_add_player(PT_COMP, "Computer 3"); + break; + case MM_8C: + match_opts_add_player(PT_COMP, "Computer 1"); + match_opts_add_player(PT_COMP, "Computer 2"); + match_opts_add_player(PT_COMP, "Computer 3"); + match_opts_add_player(PT_COMP, "Computer 4"); + match_opts_add_player(PT_COMP, "Computer 5"); + match_opts_add_player(PT_COMP, "Computer 6"); + match_opts_add_player(PT_COMP, "Computer 7"); + match_opts_add_player(PT_COMP, "Computer 8"); + break; + } + + menu_push(MENU_MATCH_OPTS); +} + void menu_display_main() { prompt_set_msgl("Select match mode:"); - add_list_opt("Play against computer"); - add_list_opt("One-player scoreboard"); - add_list_opt("Two-player scoreboard"); - add_list_opt("Computer vs computer"); - add_list_opt("Three-player scoreboard"); - add_list_opt("Play against three computers"); + add_menu_opti("Play against computer", + select_match_mode, MM_1P1C); + add_menu_opti("One-player scoreboard", + select_match_mode, MM_1P); + add_menu_opti("Two-player scoreboard", + select_match_mode, MM_2P); + add_menu_opti("Computer vs computer", + select_match_mode, MM_2C); + add_menu_opti("Three-player scoreboard", + select_match_mode, MM_3P); + add_menu_opti("Play against three computers", + select_match_mode, MM_1P3C); + add_menu_opti("Battle of the computers", + select_match_mode, MM_8C); } void menu_display_match_opts() { prompt_set_msgl("Match options:"); + add_menu_opt("Start match", start_match); + char buf[64]; - add_list_opt("Start match"); sprintf(buf, "Starting points: %d", match_opts->start_pts); - add_list_opt(buf); + add_menu_opti(buf, menu_push_int, MENU_START_PTS); sprintf(buf, "Throws first: %s", match_opts->players[match_opts->throws_first - 1].name); - add_list_opt(buf); + add_menu_opti(buf, menu_push_int, MENU_THROWS_FIRST); - list_back = true; + add_menu_opt("Back", menu_pop); +} + +static void set_start_pts(int pts) +{ + match_opts->start_pts = pts; + menu_pop(); } void menu_display_start_pts() { prompt_set_msgl("Starting points:"); - add_list_opt("301"); - add_list_opt("501"); - add_list_opt("701"); - add_list_opt("901"); + add_menu_opti("301", set_start_pts, 301); + add_menu_opti("501", set_start_pts, 501); + add_menu_opti("701", set_start_pts, 701); + add_menu_opti("901", set_start_pts, 901); - list_back = true; + add_menu_opt("Back", menu_pop); +} + +static void set_throws_first(int pn) +{ + match_opts->throws_first = pn; + menu_pop(); } void menu_display_throws_first() @@ -186,9 +287,10 @@ void menu_display_throws_first() prompt_set_msgl("Throws first:"); for (int i = 0; i < match_opts->num_players; ++i) - add_list_opt(match_opts->players[i].name); + add_menu_opti(match_opts->players[i].name, set_throws_first, + i + 1); - list_back = true; + add_menu_opt("Back", menu_pop); } void menu_display() @@ -198,7 +300,7 @@ void menu_display() prompt_set_msgl(NULL); prompt_set_msgr(NULL); - clear_list_opts(); + clear_menu_opts(); switch (menu_stack[menu_depth]) { case MENU_MAIN: @@ -215,10 +317,7 @@ void menu_display() break; } - if (list_back) - add_list_opt("Back"); - - flush_list_opts(); + flush_menu_opts(); prompt_flush(); } @@ -234,102 +333,19 @@ static void menu_push(enum menu m) menu_display(); } -void menu_submit_main(int val) -{ - match_opts_new(); - match_opts->start_pts = 501; - match_opts->throws_first = 1; - - // names need to be freed if we stop using string literals - switch(val) { - case 1: - match_opts_add_player(PT_USER, "User"); - match_opts_add_player(PT_COMP, "Computer"); - break; - case 2: - match_opts_add_player(PT_USER, "Player 1"); - break; - case 3: - match_opts_add_player(PT_USER, "Player 1"); - match_opts_add_player(PT_USER, "Player 2"); - break; - case 4: - match_opts_add_player(PT_COMP, "Computer 1"); - match_opts_add_player(PT_COMP, "Computer 2"); - break; - case 5: - match_opts_add_player(PT_USER, "Player 1"); - match_opts_add_player(PT_USER, "Player 2"); - match_opts_add_player(PT_USER, "Player 3"); - break; - case 6: - match_opts_add_player(PT_USER, "Player 1"); - match_opts_add_player(PT_COMP, "Computer 1"); - match_opts_add_player(PT_COMP, "Computer 2"); - match_opts_add_player(PT_COMP, "Computer 3"); - break; - } - - menu_push(MENU_MATCH_OPTS); -} - -static void menu_submit_match_opts(int val) -{ - if (val == 1) - start_match(); - else if (val == 2) - menu_push(MENU_START_PTS); - else if (val == 3) - menu_push(MENU_THROWS_FIRST); -} - -static void menu_submit_start_pts(int val) -{ - 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; - - menu_pop(); -} - -static void menu_submit_throws_first(int val) -{ - match_opts->throws_first = val; - - menu_pop(); -} - static void menu_submit(int opt) { - if (opt < 1 || opt > list_optc) { + if (opt < 1 || opt > menu_optc) { oi(); return; } - if (list_back && opt == list_optc) { - menu_pop(); - return; - } + struct menu_opt *m = &menu_optv[opt - 1]; - switch (menu_stack[menu_depth]) { - case MENU_MAIN: - menu_submit_main(opt); - break; - case MENU_MATCH_OPTS: - menu_submit_match_opts(opt); - break; - case MENU_START_PTS: - menu_submit_start_pts(opt); - break; - case MENU_THROWS_FIRST: - menu_submit_throws_first(opt); - break; - } + if (m->takes_arg) + ((void (*)(int))m->func)(m->arg); + else + m->func(); } void prompt_main_menu() diff --git a/web/web_scoreboard.c b/web/web_scoreboard.c index 3b5993a..e79d104 100644 --- a/web/web_scoreboard.c +++ b/web/web_scoreboard.c @@ -371,7 +371,6 @@ void draw_visits_dense() free(elemv); dom_scroll_to_bottom("#visits"); - dom_scroll_to_center_child("#visits", ".visit-n"); } void draw_visits() |