diff options
author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2022-05-23 15:23:48 -0700 |
---|---|---|
committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2022-05-23 15:25:07 -0700 |
commit | 15ff00e056a98ab4210dde3d4461a88849d6c1d4 (patch) | |
tree | 280b8d248baee5d2ae0dcc2117e3f2b309d128ec /match.c | |
parent | c93897ed2013f20d6ece33815971d206fd0d056e (diff) | |
download | dartboat-15ff00e056a98ab4210dde3d4461a88849d6c1d4.tar.gz dartboat-15ff00e056a98ab4210dde3d4461a88849d6c1d4.tar.xz |
move a bunch of general match logic from web to lib
Diffstat (limited to 'match.c')
-rw-r--r-- | match.c | 106 |
1 files changed, 98 insertions, 8 deletions
@@ -1,12 +1,13 @@ #include "match.h" +#include <stdbool.h> #include <stdlib.h> #include <string.h> -struct leg *leg_init(int points, char *name) +struct leg *leg_init(int points) { struct leg *l = calloc(1, sizeof(*l)); - l->name = strdup(name); + l->start = l->rem = points; l->size_visits = 16; l->visits = calloc(l->size_visits, sizeof(*(l->visits))); @@ -16,26 +17,115 @@ struct leg *leg_init(int points, char *name) void leg_free(struct leg *l) { + // readd undone visits before free to avoid memory leak + l->n_visits += l->undone_visits; + for (int i = 0; i < l->n_visits; ++i) { - if (l->visits[i].darts) - free(l->visits[i].darts); - if (l->visits[i].ccoords) - free(l->visits[i].ccoords); + free(l->visits[i].darts); + free(l->visits[i].ccoords); } free(l->visits); - free(l->name); free(l); } void leg_grow_visits(struct leg *l) { - size_t bytes = l->size_visits * sizeof(*(l->visits)); l->size_visits *= 2; l->visits = realloc(l->visits, 2 * bytes); memset((char *)l->visits + bytes, 0, bytes); } +void leg_undo_visit(struct leg *l) +{ + l->rem += l->visits[--l->n_visits].points; + ++l->undone_visits; +} + +void leg_redo_visit(struct leg *l) +{ + l->rem = l->visits[l->n_visits++].rem; + --l->undone_visits; +} + +struct match *match_init() +{ + struct match *m = calloc(1, sizeof(*m)); + + m->size_players = 2; + m->players = malloc(m->size_players * sizeof(*m->players)); + m->legs = malloc(m->size_players * sizeof(*m->legs)); + + return m; +} + +void match_free(struct match *m) +{ + for (int i = 0; i < m->n_players; ++i) { + free(m->players[i].name); + leg_free(m->legs[i]); + } + + free(m->players); + free(m->legs); + free(m); +} + +static void match_grow_players(struct match *m) +{ + m->size_players *= 2; + m->players = realloc(m->players, + m->size_players * sizeof(*m->players)); + m->legs = realloc(m->legs, + m->size_players * sizeof(*m->legs)); +} + +void match_add_player(struct match *m, enum player_type type, char *name, + int start_pts) +{ + if (m->n_players == m->size_players) + match_grow_players(m); + int i = m->n_players++; + + struct player *p = m->players + i; + p->type = type; + p->name = strdup(name); + + m->legs[i] = leg_init(start_pts); +} + +int match_next_player(struct match *m) +{ + if (m->active_player == m->n_players) + return 1; + else + return m->active_player + 1; +} + +int match_prev_player(struct match *m) +{ + if (m->active_player == 1) + return m->n_players; + else + return m->active_player - 1; +} + +int match_last_player_to_throw(struct match *m) +{ + int p = match_winning_player(m); + return p ? p : match_prev_player(m); +} + +int match_winning_player(struct match *m) +{ + for (int i = 0; i < m->n_players; ++i) { + if (m->legs[i]->rem == 0) + return i + 1; + } + + return 0; +} + bool is_points_valid(int pts, int rem) { return pts <= rem && |