summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--board.c140
-rw-r--r--board.h57
-rw-r--r--checkouts.c525
-rw-r--r--checkouts.h519
-rw-r--r--comp.c106
-rw-r--r--comp.h8
-rw-r--r--curses.c144
-rw-r--r--curses.h40
-rw-r--r--dartbot.c465
-rw-r--r--match.c22
-rw-r--r--match.h24
12 files changed, 1080 insertions, 976 deletions
diff --git a/Makefile b/Makefile
index b4dcc2c..83ec0a8 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/board.c b/board.c
new file mode 100644
index 0000000..1a543ee
--- /dev/null
+++ b/board.c
@@ -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 };
+}
diff --git a/board.h b/board.h
new file mode 100644
index 0000000..c7fb477
--- /dev/null
+++ b/board.h
@@ -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
diff --git a/comp.c b/comp.c
new file mode 100644
index 0000000..f1adb75
--- /dev/null
+++ b/comp.c
@@ -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;
+}
diff --git a/comp.h b/comp.h
new file mode 100644
index 0000000..c7bc830
--- /dev/null
+++ b/comp.h
@@ -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
diff --git a/dartbot.c b/dartbot.c
index abd6045..314548f 100644
--- a/dartbot.c
+++ b/dartbot.c
@@ -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);
diff --git a/match.c b/match.c
new file mode 100644
index 0000000..17ce3b1
--- /dev/null
+++ b/match.c
@@ -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);
+}
diff --git a/match.h b/match.h
new file mode 100644
index 0000000..0b44b45
--- /dev/null
+++ b/match.h
@@ -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