summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-05-21 04:43:19 -0700
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-05-21 04:43:19 -0700
commit3e8b8b804e7b30f096e557839eb5cc419a647f78 (patch)
treed59809a8d0d77d90984ef70e0ba1ae58d7b3dbc9
parent35f311f779c039423fc7e2a11f98703c40201846 (diff)
downloaddartboat-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.c9
-rw-r--r--web/web_prompt.c270
-rw-r--r--web/web_scoreboard.c1
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()