Commit 5e50fb38 authored by Chris's avatar Chris
Browse files

WIP hold menu

parent 83bc981e
Loading
Loading
Loading
Loading
+135 −18
Original line number Diff line number Diff line
@@ -2,12 +2,50 @@

#include <stdio.h>
#include <time.h>
#include <string.h>
#include "gamelogic.h"
#include "graphics.h"
#include "menu.h"
#include "utils.h"

const unsigned int SCORECARD_NUM_ITEMS = 13;

const unsigned int NUM_DICE = 5;
const int SCORE_UNSCORED = -1;
const unsigned int ROLLS_PER_TURN = 3;
const unsigned int ROLL_NUMBER_OFFSET = 1;

void init_die_st(struct die_st *die) {
    die->held = 0;
    die->value = 0;
}

void init_game_state(struct game_state_st *state) {
    // initialize dice array
    for (unsigned int i = 0; i < NUM_DICE; i++) {
        init_die_st(&state->dice[i]);
    }

    // initialize scorecard
    initialize_scorecard(&state->scorecard);
}

void initialize_scorecard(struct scorecard_st *scorecard) {
    scorecard->aces
            = scorecard->twos
            = scorecard->threes
            = scorecard->fours
            = scorecard->fives
            = scorecard->sixes
            = scorecard->three_of_a_kind
            = scorecard->four_of_a_kind
            = scorecard->full_house
            = scorecard->small_straight
            = scorecard->large_straight
            = scorecard->yahtc
            = scorecard->chance
            = SCORE_UNSCORED;
}

