diff options
Diffstat (limited to 'board.c')
-rw-r--r-- | board.c | 140 |
1 files changed, 140 insertions, 0 deletions
@@ -0,0 +1,140 @@ +#include "board.h" + +#include <math.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define NUM_SECTORS (sizeof(SECTORS) / sizeof(*SECTORS)) +#define SECTOR_WIDTH (360.0 / NUM_SECTORS) +int SECTORS[] = { 20, 1, 18, 4, 13, 6, 10, 15, 2, 17, 3, 19, 7, + 16, 8, 11, 14, 9, 12, 5 }; +int SECTOR_INDS[NUM_SECTORS]; +double SECTOR_ANGLES[NUM_SECTORS]; + +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)]; + +static void init_sectors() +{ + for (size_t i = 0; i < NUM_SECTORS; ++i) { + SECTOR_INDS[SECTORS[i]-1] = i; + + double angle = 90 - (i * SECTOR_WIDTH); + if (angle < 0) angle += 360; + SECTOR_ANGLES[i] = angle; + } +} + +static 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)); +} + +void init_board() +{ + init_sectors(); + init_centre_dists(); +} + +int get_sector(double angle) +{ + double shifted = angle - 90 - (SECTOR_WIDTH/2); + return SECTORS[NUM_SECTORS - 1 - + (int)((shifted - (360 * floor(shifted/360))) / SECTOR_WIDTH)]; +} + +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 segment get_segment(struct pcoords c) +{ + return (struct segment){ .sector = get_sector(c.a), + .ring = get_ring(c.r) }; +} + +char *segment_name(struct segment seg) +{ + char *str = malloc(SEGMENT_MAX_LEN); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" + if (seg.ring == R_BULL || seg.ring == R_25 || seg.ring == R_OUT) + strncpy(str, RING_NAMES[seg.ring], SEGMENT_MAX_LEN); + else + snprintf(str, SEGMENT_MAX_LEN, + (seg.ring == R_TREBLE ? "T%d" : + (seg.ring == R_DOUBLE ? "D%d" : "%d")), + seg.sector); +#pragma GCC diagnostic pop + + return str; +} + +int segment_points(struct segment seg) +{ + if (seg.ring == R_BULL) + return 50; + else if (seg.ring == R_25) + return 25; + else if (seg.ring == R_TREBLE) + return 3 * seg.sector; + else if (seg.ring == R_DOUBLE) + return 2 * seg.sector; + else if (seg.ring == R_SMALL || seg.ring == R_BIG) + return seg.sector; + return 0; +} + +bool segment_is_double(struct segment seg) +{ + if (seg.ring == R_DOUBLE || seg.ring == R_BULL) + return true; + return false; +} + +struct pcoords segment_centre(struct segment seg) +{ + return (struct pcoords){ .a = SECTOR_ANGLES[SECTOR_INDS[seg.sector-1]], + .r = CENTRE_DISTS[seg.ring] }; +} + +struct segment segment_from_name(char *name) +{ + int s = 20; + enum ring r; + + if (!strcmp(name, "BULL")) { + r = R_BULL; + } else if (!strcmp(name, "25")) { + r = R_25; + } else if (name[0] == 'T') { + r = R_TREBLE; + s = atoi(name+1); + } else if (name[0] == 'D') { + r = R_DOUBLE; + s = atoi(name+1); + } else { + r = R_BIG; + s = atoi(name); + } + + return (struct segment){ .sector = s, .ring = r }; +} |