Loading menu.c +58 −4 Original line number Diff line number Diff line Loading @@ -50,7 +50,7 @@ char *menu_prompt(const menu_item *items, const unsigned int num_menu_items) { hovered_item_changed = 0; } break; case SELECT: case ENTER: selected_action = items[hovered_selection_index].command; // choose the hovered + selected item break; default: Loading @@ -62,6 +62,60 @@ char *menu_prompt(const menu_item *items, const unsigned int num_menu_items) { return selected_action; } void menu_prompt_multi_select(menu_item *items, const unsigned int num_menu_items) { for (int i = 0; i < num_menu_items; i++) { printf("\n"); // make downward room for the menu } unsigned int user_done_selecting = 0; int hovered_item_changed = 1; unsigned int hovered_selection_index = 0; // menu logic! TODO make this cross platform (play nice with Windows...) do { // return cursor to menu top position if (hovered_item_changed) { for (int i = 0; i < num_menu_items; i++) { printf("\033[A"); // move cursor up one line printf("\033[2K"); // clear entire line } // print menu items, showing selection for (int i = 0; i < num_menu_items; i++) { if (i == hovered_selection_index) { printf("> "); } printf("%s\n", items[i].title); } } MENU_DIRECTION direction = get_direction(); switch (direction) { case DOWN: if (hovered_selection_index < num_menu_items - 1) { hovered_selection_index++; hovered_item_changed = 1; } else { hovered_item_changed = 0; } break; case UP: if (hovered_selection_index > 0) { hovered_selection_index--; hovered_item_changed = 1; } else { hovered_item_changed = 0; } break; case ENTER: user_done_selecting = 1; break; default: hovered_item_changed = 0; break; } } while (!user_done_selecting); } MENU_DIRECTION get_direction(void) { // todo test (+ fix) all of this character grabbing stuff in windows - use conio.h as included above char key_pressed = (char) getchar(); // with terminal set to raw mode, this will no longer wait for Enter key; note that Enter key is handled with \n case Loading Loading @@ -93,12 +147,12 @@ MENU_DIRECTION get_direction(void) { case 'W': return UP; case '\n': return SELECT; return ENTER; case ' ': return SPACE; default: return NONE; } } menu_item *get_menu_item_by_command(menu_item *items, const unsigned int num_menu_items, char *command_to_find) { Loading menu.h +3 −1 Original line number Diff line number Diff line Loading @@ -8,7 +8,8 @@ typedef enum { DOWN, UP, SELECT, ENTER, SPACE, NONE, } MENU_DIRECTION; Loading @@ -16,6 +17,7 @@ typedef struct { char *title; char *command; unsigned int enabled; unsigned int multi_selected; } menu_item; char *menu_prompt(const menu_item *items, unsigned int num_menu_items); Loading utils.c +0 −3 Original line number Diff line number Diff line Loading @@ -32,15 +32,12 @@ void set_raw_terminal_configuration(void) { raw_terminal_configuration = original_terminal_configuration; // new_terminal_configuration.c_lflag &= ~ICANON & ~ECHO & ~ISIG; // disables canonical input, echo, signals (we want signals but good to know) raw_terminal_configuration.c_lflag &= ~ICANON & ~ECHO; // disables canonical input, echo // tcsetattr(STDIN_FILENO, TCSANOW, &raw_terminal_configuration); // apply settings to terminal set_terminal_configuration(&raw_terminal_configuration); #endif } void set_original_terminal_configuration(void) { #ifndef _WIN32 // setting terminal mode is only applicable for unix environments // set_terminal_configuration(&original_terminal_configuration); // tcsetattr(STDIN_FILENO, TCSANOW, &original_terminal_configuration); // apply settings to terminal set_terminal_configuration(&original_terminal_configuration); #endif } Loading yaht.c +15 −11 Original line number Diff line number Diff line Loading @@ -26,9 +26,9 @@ int main(void) { printf("yaht.c\n"); menu_item items[] = { {.title = "New Game", .command = "start", .enabled = 1}, {.title = "Demo", .command = "demo", .enabled = 1}, {.title = "Exit", .command = "exit", .enabled = 1}, {.title = "New Game", .command = "start"}, {.title = "Demo", .command = "demo"}, {.title = "Exit", .command = "exit"}, }; const unsigned int num_menu_items = sizeof(items) / sizeof(menu_item); Loading Loading @@ -63,6 +63,7 @@ void take_turn(game_context *ctx, unsigned int num_dice) { clear_held_values(ctx); // print roll number printf("Roll %d\n", which_roll_number); sleep_ms(1000); // do a roll roll_and_print(ctx, next_roll_dice_values, 3); Loading @@ -70,17 +71,20 @@ void take_turn(game_context *ctx, unsigned int num_dice) { // ask if holding dice, scoring, or rolling again // (put this in a while loop so user keeps getting prompted with choice until choosing to roll again) // (also don't allow user to roll again if on the third roll) unsigned int can_move_on = 0; while (!can_move_on) { const char *player_action = menu_prompt(in_turn_menu, num_menu_items); if (strcasecmp(player_action, "enter_hold_selection") == 0) { // enter the menu for which dice to hold } else if (strcasecmp(player_action, "roll") == 0) { printf("Rolling again..."); printf("Rolling again...\n"); can_move_on = 1; } else if (strcasecmp(player_action, "score") == 0) { // enter the score menu } } } } void do_demo_dice_rolls(game_context *ctx, unsigned int num_dice) { clear_held_values(ctx); Loading Loading
menu.c +58 −4 Original line number Diff line number Diff line Loading @@ -50,7 +50,7 @@ char *menu_prompt(const menu_item *items, const unsigned int num_menu_items) { hovered_item_changed = 0; } break; case SELECT: case ENTER: selected_action = items[hovered_selection_index].command; // choose the hovered + selected item break; default: Loading @@ -62,6 +62,60 @@ char *menu_prompt(const menu_item *items, const unsigned int num_menu_items) { return selected_action; } void menu_prompt_multi_select(menu_item *items, const unsigned int num_menu_items) { for (int i = 0; i < num_menu_items; i++) { printf("\n"); // make downward room for the menu } unsigned int user_done_selecting = 0; int hovered_item_changed = 1; unsigned int hovered_selection_index = 0; // menu logic! TODO make this cross platform (play nice with Windows...) do { // return cursor to menu top position if (hovered_item_changed) { for (int i = 0; i < num_menu_items; i++) { printf("\033[A"); // move cursor up one line printf("\033[2K"); // clear entire line } // print menu items, showing selection for (int i = 0; i < num_menu_items; i++) { if (i == hovered_selection_index) { printf("> "); } printf("%s\n", items[i].title); } } MENU_DIRECTION direction = get_direction(); switch (direction) { case DOWN: if (hovered_selection_index < num_menu_items - 1) { hovered_selection_index++; hovered_item_changed = 1; } else { hovered_item_changed = 0; } break; case UP: if (hovered_selection_index > 0) { hovered_selection_index--; hovered_item_changed = 1; } else { hovered_item_changed = 0; } break; case ENTER: user_done_selecting = 1; break; default: hovered_item_changed = 0; break; } } while (!user_done_selecting); } MENU_DIRECTION get_direction(void) { // todo test (+ fix) all of this character grabbing stuff in windows - use conio.h as included above char key_pressed = (char) getchar(); // with terminal set to raw mode, this will no longer wait for Enter key; note that Enter key is handled with \n case Loading Loading @@ -93,12 +147,12 @@ MENU_DIRECTION get_direction(void) { case 'W': return UP; case '\n': return SELECT; return ENTER; case ' ': return SPACE; default: return NONE; } } menu_item *get_menu_item_by_command(menu_item *items, const unsigned int num_menu_items, char *command_to_find) { Loading
menu.h +3 −1 Original line number Diff line number Diff line Loading @@ -8,7 +8,8 @@ typedef enum { DOWN, UP, SELECT, ENTER, SPACE, NONE, } MENU_DIRECTION; Loading @@ -16,6 +17,7 @@ typedef struct { char *title; char *command; unsigned int enabled; unsigned int multi_selected; } menu_item; char *menu_prompt(const menu_item *items, unsigned int num_menu_items); Loading
utils.c +0 −3 Original line number Diff line number Diff line Loading @@ -32,15 +32,12 @@ void set_raw_terminal_configuration(void) { raw_terminal_configuration = original_terminal_configuration; // new_terminal_configuration.c_lflag &= ~ICANON & ~ECHO & ~ISIG; // disables canonical input, echo, signals (we want signals but good to know) raw_terminal_configuration.c_lflag &= ~ICANON & ~ECHO; // disables canonical input, echo // tcsetattr(STDIN_FILENO, TCSANOW, &raw_terminal_configuration); // apply settings to terminal set_terminal_configuration(&raw_terminal_configuration); #endif } void set_original_terminal_configuration(void) { #ifndef _WIN32 // setting terminal mode is only applicable for unix environments // set_terminal_configuration(&original_terminal_configuration); // tcsetattr(STDIN_FILENO, TCSANOW, &original_terminal_configuration); // apply settings to terminal set_terminal_configuration(&original_terminal_configuration); #endif } Loading
yaht.c +15 −11 Original line number Diff line number Diff line Loading @@ -26,9 +26,9 @@ int main(void) { printf("yaht.c\n"); menu_item items[] = { {.title = "New Game", .command = "start", .enabled = 1}, {.title = "Demo", .command = "demo", .enabled = 1}, {.title = "Exit", .command = "exit", .enabled = 1}, {.title = "New Game", .command = "start"}, {.title = "Demo", .command = "demo"}, {.title = "Exit", .command = "exit"}, }; const unsigned int num_menu_items = sizeof(items) / sizeof(menu_item); Loading Loading @@ -63,6 +63,7 @@ void take_turn(game_context *ctx, unsigned int num_dice) { clear_held_values(ctx); // print roll number printf("Roll %d\n", which_roll_number); sleep_ms(1000); // do a roll roll_and_print(ctx, next_roll_dice_values, 3); Loading @@ -70,17 +71,20 @@ void take_turn(game_context *ctx, unsigned int num_dice) { // ask if holding dice, scoring, or rolling again // (put this in a while loop so user keeps getting prompted with choice until choosing to roll again) // (also don't allow user to roll again if on the third roll) unsigned int can_move_on = 0; while (!can_move_on) { const char *player_action = menu_prompt(in_turn_menu, num_menu_items); if (strcasecmp(player_action, "enter_hold_selection") == 0) { // enter the menu for which dice to hold } else if (strcasecmp(player_action, "roll") == 0) { printf("Rolling again..."); printf("Rolling again...\n"); can_move_on = 1; } else if (strcasecmp(player_action, "score") == 0) { // enter the score menu } } } } void do_demo_dice_rolls(game_context *ctx, unsigned int num_dice) { clear_held_values(ctx); Loading