1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
#include "board.h"
#include "checkouts.h"
#include "comp.h"
#include "match.h"
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
double horizontal_stdev = 16, vertical_stdev = 16;
#define NUM_DIFF_PRESETS (sizeof(DIFF_PRESETS) / sizeof(*DIFF_PRESETS))
static struct { int diff; double stdev; } DIFF_PRESETS[] = {
{ 0, 66.80}, // 10
{ 8, 40.24}, // 20
{16, 28.14}, // 30
{24, 21.35}, // 40
{32, 17.20}, // 50
{40, 14.34}, // 60
{48, 12.15}, // 70
{56, 10.36}, // 80
{64, 8.83}, // 90
{72, 7.48}, // 100
{80, 6.32}, // 110
{88, 5.34}, // 120
{99, 0.00}, // 167
};
// optional function to set stdevs using precomputed 0-99 difficulty values.
// fixed-step interpolation is done between presets.
void comp_set_difficulty(int diff)
{
if (diff < DIFF_PRESETS[0].diff)
diff = DIFF_PRESETS[0].diff;
else if (diff > DIFF_PRESETS[NUM_DIFF_PRESETS - 1].diff)
diff = DIFF_PRESETS[NUM_DIFF_PRESETS - 1].diff;
size_t ind = 1;
while (ind < NUM_DIFF_PRESETS - 1 && DIFF_PRESETS[ind].diff <= diff)
ind++;
double step = (DIFF_PRESETS[ind - 1].stdev - DIFF_PRESETS[ind].stdev) /
(DIFF_PRESETS[ind].diff - DIFF_PRESETS[ind - 1].diff);
horizontal_stdev = vertical_stdev = DIFF_PRESETS[ind - 1].stdev -
((diff - DIFF_PRESETS[ind - 1].diff) * step);
}
static double drand()
{
return (double)rand() / RAND_MAX;
}
static 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);
}
static struct ccoords gauss_offset()
{
return (struct ccoords){ .x = gauss(0, horizontal_stdev),
.y = gauss(0, vertical_stdev) };
}
static struct pcoords throw_dart(struct pcoords target, struct ccoords *cc)
{
struct ccoords tc = pol_to_cart(target);
struct ccoords offset = gauss_offset();
cc->x = tc.x + offset.x;
cc->y = tc.y + offset.y;
return cart_to_pol(*cc);
}
static struct segment next_dart(int rem, int darts_in_hand)
{
char *c = NULL;
if (rem <= NUM_CHECKOUTS)
c = CHECKOUTS[darts_in_hand - 1][rem - 1];
if (!c && rem <= NUM_SETUP_SHOTS)
c = SETUP_SHOTS[rem - 1];
if (!c)
c = "T20";
return segment_from_name(c);
}
void comp_visit(struct leg *l)
{
struct visit *v = leg_visit(l);
v->darts = calloc(3, sizeof(*v->darts));
v->ccoords = calloc(3, sizeof(*v->ccoords));
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 ccoords dcart;
struct pcoords dc = throw_dart(tc, &dcart);
struct segment ds = segment_from_pcoords(dc);
v->ccoords[v->n_darts] = dcart;
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;
}
|