void roll_and_print(game_context *ctx, unsigned int *out_dice_values, unsigned int animation_seconds) {
    unsigned int temporary_next_roll[NUM_DICE];
@@ -28,7 +66,7 @@ void roll_and_print(game_context *ctx, unsigned int *out_dice_values, unsigned i
}

void generate_dice_roll(game_context *ctx, unsigned int *out_dice_values, int save_in_game_state) {
    for (int i = 0; i < NUM_DICE; i++) {
    for (unsigned int i = 0; i < NUM_DICE; i++) {
        if (ctx->game_state.dice[i].held) {
            out_dice_values[i] = ctx->game_state.dice[i].value;
        } else {
@@ -63,33 +101,78 @@ int set_die_held(game_context *ctx, unsigned int index, unsigned int held) {
}

void clear_held_values(game_context *ctx) {
    for (int i = 0; i < NUM_DICE; i++) {
    for (unsigned int i = 0; i < NUM_DICE; i++) {
        ctx->game_state.dice[i].held = 0;
    }
}

unsigned int calculate_score(struct scorecard_st *scorecard, char *scoring_selection) {
// actual game logic will go in here
unsigned int calculate_selection_score(game_context *ctx, char *selection) {
    // discern score action based on the scoring selection
    // we pass in a whole game_context because we need to write to the scorecard and read the dice values
    if (strcasecmp(selection, "aces") == 0) {
        ctx->game_state.scorecard.aces = sum_dice_matching_value(ctx->game_state.dice, 1);
    } else if (strcasecmp(selection, "twos") == 0) {
        ctx->game_state.scorecard.twos = sum_dice_matching_value(ctx->game_state.dice, 2);
    } else if (strcasecmp(selection, "threes") == 0) {
        ctx->game_state.scorecard.threes = sum_dice_matching_value(ctx->game_state.dice, 3);
    } else if (strcasecmp(selection, "fours") == 0) {
        ctx->game_state.scorecard.fours = sum_dice_matching_value(ctx->game_state.dice, 4);
    } else if (strcasecmp(selection, "fives") == 0) {
        ctx->game_state.scorecard.fives = sum_dice_matching_value(ctx->game_state.dice, 5);
    } else if (strcasecmp(selection, "sixes") == 0) {
        ctx->game_state.scorecard.sixes = sum_dice_matching_value(ctx->game_state.dice, 6);
    } else if (strcasecmp(selection, "three_of_a_kind") == 0) {
        // sum all dice if 3 of a kind match; 0 otherwise
        printf("not implemented, scoring 0 for now");
        ctx->game_state.scorecard.three_of_a_kind = 0;
    } else if (strcasecmp(selection, "four_of_a_kind") == 0) {
        // sum all dice if 4 of a kind match; 0 otherwise
        printf("not implemented, scoring 0 for now");
        ctx->game_state.scorecard.four_of_a_kind = 0;
    } else if (strcasecmp(selection, "full_house") == 0) {
        // 25 points for a combination of three of one number + two of another; 0 otherwise
        printf("not implemented, scoring 0 for now");
        ctx->game_state.scorecard.full_house = 0;
    } else if (strcasecmp(selection, "small_straight") == 0) {
        // 30 points for a sequence of four consecutive numbers; 0 otherwise
        printf("not implemented, scoring 0 for now");
        ctx->game_state.scorecard.small_straight = 0;
    } else if (strcasecmp(selection, "large_straight") == 0) {
        // 40 points for a sequence of five consecutive numbers; 0 otherwise
        printf("not implemented, scoring 0 for now");
        ctx->game_state.scorecard.large_straight = 0;
    } else if (strcasecmp(selection, "yahtc") == 0) {
        // 50 points for five of a kind; 0 otherwise
        printf("not implemented, scoring 0 for now");
        ctx->game_state.scorecard.yahtc = 0;
    } else if (strcasecmp(selection, "chance") == 0) {
        // sum of all dice
        printf("not implemented, scoring 0 for now");
        ctx->game_state.scorecard.chance = 0;
    }

    // default
    return 0;
}

void initialize_scorecard(struct scorecard_st *scorecard) {
    scorecard->aces
            = scorecard->twos
            = scorecard->threes
            = scorecard->fours
            = scorecard->fives
            = scorecard->sixes
            = scorecard->three_of_a_kind
            = scorecard->four_of_a_kind
            = scorecard->full_house
            = scorecard->small_straight
            = scorecard->large_straight
            = scorecard->yahtc
            = scorecard->chance
            = SCORE_UNSCORED;
unsigned int calculate_total_score(struct scorecard_st *scorecard) {
    return (scorecard->aces >= 0 ? scorecard->aces : 0)
            + (scorecard->twos >= 0 ? scorecard->twos : 0)
            + (scorecard->threes >= 0 ? scorecard->threes : 0)
            + (scorecard->fours >= 0 ? scorecard->fours : 0)
            + (scorecard->fives >= 0 ? scorecard->fives : 0)
            + (scorecard->sixes >= 0 ? scorecard->sixes : 0)
            + (scorecard->three_of_a_kind >= 0 ? scorecard->three_of_a_kind : 0)
            + (scorecard->four_of_a_kind >= 0 ? scorecard->four_of_a_kind : 0)
            + (scorecard->full_house >= 0 ? scorecard->full_house : 0)
            + (scorecard->small_straight >= 0 ? scorecard->small_straight : 0)
            + (scorecard->large_straight >= 0 ? scorecard->large_straight : 0)
            + (scorecard->yahtc >= 0 ? scorecard->yahtc : 0)
            + (scorecard->chance >= 0 ? scorecard->chance : 0);
}


unsigned int can_continue_playing(struct scorecard_st *scorecard) {
    return scorecard->aces == SCORE_UNSCORED
           || scorecard->twos == SCORE_UNSCORED
@@ -105,3 +188,37 @@ unsigned int can_continue_playing(struct scorecard_st *scorecard) {
           || scorecard->yahtc == SCORE_UNSCORED
           || scorecard->chance == SCORE_UNSCORED;
}


void hold_dice_with_menu(struct die_st *dice, unsigned int num_dice) {
    menu_item dice_hold_selections[num_dice];
    printf("initializing hold dice menu\n");
    for (unsigned int i = 0; i < num_dice; i++) {
        unsigned int human_readable_i = i + 1;
        sprintf(dice_hold_selections[i].title, "%d", human_readable_i);
        dice_hold_selections[i].multi_selected = dice[i].held;
        dice_hold_selections[i].enabled = 1;
        sprintf(dice_hold_selections[i].command, "toggle_hold_%d", i);
    }
    printf("prompting hold dice menu\n");
    menu_prompt_multi_select(dice_hold_selections, num_dice);
    printf("done prompting hold dice menu; saving selections\n");
    for (unsigned int i = 0; i < num_dice; i++) {
        dice[i].held = dice_hold_selections[i].multi_selected;
    }
    printf("hold_dice_with_menu() done\n");
}

char *get_player_score_selection() {
    return ""; // placeholder
}

int sum_dice_matching_value(struct die_st *dice, unsigned int value) {
    int sum = 0;
    for (unsigned int i = 0; i < NUM_DICE; i++) {
        if (dice->value == value) {
            sum += dice->value;
        }
    }
    return sum;
}
+12 −6
Original line number Diff line number Diff line
@@ -7,14 +7,14 @@

extern const unsigned int NUM_DICE;
extern const int SCORE_UNSCORED;

//const unsigned int MAX_TURNS = 3;
//const unsigned int TURN_NUMBER_OFFSET = 1;
extern const unsigned int ROLLS_PER_TURN;
extern const unsigned int ROLL_NUMBER_OFFSET;

struct die_st {
    unsigned int value;
    int value;
    unsigned int held;
};
void init_die_st(struct die_st *die);

struct scorecard_st {
    int aces;
@@ -31,11 +31,13 @@ struct scorecard_st {
    int yahtc; // five of a kind
    int chance;
};
extern const unsigned int SCORECARD_NUM_ITEMS;

struct game_state_st {
    struct die_st dice[5];
    struct scorecard_st scorecard;
};
void init_game_state(struct game_state_st *state);

typedef struct game_context_st {
    FILE *random_device_fd;
@@ -44,15 +46,19 @@ typedef struct game_context_st {

// dice functions
unsigned int generate_single_die_roll(FILE *urandom_file);
// todo disassemble: I don't want to reference the entire ctx in these, I want to reference direct struct members directly
// todo deconstruct ctx arguments: I don't want to reference the entire ctx in most of these, I want to reference direct struct members directly
void generate_dice_roll(game_context *ctx, unsigned int *out_dice_values, int save_in_game_state);
int set_die_held(game_context *ctx, unsigned int index, unsigned int held);
void roll_and_print(game_context *ctx, unsigned int *out_dice_values, unsigned int animation_seconds);
void clear_held_values(game_context *ctx);
unsigned int can_continue_playing(struct scorecard_st *scorecard);
void hold_dice_with_menu(struct die_st *dice, unsigned int num_dice);

// scorecard functions
unsigned int calculate_score(struct scorecard_st *scorecard, char *scoring_selection);
unsigned int calculate_selection_score(game_context *ctx, char *selection);
unsigned int calculate_total_score(struct scorecard_st *scorecard);
void initialize_scorecard(struct scorecard_st *scorecard);
char *get_player_score_selection();
int sum_dice_matching_value(struct die_st *dice, unsigned int value);

#endif //DICELOGIC_H
+7 −7
Original line number Diff line number Diff line
@@ -7,14 +7,14 @@ void print_single_die(unsigned int die_value) {
		die_value = 0;
	}

	for (int i = 0; i < DIE_VERTICAL_LENGTH; i++) {
	for (unsigned int i = 0; i < DIE_VERTICAL_LENGTH; i++) {
		printf("%s\n", DICE[die_value][i]);
	}
}

void print_multiple_dice(const unsigned int *die_value, const int n) {
	for (int which_row = 0; which_row < DIE_VERTICAL_LENGTH; which_row++) {
		for (int j = 0; j < n; j++) {
void print_multiple_dice(const unsigned int *die_value, const unsigned int n) {
	for (unsigned int which_row = 0; which_row < DIE_VERTICAL_LENGTH; which_row++) {
		for (unsigned int j = 0; j < n; j++) {
			unsigned int which_die = die_value[j];
			printf("%s  ", DICE[which_die][which_row]);
		}
@@ -24,10 +24,10 @@ void print_multiple_dice(const unsigned int *die_value, const int n) {

// to only be called after print_multiple_dice() as this will return the terminal cursor to its original positon
//		useful for erasing or positioning for redraw of dice area
void cursor_to_dice_start(const int erase_lines) {
void cursor_to_dice_start(unsigned int erase_lines) {
	// move cursor up
	// for (int i = 0; i < DIE_VERTICAL_LENGTH + 1; i++) {
	for (int i = 0; i < DIE_VERTICAL_LENGTH; i++) {
	// for (unsigned int i = 0; i < DIE_VERTICAL_LENGTH + 1; i++) {
	for (unsigned int i = 0; i < DIE_VERTICAL_LENGTH; i++) {
		printf("\033[A"); // move cursor up one line
		if (i < erase_lines) {
			printf("\033[2K"); // clear entire line
+4 −4
Original line number Diff line number Diff line
@@ -8,8 +8,8 @@
#include <stdarg.h>
#include "utils.h"

static const int DIE_VERTICAL_LENGTH = 6;
static const int DICE_ARRAY_LENGTH = 7;
static const unsigned int DIE_VERTICAL_LENGTH = 6;
static const unsigned int DICE_ARRAY_LENGTH = 7;

static const char *DICE[7][6] = {
	{	
@@ -73,7 +73,7 @@ static const char *DICE[7][6] = {
};

void print_single_die(unsigned int die_value);
void print_multiple_dice(const unsigned int *die_value, int n);
void cursor_to_dice_start(int erase_lines);
void print_multiple_dice(const unsigned int *die_value, unsigned int n);
void cursor_to_dice_start(unsigned int erase_lines);

#endif //GRAPHICS_H_
+18 −8
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
MENU_DIRECTION get_direction(void);

char *menu_prompt(const menu_item *items, const unsigned int num_menu_items) {
    for (int i = 0; i < num_menu_items; i++) {
    for (unsigned int i = 0; i < num_menu_items; i++) {
        printf("\n"); // make downward room for the menu
    }
    char *selected_action = "";
@@ -17,13 +17,13 @@ char *menu_prompt(const menu_item *items, const unsigned int num_menu_items) {
    do {
        // return cursor to menu top position
        if (hovered_item_changed) {
            for (int i = 0; i < num_menu_items; i++) {
            for (unsigned 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++) {
            for (unsigned int i = 0; i < num_menu_items; i++) {
                if (i == hovered_selection_index) {
                    printf("> ");
                }
@@ -51,7 +51,9 @@ char *menu_prompt(const menu_item *items, const unsigned int num_menu_items) {
                }
                break;
            case ENTER:
                if (items[hovered_selection_index].enabled) {
                    selected_action = items[hovered_selection_index].command; // choose the hovered + selected item
                }
                break;
            default:
                hovered_item_changed = 0;
@@ -63,7 +65,7 @@ char *menu_prompt(const menu_item *items, const unsigned int num_menu_items) {
}

void menu_prompt_multi_select(menu_item *items, const unsigned int num_menu_items) {
    for (int i = 0; i < num_menu_items; i++) {
    for (unsigned int i = 0; i < num_menu_items; i++) {
        printf("\n"); // make downward room for the menu
    }
    unsigned int user_done_selecting = 0;
@@ -73,16 +75,19 @@ void menu_prompt_multi_select(menu_item *items, const unsigned int num_menu_item
    do {
        // return cursor to menu top position
        if (hovered_item_changed) {
            for (int i = 0; i < num_menu_items; i++) {
            for (unsigned 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++) {
            for (unsigned int i = 0; i < num_menu_items; i++) {
                if (i == hovered_selection_index) {
                    printf("> ");
                }
                if (items[i].multi_selected) {
                    printf(" [selected] ");
                }
                printf("%s\n", items[i].title);
            }
        }
@@ -106,8 +111,13 @@ void menu_prompt_multi_select(menu_item *items, const unsigned int num_menu_item
                    hovered_item_changed = 0;
                }
                break;
            case SPACE:
                items[hovered_selection_index].multi_selected = !items[hovered_selection_index].multi_selected;
                hovered_item_changed = 1;
            case ENTER:
                if (items[hovered_selection_index].enabled) {
                    user_done_selecting = 1;
                }
                break;
            default:
                hovered_item_changed = 0;
Loading