-
Notifications
You must be signed in to change notification settings - Fork 0
/
eval.c
146 lines (139 loc) · 4.69 KB
/
eval.c
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
typedef double (*eval_fun)(void *s);
double eval_zero(void *s) {
return 0;
}
double eval_random(void *s) {
state *c = malloc(sizeof(state));
int total_score = 0;
for (int i = 0; i < 20; ++i) {
memcpy(c, s, sizeof(state));
for (int j = 0; j < 25; ++j) {
if(!apply_deal_and_choice(c, rand_piece(), CHOICES[jrand() % NUM_CHOICES])) {
break;
}
total_score += resolve(c, NULL);
}
}
free(c);
return total_score * 0.05;
}
double eval_weighted(void *s) {
state *c;
double total_score = 0;
double total_weight = 0;
for (int i = 0; i < 10; ++i) {
c = copy_state(s);
for (int j = 0; j < 25; ++j) {
if(!apply_deal_and_choice(c, rand_piece(), CHOICES[jrand() % NUM_CHOICES])) {
break;
}
double score = resolve(c, NULL);
int num_remaining = 0;
for (int j = 0; j < NUM_FLOORS; ++j) {
for (int i = 0; i < NUM_COLORS; ++i) {
num_remaining += popcount(c->floors[j][i]);
}
}
score += 1.5 * exp(-0.3 * num_remaining);
double weight = exp(-state_euler(c));
total_weight += weight;
total_score += score * weight;
}
free(c);
}
return total_score / total_weight;
}
// groups and chains inspired by https://github.com/mbrown1413/Puyo-AI
double eval_groups(void *_s) {
state *s = _s;
puyos_t groups[2*MAX_GROUPS];
double score = 0;
for (int i = 0; i < NUM_COLORS - 1; ++i) {
puyos_t puyos[2] = {s->floors[0][i], s->floors[1][i]};
int num = num_groups_2(puyos, groups);
for (int j = 0; j < num; ++j) {
int size = popcount(groups[2*j]) + popcount(groups[2*j + 1]);
score += size*size;
}
}
return score;
}
double eval_chains(void *_s) {
state *s = _s;
int original_pc = state_popcount(s);
puyos_t all[2];
get_state_mask(s, all);
double score = 0;
state *c = malloc(sizeof(state));
for (int i = 0; i < NUM_COLORS - 1; ++i) {
puyos_t handled[2] = {0};
for (int j = 0; j < WIDTH; ++j) {
// Resolution is expensive so we try to short-circuit.
// We also filter out chains that we checked previously.
// There are some corner cases where the filtering is overaggressive, but they are ignored for now.
int depth = depth_2(all, j);
puyos_t p[2];
point_2(p, j, depth - 1);
puyos_t target[2] = {
(s->floors[0][i] & LIFE_BLOCK) | p[0],
s->floors[1][i] | p [1]
};
flood_2(p, target);
if (popcount_2(p) < CLEAR_THRESHOLD) {
continue;
} else if ((p[0] & handled[0]) || (p[1] & handled[1])) {
continue;
} else {
handled[0] |= p[0];
handled[1] |= p[1];
}
// Do the actual thing.
memcpy(c, s, sizeof(state));
c->floors[0][i] |= 1ULL << j;
int chain;
resolve(c, &chain);
if (chain > 1) {
double pc = state_popcount(c);
double count = original_pc + 1 - pc;
score += chain * chain * chain / count;
}
}
}
free(c);
return score;
}
// XXX: Needs more work
double eval_groups_plus(void *_s) {
state *s = _s;
puyos_t groups[2*MAX_GROUPS];
double score = 0;
for (int i = 0; i < NUM_COLORS - 1; ++i) {
puyos_t puyos[2] = {s->floors[0][i], s->floors[1][i]};
int num = num_groups_2(puyos, groups);
puyos_t threes[2] = {0, 0};
for (int j = 0; j < num; ++j) {
int size = popcount(groups[2*j]) + popcount(groups[2*j + 1]);
if (size == 3) {
threes[0] |= groups[2*j];
threes[1] |= groups[2*j + 1];
}
}
for (int j = 0; j < num; ++j) {
int size = popcount(groups[2*j]) + popcount(groups[2*j + 1]);
score += pow(size, 2.5);
if (size == 1) {
puyos_t group_l[2] = {groups[2*j], groups[2*j + 1]};
down_2(group_l);
puyos_t group_r[2] = {group_l[0], group_l[1]};
left_2(group_l);
right_2(group_r);
int left_connects = (threes[0] & group_l[0]) || (threes[1] & group_l[1]);
int right_connects = (threes[0] & group_r[0]) || (threes[1] & group_r[1]);
if (left_connects ^ right_connects) {
score += 0.77;
}
}
}
}
return score;
}