diff options
Diffstat (limited to 'comp.c')
-rw-r--r-- | comp.c | 106 |
1 files changed, 106 insertions, 0 deletions
@@ -0,0 +1,106 @@ +#include "board.h" +#include "checkouts.h" +#include "comp.h" +#include "match.h" + +#include <math.h> +#include <stdbool.h> +#include <stdlib.h> + +#define HORIZONTAL_STDEV 24 +#define VERTICAL_STDEV 24 + +double drand() +{ + return (double)rand() / RAND_MAX; +} + +double gauss(double mean, double stdev) +{ + static bool have_next; + static double next; + + double curr; + + if (have_next) { + curr = next; + } else { + double theta = 2 * M_PI * drand(); + double r = sqrt(-2 * log(1 - drand())); + + curr = r * cos(theta); + next = r * sin(theta); + } + + have_next = !have_next; + return mean + (curr * stdev); +} + +struct ccoords get_offset() +{ + return (struct ccoords){ .x = gauss(0, HORIZONTAL_STDEV), + .y = gauss(0, VERTICAL_STDEV) }; +} + +struct ccoords pol_to_cart(struct pcoords c) +{ + double t = c.a * (M_PI / 180); + double x = c.r * cos(t); + double y = c.r * sin(t); + + return (struct ccoords){ .x = x, .y = y }; +} + +struct pcoords cart_to_pol(struct ccoords c) +{ + double a = atan2(c.y, c.x) * (180 / M_PI); + double r = sqrt(pow(c.x, 2) + pow(c.y, 2)); + + return (struct pcoords){ .a = a, .r = r }; +} + +struct pcoords throw_dart(struct pcoords target) +{ + struct ccoords cc = pol_to_cart(target); + struct ccoords offset = get_offset(); + + return cart_to_pol((struct ccoords){ .x = cc.x + offset.x, + .y = cc.y + offset.y }); +} + +struct segment next_dart(int rem, int darts_in_hand) +{ + char *c = NULL; + if (rem <= 170) + c = CHECKOUTS[darts_in_hand-1][rem-1]; + if (!c) c = "T20"; + + return segment_from_name(c); +} + +void comp_visit(struct leg *l) +{ + struct visit *v = l->visits + l->n_visits++; + v->darts = calloc(3, sizeof(*(v->darts))); + + for (int i = 0; i < 3; ++i) { + struct segment ts = next_dart(l->rem - v->points, 3 - i); + struct pcoords tc = segment_centre(ts); + struct pcoords dc = throw_dart(tc); + struct segment ds = get_segment(dc); + + v->darts[v->n_darts++] = ds; + v->points += segment_points(ds); + + if (l->rem - v->points == 0 && segment_is_double(ds)) + break; + + if (l->rem - v->points <= 1) { + v->points = 0; + break; + } + } + + l->rem -= v->points; + v->rem = l->rem; +} |