diff options
-rw-r--r-- | dartbot.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/dartbot.c b/dartbot.c new file mode 100644 index 0000000..263bbc1 --- /dev/null +++ b/dartbot.c @@ -0,0 +1,182 @@ +#include <math.h> +#include <ncurses.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#define HORIZONTAL_STDEV 50 +#define VERTICAL_STDEV 50 + +#define WIRE_WIDTH 1.56 +#define INNER_DIAMETER_BULL 12.7 +#define INNER_DIAMETER_25 31.8 +#define DOUBLE_OUTER_EDGE 170.0 +#define TREBLE_OUTER_EDGE 107.4 +#define DOUBLE_INSIDE_WIDTH 8.0 +#define TREBLE_INSIDE_WIDTH 8.0 + +#define FOREACH_RING(M) \ + M(R_BULL, INNER_DIAMETER_BULL/2 + WIRE_WIDTH/2) \ + M(R_25, INNER_DIAMETER_25/2 + WIRE_WIDTH/2) \ + M(R_SMALL, TREBLE_OUTER_EDGE - WIRE_WIDTH - TREBLE_INSIDE_WIDTH - WIRE_WIDTH/2) \ + M(R_TREBLE, TREBLE_OUTER_EDGE - WIRE_WIDTH/2) \ + M(R_BIG, DOUBLE_OUTER_EDGE - WIRE_WIDTH - DOUBLE_INSIDE_WIDTH - WIRE_WIDTH/2) \ + M(R_DOUBLE, DOUBLE_OUTER_EDGE - WIRE_WIDTH/2) +#define GEN_RING_ENUM(X, D) X, +#define GEN_RING_STRING(X, D) #X, +#define GEN_RING_OUTER_DIST(X, D) D, + +int sectors[] = { 20, 1, 18, 4, 13, 6, 10, 15, 2, 17, 3, 19, 7, + 16, 8, 11, 14, 9, 12, 5 }; + +enum ring { + FOREACH_RING(GEN_RING_ENUM) + R_OUT +}; + +char *RING_NAMES[] = { + FOREACH_RING(GEN_RING_STRING) + "OUT" +}; + +double OUTER_DISTS[] = { + FOREACH_RING(GEN_RING_OUTER_DIST) +}; + +double CENTRE_DISTS[sizeof(OUTER_DISTS)/sizeof(*OUTER_DISTS)]; +void init_centre_dists() { + CENTRE_DISTS[0] = 0; + for (int i = R_25; i < R_OUT; ++i) + CENTRE_DISTS[i] = (OUTER_DISTS[i] - + ((OUTER_DISTS[i] - OUTER_DISTS[i-1]) / 2)); +} + +struct ccoords { + double x, y; +}; + +struct pcoords { + double a, r; +}; + +struct segment { + enum ring ring; + int sector; +}; + +int get_sector(double angle) +{ + //return sectors[(int)(fmod(angle + 279, 360) / 18)]; + double shifted = angle + 279; + return sectors[(int)((shifted - (360 * floor(shifted / 360))) / 18)]; +} + +enum ring get_ring(double radius) +{ + for (int i = R_BULL; i < R_OUT; ++i) + if (radius < OUTER_DISTS[i]) + return i; + + return R_OUT; +} + +struct ccoords gauss() +{ + double theta = 2 * M_PI * ((double)rand() / RAND_MAX); + double r = sqrt(-2 * log(1 - (double)rand() / RAND_MAX)); + return (struct ccoords){ .x = r * cos(theta), .y = r * sin(theta) }; +} + +struct ccoords get_offset() +{ + struct ccoords g = gauss(); + return (struct ccoords){ .x = g.x * HORIZONTAL_STDEV, + .y = g.y * VERTICAL_STDEV }; +} + +struct ccoords pol_to_cart(struct pcoords a) +{ + double t = a.a * (M_PI / 180); + double x = a.r * cos(t); + double y = a.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 get_segment(struct pcoords pos) +{ + return (struct segment){ .sector = get_sector(pos.a), + .ring = get_ring(pos.r) }; +} + +char *segment_name(struct segment seg) +{ + char *str = malloc(5); + + if (seg.ring == R_BULL) + strncpy(str, "BULL", 5); + else if (seg.ring == R_25) + strncpy(str, "25", 5); + else if (seg.ring == R_OUT) + strncpy(str, "OUT", 5); + else if (seg.ring == R_TREBLE) + snprintf(str, 5, "T%d", seg.sector); + else if (seg.ring == R_DOUBLE) + snprintf(str, 5, "D%d", seg.sector); + else + snprintf(str, 5, "%d", seg.sector); + + return str; +} + +int main() +{ + /* + initscr(); + addstr("test"); + refresh(); + + getch(); + endwin(); + */ + srand(time(NULL)); + init_centre_dists(); + + struct pcoords t = { .a = 90, .r = 100 }; + struct pcoords res = throw_dart(t); + struct segment seg = get_segment(res); + + for (int i = 0; i < 20; ++i) { + res = throw_dart(t); + seg = get_segment(res); + char *name = segment_name(seg); + printf("%d %f %f %d %s %s\n", seg.sector, res.a, res.r, seg.ring, RING_NAMES[seg.ring], name); + free(name); + } + + /* + printf("\n"); + for (int i = 0; i < 6; i++) { + printf("%.2f\n%.2f\n\n", CENTRE_DISTS[i], OUTER_DISTS[i]); + } + */ + + return 0; +} |