summaryrefslogtreecommitdiff
path: root/match.c
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-05-23 15:23:48 -0700
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-05-23 15:25:07 -0700
commit15ff00e056a98ab4210dde3d4461a88849d6c1d4 (patch)
tree280b8d248baee5d2ae0dcc2117e3f2b309d128ec /match.c
parentc93897ed2013f20d6ece33815971d206fd0d056e (diff)
downloaddartboat-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.c106
1 files changed, 98 insertions, 8 deletions
diff --git a/match.c b/match.c
index 1e131f0..03e91fd 100644
--- a/match.c
+++ b/match.c
@@ -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 &&