#include "web_match.h" #include "match.h" #include #include #include struct match_state *state; struct match_opts *match_opts; static int curr_id = 0; void match_new() { if (state) free_state(); state = calloc(1, sizeof(*state)); state->id = ++curr_id; state->size_players = 2; state->legs = malloc(state->size_players * sizeof(*(state->legs))); state->player_types = malloc(state->size_players * sizeof(*(state->player_types))); state->comp_undone = malloc(state->size_players * sizeof(*(state->comp_undone))); } void match_add_player(int start_pts, enum player_type type, char *name) { if (state->num_players == state->size_players) { state->size_players += state->size_players ? state->size_players : 1; state->legs = realloc(state->legs, state->size_players * sizeof(*(state->legs))); state->player_types = realloc(state->player_types, state->size_players * sizeof(*(state->player_types))); state->comp_undone = realloc(state->comp_undone, state->size_players * sizeof(*(state->comp_undone))); } state->legs[state->num_players] = leg_init(start_pts, name); state->player_types[state->num_players] = type; state->comp_undone[state->num_players++] = 0; } void free_state() { for (int i = 0; i < state->num_players; ++i) { // undone visits readded before free to avoid memory leak state->legs[i]->n_visits += state->comp_undone[i]; leg_free(state->legs[i]); } free(state->legs); free(state); state = NULL; } 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( match_opts->size_players * sizeof(*(match_opts->players))); } void match_opts_add_player(enum player_type type, char *name) { if (match_opts->num_players == match_opts->size_players) { match_opts->size_players += match_opts->size_players ? match_opts->size_players : 1; match_opts->players = realloc(match_opts->players, match_opts->size_players * sizeof(*(match_opts->players))); } 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() { if (!match_opts) return; free(match_opts->players); free(match_opts); match_opts = NULL; } struct leg *state_active_leg() { return state->legs[state->active_player - 1]; } int match_num_players() { return state->num_players; } int match_winning_player() { for (int i = 0; i < match_num_players(); ++i) { if (state->legs[i]->rem == 0) return i + 1; } return 0; } bool match_is_over() { return match_winning_player() != 0; } int match_prev_player() { if (state->active_player == 1) return match_num_players(); else return state->active_player - 1; } int match_next_player() { if (state->active_player == match_num_players()) return 1; else return state->active_player + 1; } int match_prev_throw_player() { if (match_is_over()) return state->active_player; return match_prev_player(); } bool match_player_is_comp(int pn) { return state->player_types[pn - 1] == PT_COMP; } bool match_first_user_has_thrown() { for (int i = 0, np = match_num_players(); i < np; ++i) { int pn = match_opts->throws_first + i; if (pn > np) pn -= np; if (!match_player_is_comp(pn)) return !!state->legs[pn - 1]->n_visits; } return false; }