summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dartbot.c182
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;
+}