diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | board.c | 140 | ||||
-rw-r--r-- | board.h | 57 | ||||
-rw-r--r-- | checkouts.c | 525 | ||||
-rw-r--r-- | checkouts.h | 519 | ||||
-rw-r--r-- | comp.c | 106 | ||||
-rw-r--r-- | comp.h | 8 | ||||
-rw-r--r-- | curses.c | 144 | ||||
-rw-r--r-- | curses.h | 40 | ||||
-rw-r--r-- | dartbot.c | 465 | ||||
-rw-r--r-- | match.c | 22 | ||||
-rw-r--r-- | match.h | 24 |
12 files changed, 1080 insertions, 976 deletions
@@ -1,16 +1,20 @@ CFLAGS += -O2 -Wall -Wextra -Wpedantic +CPPFLAGS += -MMD -MP LDFLAGS += -lm -lncurses TARGET := dartbot SRC := $(wildcard *.c) OBJ := $(SRC:.c=.o) +DEP := $(OBJ:.o=.d) all: $(TARGET) $(TARGET): $(OBJ) clean: - rm -f $(TARGET) $(OBJ) + rm -f $(TARGET) $(OBJ) $(DEP) + +-include $(DEP) .PHONY: all clean @@ -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 }; +} @@ -0,0 +1,57 @@ +#ifndef BOARD_H +#define BOARD_H + +#include <stdbool.h> + +// board spec from WDF rules +#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 SEGMENT_MAX_LEN 5 +// distance from centre to apex of outer wire +// must be ordered outwards from centre +#define FOREACH_RING(M) \ + M(BULL, INNER_DIAMETER_BULL/2 + WIRE_WIDTH/2) \ + M(25, INNER_DIAMETER_25/2 + WIRE_WIDTH/2) \ + M(SMALL, TREBLE_OUTER_EDGE - WIRE_WIDTH - TREBLE_INSIDE_WIDTH - \ + WIRE_WIDTH/2) \ + M(TREBLE, TREBLE_OUTER_EDGE - WIRE_WIDTH/2) \ + M(BIG, DOUBLE_OUTER_EDGE - WIRE_WIDTH - DOUBLE_INSIDE_WIDTH - \ + WIRE_WIDTH/2) \ + M(DOUBLE, DOUBLE_OUTER_EDGE - WIRE_WIDTH/2) +#define GEN_RING_ENUM(X, D) R_ ## X, +#define GEN_RING_STRING(X, D) #X, +#define GEN_RING_OUTER_DIST(X, D) D, +enum ring { + FOREACH_RING(GEN_RING_ENUM) + R_OUT +}; + +struct segment { + enum ring ring; + int sector; +}; + +void init_board(); + +struct ccoords { + double x, y; +}; + +struct pcoords { + double a, r; +}; + +struct segment get_segment(struct pcoords c); +char *segment_name(struct segment seg); +int segment_points(struct segment seg); +bool segment_is_double(struct segment seg); +struct pcoords segment_centre(struct segment seg); +struct segment segment_from_name(char *name); + +#endif diff --git a/checkouts.c b/checkouts.c new file mode 100644 index 0000000..230c264 --- /dev/null +++ b/checkouts.c @@ -0,0 +1,525 @@ +#ifndef CHECKOUT_H +#define CHECKOUT_H + +#include <stddef.h> + +char *CHECKOUTS[][170] = { + { + NULL, // 1 + "D1", // 2 + NULL, // 3 + "D2", // 4 + NULL, // 5 + "D3", // 6 + NULL, // 7 + "D4", // 8 + NULL, // 9 + "D5", // 10 + NULL, // 11 + "D6", // 12 + NULL, // 13 + "D7", // 14 + NULL, // 15 + "D8", // 16 + NULL, // 17 + "D9", // 18 + NULL, // 19 + "D10", // 20 + NULL, // 21 + "D11", // 22 + NULL, // 23 + "D12", // 24 + NULL, // 25 + "D13", // 26 + NULL, // 27 + "D14", // 28 + NULL, // 29 + "D15", // 30 + NULL, // 31 + "D16", // 32 + NULL, // 33 + "D17", // 34 + NULL, // 35 + "D18", // 36 + NULL, // 37 + "D19", // 38 + NULL, // 39 + "D20", // 40 + NULL, // 41 + NULL, // 42 + NULL, // 43 + NULL, // 44 + NULL, // 45 + NULL, // 46 + NULL, // 47 + NULL, // 48 + NULL, // 49 + "BULL", // 50 + NULL, // 51 + NULL, // 52 + NULL, // 53 + NULL, // 54 + NULL, // 55 + NULL, // 56 + NULL, // 57 + NULL, // 58 + NULL, // 59 + NULL, // 60 + NULL, // 61 + NULL, // 62 + NULL, // 63 + NULL, // 64 + NULL, // 65 + NULL, // 66 + NULL, // 67 + NULL, // 68 + NULL, // 69 + NULL, // 70 + NULL, // 71 + NULL, // 72 + NULL, // 73 + NULL, // 74 + NULL, // 75 + NULL, // 76 + NULL, // 77 + NULL, // 78 + NULL, // 79 + NULL, // 80 + NULL, // 81 + NULL, // 82 + NULL, // 83 + NULL, // 84 + NULL, // 85 + NULL, // 86 + NULL, // 87 + NULL, // 88 + NULL, // 89 + NULL, // 90 + NULL, // 91 + NULL, // 92 + NULL, // 93 + NULL, // 94 + NULL, // 95 + NULL, // 96 + NULL, // 97 + NULL, // 98 + NULL, // 99 + NULL, // 100 + NULL, // 101 + NULL, // 102 + NULL, // 103 + NULL, // 104 + NULL, // 105 + NULL, // 106 + NULL, // 107 + NULL, // 108 + NULL, // 109 + NULL, // 110 + NULL, // 111 + NULL, // 112 + NULL, // 113 + NULL, // 114 + NULL, // 115 + NULL, // 116 + NULL, // 117 + NULL, // 118 + NULL, // 119 + NULL, // 120 + NULL, // 121 + NULL, // 122 + NULL, // 123 + NULL, // 124 + NULL, // 125 + NULL, // 126 + NULL, // 127 + NULL, // 128 + NULL, // 129 + NULL, // 130 + NULL, // 131 + NULL, // 132 + NULL, // 133 + NULL, // 134 + NULL, // 135 + NULL, // 136 + NULL, // 137 + NULL, // 138 + NULL, // 139 + NULL, // 140 + NULL, // 141 + NULL, // 142 + NULL, // 143 + NULL, // 144 + NULL, // 145 + NULL, // 146 + NULL, // 147 + NULL, // 148 + NULL, // 149 + NULL, // 150 + NULL, // 151 + NULL, // 152 + NULL, // 153 + NULL, // 154 + NULL, // 155 + NULL, // 156 + NULL, // 157 + NULL, // 158 + NULL, // 159 + NULL, // 160 + NULL, // 161 + NULL, // 162 + NULL, // 163 + NULL, // 164 + NULL, // 165 + NULL, // 166 + NULL, // 167 + NULL, // 168 + NULL, // 169 + NULL, // 170 + }, + { + NULL, // 1 + "D1", // 2 + "1", // 3 + "D2", // 4 + "1", // 5 + "D3", // 6 + "3", // 7 + "D4", // 8 + "1", // 9 + "D5", // 10 + "3", // 11 + "D6", // 12 + "5", // 13 + "D7", // 14 + "7", // 15 + "D8", // 16 + "1", // 17 + "D9", // 18 + "3", // 19 + "D10", // 20 + "17", // 21 + "D11", // 22 + "7", // 23 + "D12", // 24 + "17", // 25 + "D13", // 26 + "3", // 27 + "D14", // 28 + "17", // 29 + "D15", // 30 + "7", // 31 + "D16", // 32 + "17", // 33 + "D17", // 34 + "3", // 35 + "D18", // 36 + "17", // 37 + "D19", // 38 + "7", // 39 + "D20", // 40 + "17", // 41 + "10", // 42 + "3", // 43 + "12", // 44 + "13", // 45 + "14", // 46 + "15", // 47 + "16", // 48 + "17", // 49 + "18", // 50 + "19", // 51 + "20", // 52 + "13", // 53 + "14", // 54 + "15", // 55 + "16", // 56 + "17", // 57 + "18", // 58 + "19", // 59 + "20", // 60 + "T11", // 61 + "T12", // 62 + "T13", // 63 + "T14", // 64 + "T15", // 65 + "T16", // 66 + "T17", // 67 + "T18", // 68 + "T19", // 69 + "T20", // 70 + "T19", // 71 + "T16", // 72 + "T19", // 73 + "T16", // 74 + "T17", // 75 + "T20", // 76 + "T19", // 77 + "T18", // 78 + "T19", // 79 + "T20", // 80 + "T19", // 81 + "T14", // 82 + "T17", // 83 + "T20", // 84 + "T15", // 85 + "T18", // 86 + "T17", // 87 + "T16", // 88 + "T19", // 89 + "T18", // 90 + "T17", // 91 + "T20", // 92 + "T19", // 93 + "T18", // 94 + "T19", // 95 + "T20", // 96 + "T19", // 97 + "T20", // 98 + NULL, // 99 + "T20", // 100 + "T17", // 101 + NULL, // 102 + NULL, // 103 + "T18", // 104 + NULL, // 105 + NULL, // 106 + "T19", // 107 + NULL, // 108 + NULL, // 109 + "T20", // 110 + NULL, // 111 + NULL, // 112 + NULL, // 113 + NULL, // 114 + NULL, // 115 + NULL, // 116 + NULL, // 117 + NULL, // 118 + NULL, // 119 + NULL, // 120 + NULL, // 121 + NULL, // 122 + NULL, // 123 + NULL, // 124 + NULL, // 125 + NULL, // 126 + NULL, // 127 + NULL, // 128 + NULL, // 129 + NULL, // 130 + NULL, // 131 + NULL, // 132 + NULL, // 133 + NULL, // 134 + NULL, // 135 + NULL, // 136 + NULL, // 137 + NULL, // 138 + NULL, // 139 + NULL, // 140 + NULL, // 141 + NULL, // 142 + NULL, // 143 + NULL, // 144 + NULL, // 145 + NULL, // 146 + NULL, // 147 + NULL, // 148 + NULL, // 149 + NULL, // 150 + NULL, // 151 + NULL, // 152 + NULL, // 153 + NULL, // 154 + NULL, // 155 + NULL, // 156 + NULL, // 157 + NULL, // 158 + NULL, // 159 + NULL, // 160 + NULL, // 161 + NULL, // 162 + NULL, // 163 + NULL, // 164 + NULL, // 165 + NULL, // 166 + NULL, // 167 + NULL, // 168 + NULL, // 169 + NULL, // 170 + }, + { + NULL, // 1 + "D1", // 2 + "1", // 3 + "D2", // 4 + "1", // 5 + "D3", // 6 + "3", // 7 + "D4", // 8 + "1", // 9 + "D5", // 10 + "3", // 11 + "D6", // 12 + "5", // 13 + "D7", // 14 + "7", // 15 + "D8", // 16 + "1", // 17 + "D9", // 18 + "3", // 19 + "D10", // 20 + "5", // 21 + "D11", // 22 + "7", // 23 + "D12", // 24 + "9", // 25 + "D13", // 26 + "11", // 27 + "D14", // 28 + "13", // 29 + "D15", // 30 + "15", // 31 + "D16", // 32 + "1", // 33 + "D17", // 34 + "3", // 35 + "D18", // 36 + "5", // 37 + "D19", // 38 + "7", // 39 + "D20", // 40 + "9", // 41 + "10", // 42 + "11", // 43 + "12", // 44 + "13", // 45 + "14", // 46 + "15", // 47 + "16", // 48 + "17", // 49 + "18", // 50 + "19", // 51 + "20", // 52 + "13", // 53 + "14", // 54 + "15", // 55 + "16", // 56 + "17", // 57 + "18", // 58 + "19", // 59 + "20", // 60 + "BULL", // 61 + "T10", // 62 + "T13", // 63 + "T16", // 64 + "BULL", // 65 + "T14", // 66 + "T17", // 67 + "T12", // 68 + "T15", // 69 + "T18", // 70 + "T13", // 71 + "T16", // 72 + "T19", // 73 + "T14", // 74 + "T17", // 75 + "T16", // 76 + "T19", // 77 + "T18", // 78 + "T19", // 79 + "T20", // 80 + "T19", // 81 + "BULL", // 82 + "T17", // 83 + "T20", // 84 + "T15", // 85 + "T18", // 86 + "T17", // 87 + "T20", // 88 + "T19", // 89 + "T20", // 90 + "T17", // 91 + "T20", // 92 + "T19", // 93 + "T18", // 94 + "T19", // 95 + "T20", // 96 + "T19", // 97 + "T20", // 98 + "T19", // 99 + "T20", // 100 + "T19", // 101 + "T20", // 102 + "T19", // 103 + "T19", // 104 + "T20", // 105 + "T20", // 106 + "T19", // 107 + "T20", // 108 + "T20", // 109 + "T19", // 110 + "T19", // 111 + "T20", // 112 + "T19", // 113 + "T20", // 114 + "T19", // 115 + "T19", // 116 + "T20", // 117 + "T20", // 118 + "T19", // 119 + "T20", // 120 + "T20", // 121 + "T18", // 122 + "T19", // 123 + "T20", // 124 + "BULL", // 125 + "T19", // 126 + "T20", // 127 + "T20", // 128 + "T19", // 129 + "T20", // 130 + "T19", // 131 + "BULL", // 132 + "T14", // 133 + "T14", // 134 + "BULL", // 135 + "T20", // 136 + "T14", // 137 + "T20", // 138 + "T19", // 139 + "T15", // 140 + "T19", // 141 + "T20", // 142 + "T20", // 143 + "T20", // 144 + "T20", // 145 + "T19", // 146 + "T19", // 147 + "T20", // 148 + "T20", // 149 + "T20", // 150 + "T20", // 151 + "T20", // 152 + "T20", // 153 + "T19", // 154 + "T20", // 155 + "T20", // 156 + "T20", // 157 + "T20", // 158 + NULL, // 159 + "T20", // 160 + "T20", // 161 + NULL, // 162 + NULL, // 163 + "T19", // 164 + NULL, // 165 + NULL, // 166 + "T19", // 167 + NULL, // 168 + NULL, // 169 + "T20", // 170 + } +}; + +#endif diff --git a/checkouts.h b/checkouts.h index 230c264..5d0874e 100644 --- a/checkouts.h +++ b/checkouts.h @@ -3,523 +3,6 @@ #include <stddef.h> -char *CHECKOUTS[][170] = { - { - NULL, // 1 - "D1", // 2 - NULL, // 3 - "D2", // 4 - NULL, // 5 - "D3", // 6 - NULL, // 7 - "D4", // 8 - NULL, // 9 - "D5", // 10 - NULL, // 11 - "D6", // 12 - NULL, // 13 - "D7", // 14 - NULL, // 15 - "D8", // 16 - NULL, // 17 - "D9", // 18 - NULL, // 19 - "D10", // 20 - NULL, // 21 - "D11", // 22 - NULL, // 23 - "D12", // 24 - NULL, // 25 - "D13", // 26 - NULL, // 27 - "D14", // 28 - NULL, // 29 - "D15", // 30 - NULL, // 31 - "D16", // 32 - NULL, // 33 - "D17", // 34 - NULL, // 35 - "D18", // 36 - NULL, // 37 - "D19", // 38 - NULL, // 39 - "D20", // 40 - NULL, // 41 - NULL, // 42 - NULL, // 43 - NULL, // 44 - NULL, // 45 - NULL, // 46 - NULL, // 47 - NULL, // 48 - NULL, // 49 - "BULL", // 50 - NULL, // 51 - NULL, // 52 - NULL, // 53 - NULL, // 54 - NULL, // 55 - NULL, // 56 - NULL, // 57 - NULL, // 58 - NULL, // 59 - NULL, // 60 - NULL, // 61 - NULL, // 62 - NULL, // 63 - NULL, // 64 - NULL, // 65 - NULL, // 66 - NULL, // 67 - NULL, // 68 - NULL, // 69 - NULL, // 70 - NULL, // 71 - NULL, // 72 - NULL, // 73 - NULL, // 74 - NULL, // 75 - NULL, // 76 - NULL, // 77 - NULL, // 78 - NULL, // 79 - NULL, // 80 - NULL, // 81 - NULL, // 82 - NULL, // 83 - NULL, // 84 - NULL, // 85 - NULL, // 86 - NULL, // 87 - NULL, // 88 - NULL, // 89 - NULL, // 90 - NULL, // 91 - NULL, // 92 - NULL, // 93 - NULL, // 94 - NULL, // 95 - NULL, // 96 - NULL, // 97 - NULL, // 98 - NULL, // 99 - NULL, // 100 - NULL, // 101 - NULL, // 102 - NULL, // 103 - NULL, // 104 - NULL, // 105 - NULL, // 106 - NULL, // 107 - NULL, // 108 - NULL, // 109 - NULL, // 110 - NULL, // 111 - NULL, // 112 - NULL, // 113 - NULL, // 114 - NULL, // 115 - NULL, // 116 - NULL, // 117 - NULL, // 118 - NULL, // 119 - NULL, // 120 - NULL, // 121 - NULL, // 122 - NULL, // 123 - NULL, // 124 - NULL, // 125 - NULL, // 126 - NULL, // 127 - NULL, // 128 - NULL, // 129 - NULL, // 130 - NULL, // 131 - NULL, // 132 - NULL, // 133 - NULL, // 134 - NULL, // 135 - NULL, // 136 - NULL, // 137 - NULL, // 138 - NULL, // 139 - NULL, // 140 - NULL, // 141 - NULL, // 142 - NULL, // 143 - NULL, // 144 - NULL, // 145 - NULL, // 146 - NULL, // 147 - NULL, // 148 - NULL, // 149 - NULL, // 150 - NULL, // 151 - NULL, // 152 - NULL, // 153 - NULL, // 154 - NULL, // 155 - NULL, // 156 - NULL, // 157 - NULL, // 158 - NULL, // 159 - NULL, // 160 - NULL, // 161 - NULL, // 162 - NULL, // 163 - NULL, // 164 - NULL, // 165 - NULL, // 166 - NULL, // 167 - NULL, // 168 - NULL, // 169 - NULL, // 170 - }, - { - NULL, // 1 - "D1", // 2 - "1", // 3 - "D2", // 4 - "1", // 5 - "D3", // 6 - "3", // 7 - "D4", // 8 - "1", // 9 - "D5", // 10 - "3", // 11 - "D6", // 12 - "5", // 13 - "D7", // 14 - "7", // 15 - "D8", // 16 - "1", // 17 - "D9", // 18 - "3", // 19 - "D10", // 20 - "17", // 21 - "D11", // 22 - "7", // 23 - "D12", // 24 - "17", // 25 - "D13", // 26 - "3", // 27 - "D14", // 28 - "17", // 29 - "D15", // 30 - "7", // 31 - "D16", // 32 - "17", // 33 - "D17", // 34 - "3", // 35 - "D18", // 36 - "17", // 37 - "D19", // 38 - "7", // 39 - "D20", // 40 - "17", // 41 - "10", // 42 - "3", // 43 - "12", // 44 - "13", // 45 - "14", // 46 - "15", // 47 - "16", // 48 - "17", // 49 - "18", // 50 - "19", // 51 - "20", // 52 - "13", // 53 - "14", // 54 - "15", // 55 - "16", // 56 - "17", // 57 - "18", // 58 - "19", // 59 - "20", // 60 - "T11", // 61 - "T12", // 62 - "T13", // 63 - "T14", // 64 - "T15", // 65 - "T16", // 66 - "T17", // 67 - "T18", // 68 - "T19", // 69 - "T20", // 70 - "T19", // 71 - "T16", // 72 - "T19", // 73 - "T16", // 74 - "T17", // 75 - "T20", // 76 - "T19", // 77 - "T18", // 78 - "T19", // 79 - "T20", // 80 - "T19", // 81 - "T14", // 82 - "T17", // 83 - "T20", // 84 - "T15", // 85 - "T18", // 86 - "T17", // 87 - "T16", // 88 - "T19", // 89 - "T18", // 90 - "T17", // 91 - "T20", // 92 - "T19", // 93 - "T18", // 94 - "T19", // 95 - "T20", // 96 - "T19", // 97 - "T20", // 98 - NULL, // 99 - "T20", // 100 - "T17", // 101 - NULL, // 102 - NULL, // 103 - "T18", // 104 - NULL, // 105 - NULL, // 106 - "T19", // 107 - NULL, // 108 - NULL, // 109 - "T20", // 110 - NULL, // 111 - NULL, // 112 - NULL, // 113 - NULL, // 114 - NULL, // 115 - NULL, // 116 - NULL, // 117 - NULL, // 118 - NULL, // 119 - NULL, // 120 - NULL, // 121 - NULL, // 122 - NULL, // 123 - NULL, // 124 - NULL, // 125 - NULL, // 126 - NULL, // 127 - NULL, // 128 - NULL, // 129 - NULL, // 130 - NULL, // 131 - NULL, // 132 - NULL, // 133 - NULL, // 134 - NULL, // 135 - NULL, // 136 - NULL, // 137 - NULL, // 138 - NULL, // 139 - NULL, // 140 - NULL, // 141 - NULL, // 142 - NULL, // 143 - NULL, // 144 - NULL, // 145 - NULL, // 146 - NULL, // 147 - NULL, // 148 - NULL, // 149 - NULL, // 150 - NULL, // 151 - NULL, // 152 - NULL, // 153 - NULL, // 154 - NULL, // 155 - NULL, // 156 - NULL, // 157 - NULL, // 158 - NULL, // 159 - NULL, // 160 - NULL, // 161 - NULL, // 162 - NULL, // 163 - NULL, // 164 - NULL, // 165 - NULL, // 166 - NULL, // 167 - NULL, // 168 - NULL, // 169 - NULL, // 170 - }, - { - NULL, // 1 - "D1", // 2 - "1", // 3 - "D2", // 4 - "1", // 5 - "D3", // 6 - "3", // 7 - "D4", // 8 - "1", // 9 - "D5", // 10 - "3", // 11 - "D6", // 12 - "5", // 13 - "D7", // 14 - "7", // 15 - "D8", // 16 - "1", // 17 - "D9", // 18 - "3", // 19 - "D10", // 20 - "5", // 21 - "D11", // 22 - "7", // 23 - "D12", // 24 - "9", // 25 - "D13", // 26 - "11", // 27 - "D14", // 28 - "13", // 29 - "D15", // 30 - "15", // 31 - "D16", // 32 - "1", // 33 - "D17", // 34 - "3", // 35 - "D18", // 36 - "5", // 37 - "D19", // 38 - "7", // 39 - "D20", // 40 - "9", // 41 - "10", // 42 - "11", // 43 - "12", // 44 - "13", // 45 - "14", // 46 - "15", // 47 - "16", // 48 - "17", // 49 - "18", // 50 - "19", // 51 - "20", // 52 - "13", // 53 - "14", // 54 - "15", // 55 - "16", // 56 - "17", // 57 - "18", // 58 - "19", // 59 - "20", // 60 - "BULL", // 61 - "T10", // 62 - "T13", // 63 - "T16", // 64 - "BULL", // 65 - "T14", // 66 - "T17", // 67 - "T12", // 68 - "T15", // 69 - "T18", // 70 - "T13", // 71 - "T16", // 72 - "T19", // 73 - "T14", // 74 - "T17", // 75 - "T16", // 76 - "T19", // 77 - "T18", // 78 - "T19", // 79 - "T20", // 80 - "T19", // 81 - "BULL", // 82 - "T17", // 83 - "T20", // 84 - "T15", // 85 - "T18", // 86 - "T17", // 87 - "T20", // 88 - "T19", // 89 - "T20", // 90 - "T17", // 91 - "T20", // 92 - "T19", // 93 - "T18", // 94 - "T19", // 95 - "T20", // 96 - "T19", // 97 - "T20", // 98 - "T19", // 99 - "T20", // 100 - "T19", // 101 - "T20", // 102 - "T19", // 103 - "T19", // 104 - "T20", // 105 - "T20", // 106 - "T19", // 107 - "T20", // 108 - "T20", // 109 - "T19", // 110 - "T19", // 111 - "T20", // 112 - "T19", // 113 - "T20", // 114 - "T19", // 115 - "T19", // 116 - "T20", // 117 - "T20", // 118 - "T19", // 119 - "T20", // 120 - "T20", // 121 - "T18", // 122 - "T19", // 123 - "T20", // 124 - "BULL", // 125 - "T19", // 126 - "T20", // 127 - "T20", // 128 - "T19", // 129 - "T20", // 130 - "T19", // 131 - "BULL", // 132 - "T14", // 133 - "T14", // 134 - "BULL", // 135 - "T20", // 136 - "T14", // 137 - "T20", // 138 - "T19", // 139 - "T15", // 140 - "T19", // 141 - "T20", // 142 - "T20", // 143 - "T20", // 144 - "T20", // 145 - "T19", // 146 - "T19", // 147 - "T20", // 148 - "T20", // 149 - "T20", // 150 - "T20", // 151 - "T20", // 152 - "T20", // 153 - "T19", // 154 - "T20", // 155 - "T20", // 156 - "T20", // 157 - "T20", // 158 - NULL, // 159 - "T20", // 160 - "T20", // 161 - NULL, // 162 - NULL, // 163 - "T19", // 164 - NULL, // 165 - NULL, // 166 - "T19", // 167 - NULL, // 168 - NULL, // 169 - "T20", // 170 - } -}; +extern char *CHECKOUTS[3][170]; #endif @@ -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; +} @@ -0,0 +1,8 @@ +#ifndef COMP_H +#define COMP_H + +#include "match.h" + +void comp_visit(struct leg *l); + +#endif diff --git a/curses.c b/curses.c new file mode 100644 index 0000000..4169906 --- /dev/null +++ b/curses.c @@ -0,0 +1,144 @@ +#include "curses.h" +#include "match.h" + +#include <ncurses.h> +#include <stdlib.h> + +WINDOW *w, *titlew, *statw, *promptw; + +void init_curses() +{ + initscr(); + refresh(); + start_color(); + init_colours(); + curs_set(0); + noecho(); + + w = newwin(LINES-3, COLS, 1, 0); + titlew = newwin(1, COLS, 0, 0); + statw = newwin(1, COLS, LINES-2, 0); + promptw = newwin(1, COLS, LINES-1, 0); + wbkgd(titlew, COLOR_PAIR(C_STATUS)); + wbkgd(statw, COLOR_PAIR(C_STATUS)); + waddstr(titlew, " dartbot"); + wrefresh(titlew); +} + +void free_curses() +{ + delwin(promptw); + delwin(statw); + delwin(titlew); + delwin(w); + endwin(); +} + +void init_colours() +{ + FOREACH_COLOUR(GEN_COLOUR_INIT_PAIR) +} + +void curses_status(char *status) +{ + wmove(statw, 0, 0); + wclrtoeol(statw); + waddstr(statw, status); + wrefresh(statw); +} + +void curses_prompt(char *prompt) +{ + wmove(promptw, 0, 0); + wclrtoeol(promptw); + waddstr(promptw, prompt); + wrefresh(promptw); +} + +void flushbuf(char *buf, int *buflen, int col) +{ + if (!(*buflen)) return; + + if (col) wattron(w, col); + waddstr(w, buf); + if (col) wattroff(w, col); + + *buflen = 0; +} + +int points_colour(int points) +{ + if (points >= 180) + return COLOR_PAIR(C_140) | A_BOLD; + else if (points >= 140) + return COLOR_PAIR(C_140); + else if (points >= 100) + return COLOR_PAIR(C_100); + else if (points >= 60) + return COLOR_PAIR(C_60); + else if (points >= 40) + return COLOR_PAIR(C_40); + else if (points >= 20) + return COLOR_PAIR(C_20); + else if (points > 0) + return COLOR_PAIR(C_0); + else + return COLOR_PAIR(C_0) | A_BOLD; +} + +void curses_draw(struct leg *l1, struct leg *l2) +{ + werase(w); + + char buf[100]; + int buflen = 0; + + int wlines = LINES - 3; + int n_visits = l1->n_visits > l2->n_visits ? l1->n_visits : l2->n_visits; + int start_visit = (wlines > n_visits) ? 0 : (n_visits - wlines); + int offset = 0; + + if (start_visit == 0 && wlines > n_visits) { + wmove(w, (offset++)-start_visit, 1); + buflen = sprintf(buf, "(%2d)", 0); + flushbuf(buf, &buflen, COLOR_PAIR(C_VISIT)); + buflen = sprintf(buf, " %3d %3d", l1->start, l2->start); + flushbuf(buf, &buflen, 0); + } + + for (int i = start_visit; i < n_visits; ++i) { + wmove(w, offset+i-start_visit, 1); + buflen += sprintf(buf + buflen, "(%2d)", i+1); + flushbuf(buf, &buflen, COLOR_PAIR(C_VISIT)); + buflen += sprintf(buf + buflen, " "); + flushbuf(buf, &buflen, 0); + + struct visit *v = l1->visits + i; + + flushbuf(buf, &buflen, 0); + buflen += sprintf(buf + buflen, "%3d", v->points); + flushbuf(buf, &buflen, points_colour(v->points)); + + buflen += sprintf(buf + buflen, " %3d", v->rem); + + if (i < l2->n_visits) { + v = l2->visits + i; + + buflen += sprintf(buf + buflen, " %3d ", v->rem); + + flushbuf(buf, &buflen, 0); + buflen += sprintf(buf + buflen, "%3d", v->points); + flushbuf(buf, &buflen, points_colour(v->points)); + + for (int j = 0; j < v->n_darts; ++j) { + char *n = segment_name(v->darts[j]); + buflen += sprintf(buf + buflen, j == 0 ? " %4s" :" %4s", n); + free(n); + } + flushbuf(buf, &buflen, COLOR_PAIR(C_DARTS)); + } + + flushbuf(buf, &buflen, 0); + } + wrefresh(w); +} diff --git a/curses.h b/curses.h new file mode 100644 index 0000000..4a34a16 --- /dev/null +++ b/curses.h @@ -0,0 +1,40 @@ +#ifndef CURSES_H +#define CURSES_H + +#include "match.h" + +#include <ncurses.h> + +extern WINDOW *w, *titlew, *statw, *promptw; + +#define FOREACH_COLOUR(M) \ + M(140, 82, 0) \ + M(100, 154, 0) \ + M(60, 226, 0) \ + M(40, 214, 0) \ + M(20, 202, 0) \ + M(0, 196, 0) \ + M(DARTS, 235, 0) \ + M(VISIT, 244, 0) \ + M(STATUS, 7, 4) +#define GEN_COLOUR_ENUM(X, FG, BG) C_ ## X, +#define GEN_COLOUR_INIT_PAIR(X, FG, BG) init_pair(C_ ## X, FG, BG); + +enum colour { + C_DEFAULT, // index 0 is reserved for default colours + FOREACH_COLOUR(GEN_COLOUR_ENUM) +}; + +void init_curses(); +void free_curses(); +void init_colours(); + +void curses_status(char *status); +void curses_prompt(char *prompt); + +void flushbuf(char *buf, int *buflen, int col); +int points_colour(int points); + +void curses_draw(struct leg *l1, struct leg *l2); + +#endif @@ -1,338 +1,13 @@ +#include "board.h" #include "checkouts.h" +#include "comp.h" +#include "curses.h" +#include "match.h" -#include <math.h> #include <ncurses.h> -#include <stdbool.h> +#include <stdio.h> #include <stdlib.h> -#include <string.h> #include <time.h> -#include <unistd.h> - -#define HORIZONTAL_STDEV 24 -#define VERTICAL_STDEV 24 - -// board spec from WDF rules -#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 SEGMENT_MAX_LEN 5 -// distance from centre to apex of outer wire -// must be ordered outwards from centre -#define FOREACH_RING(M) \ - M(BULL, INNER_DIAMETER_BULL/2 + WIRE_WIDTH/2) \ - M(25, INNER_DIAMETER_25/2 + WIRE_WIDTH/2) \ - M(SMALL, TREBLE_OUTER_EDGE - WIRE_WIDTH - TREBLE_INSIDE_WIDTH - \ - WIRE_WIDTH/2) \ - M(TREBLE, TREBLE_OUTER_EDGE - WIRE_WIDTH/2) \ - M(BIG, DOUBLE_OUTER_EDGE - WIRE_WIDTH - DOUBLE_INSIDE_WIDTH - \ - WIRE_WIDTH/2) \ - M(DOUBLE, DOUBLE_OUTER_EDGE - WIRE_WIDTH/2) -#define GEN_RING_ENUM(X, D) R_ ## X, -#define GEN_RING_STRING(X, D) #X, -#define GEN_RING_OUTER_DIST(X, D) D, - -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)); -} - -int SECTORS[] = { 20, 1, 18, 4, 13, 6, 10, 15, 2, 17, 3, 19, 7, - 16, 8, 11, 14, 9, 12, 5 }; -#define NUM_SECTORS (sizeof(SECTORS) / sizeof(*SECTORS)) -#define SECTOR_WIDTH (360.0 / NUM_SECTORS) -int SECTOR_INDS[NUM_SECTORS]; -double SECTOR_ANGLES[NUM_SECTORS]; -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; - } -} - -#define FOREACH_COLOUR(M) \ - M(140, 82, 0) \ - M(100, 154, 0) \ - M(60, 226, 0) \ - M(40, 214, 0) \ - M(20, 202, 0) \ - M(0, 196, 0) \ - M(DARTS, 235, 0) \ - M(VISIT, 244, 0) \ - M(STATUS, 7, 4) -#define GEN_COLOUR_ENUM(X, FG, BG) C_ ## X, -#define GEN_COLOUR_INIT_PAIR(X, FG, BG) init_pair(C_ ## X, FG, BG); - -enum colour { - C_DEFAULT, // index 0 is reserved for default colours - FOREACH_COLOUR(GEN_COLOUR_ENUM) -}; - -void init_colours() -{ - FOREACH_COLOUR(GEN_COLOUR_INIT_PAIR) -} - -WINDOW *w, *titlew, *statw, *promptw; - -struct ccoords { - double x, y; -}; - -struct pcoords { - double a, r; -}; - -struct segment { - enum ring ring; - int sector; -}; - -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; -} - -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 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 }; -} - -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); -} - -struct visit { - int points; - int rem; - int n_darts; - struct segment *darts; -}; - -struct leg { - char *name; - int start; - int rem; - int n_visits; - struct visit *visits; -}; - -struct leg *leg_init(int points, char *name) -{ - struct leg *l = calloc(1, sizeof(*l)); - l->name = name; - l->start = l->rem = points; - l->visits = calloc(1000, sizeof(*(l->visits))); // FIXME - - return l; -} - -void leg_free(struct leg *l) -{ - for (int i = 0; i < l->n_visits; ++i) - if (l->visits[i].darts) - free(l->visits[i].darts); - free(l->visits); - free(l); -} - -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; -} void test_match(int start_points) { @@ -357,22 +32,6 @@ void test_match(int start_points) leg_free(l); } -void curses_status(char *status) -{ - wmove(statw, 0, 0); - wclrtoeol(statw); - waddstr(statw, status); - wrefresh(statw); -} - -void curses_prompt(char *prompt) -{ - wmove(promptw, 0, 0); - wclrtoeol(promptw); - waddstr(promptw, prompt); - wrefresh(promptw); -} - void user_visit(struct leg *l) { struct visit *v = l->visits + l->n_visits++; @@ -425,113 +84,10 @@ void user_visit(struct leg *l) v->rem = l->rem; } -int points_colour(int points) -{ - if (points >= 180) - return COLOR_PAIR(C_140) | A_BOLD; - else if (points >= 140) - return COLOR_PAIR(C_140); - else if (points >= 100) - return COLOR_PAIR(C_100); - else if (points >= 60) - return COLOR_PAIR(C_60); - else if (points >= 40) - return COLOR_PAIR(C_40); - else if (points >= 20) - return COLOR_PAIR(C_20); - else if (points > 0) - return COLOR_PAIR(C_0); - else - return COLOR_PAIR(C_0) | A_BOLD; -} - -void flushbuf(char *buf, int *buflen, int col) -{ - if (!(*buflen)) return; - - if (col) wattron(w, col); - waddstr(w, buf); - if (col) wattroff(w, col); - - *buflen = 0; -} - -void curses_draw(struct leg *l1, struct leg *l2) -{ - werase(w); - - char buf[100]; - int buflen = 0; - - int wlines = LINES - 3; - int n_visits = l1->n_visits > l2->n_visits ? l1->n_visits : l2->n_visits; - int start_visit = (wlines > n_visits) ? 0 : (n_visits - wlines); - int offset = 0; - - if (start_visit == 0 && wlines > n_visits) { - wmove(w, (offset++)-start_visit, 1); - buflen = sprintf(buf, "(%2d)", 0); - flushbuf(buf, &buflen, COLOR_PAIR(C_VISIT)); - buflen = sprintf(buf, " %3d %3d", l1->start, l2->start); - flushbuf(buf, &buflen, 0); - } - - for (int i = start_visit; i < n_visits; ++i) { - wmove(w, offset+i-start_visit, 1); - buflen += sprintf(buf + buflen, "(%2d)", i+1); - flushbuf(buf, &buflen, COLOR_PAIR(C_VISIT)); - buflen += sprintf(buf + buflen, " "); - flushbuf(buf, &buflen, 0); - - struct visit *v = l1->visits + i; - - flushbuf(buf, &buflen, 0); - buflen += sprintf(buf + buflen, "%3d", v->points); - flushbuf(buf, &buflen, points_colour(v->points)); - - buflen += sprintf(buf + buflen, " %3d", v->rem); - - if (i < l2->n_visits) { - v = l2->visits + i; - - buflen += sprintf(buf + buflen, " %3d ", v->rem); - - flushbuf(buf, &buflen, 0); - buflen += sprintf(buf + buflen, "%3d", v->points); - flushbuf(buf, &buflen, points_colour(v->points)); - - for (int j = 0; j < v->n_darts; ++j) { - char *n = segment_name(v->darts[j]); - buflen += sprintf(buf + buflen, j == 0 ? " %4s" :" %4s", n); - free(n); - } - flushbuf(buf, &buflen, COLOR_PAIR(C_DARTS)); - } - - flushbuf(buf, &buflen, 0); - } - - wrefresh(w); -} - void curses_match(int start_points, char *n1, void (*f1)(struct leg *), char *n2, void (*f2)(struct leg *)) { - initscr(); - refresh(); - start_color(); - init_colours(); - curs_set(0); - noecho(); - - w = newwin(LINES-3, COLS, 1, 0); - titlew = newwin(1, COLS, 0, 0); - statw = newwin(1, COLS, LINES-2, 0); - promptw = newwin(1, COLS, LINES-1, 0); - wbkgd(titlew, COLOR_PAIR(C_STATUS)); - wbkgd(statw, COLOR_PAIR(C_STATUS)); - waddstr(titlew, " dartbot"); - wrefresh(titlew); + init_curses(); struct leg *l1 = leg_init(start_points, n1); struct leg *l2 = leg_init(start_points, n2); @@ -555,11 +111,7 @@ void curses_match(int start_points, char *n1, void (*f1)(struct leg *), leg_free(l1); leg_free(l2); wgetch(w); - delwin(promptw); - delwin(statw); - delwin(titlew); - delwin(w); - endwin(); + free_curses(); } void cvc_curses_match(int start_points) @@ -580,8 +132,7 @@ void pvp_curses_match(int start_points) int main() { srand(time(NULL)); - init_sectors(); - init_centre_dists(); + init_board(); //cvc_curses_match(501); pvc_curses_match(501); @@ -0,0 +1,22 @@ +#include "match.h" + +#include <stdlib.h> + +struct leg *leg_init(int points, char *name) +{ + struct leg *l = calloc(1, sizeof(*l)); + l->name = name; + l->start = l->rem = points; + l->visits = calloc(1000, sizeof(*(l->visits))); // FIXME + + return l; +} + +void leg_free(struct leg *l) +{ + for (int i = 0; i < l->n_visits; ++i) + if (l->visits[i].darts) + free(l->visits[i].darts); + free(l->visits); + free(l); +} @@ -0,0 +1,24 @@ +#ifndef MATCH_H +#define MATCH_H + +#include "board.h" + +struct visit { + int points; + int rem; + int n_darts; + struct segment *darts; +}; + +struct leg { + char *name; + int start; + int rem; + int n_visits; + struct visit *visits; +}; + +struct leg *leg_init(int points, char *name); +void leg_free(struct leg *l); + +#endif |