-
Notifications
You must be signed in to change notification settings - Fork 0
/
bottom.c
153 lines (144 loc) · 4.2 KB
/
bottom.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
147
148
149
150
151
152
153
#define MAX_BOTTOM_CHAIN ((WIDTH * HEIGHT) / CLEAR_THRESHOLD)
char color_label(int color) {
int c = '0' + color;
if (c > '9') {
c = c - '9' + 'a' - 1;
}
if (c > 'z') {
c = c - 'z' + 'A' - 1;
}
return c;
}
void print_bottom_spam(puyos_t *floor, int num_links, int num_colors) {
printf(" ");
for (int i = 0; i < WIDTH; ++i) {
printf(" %c", 'A' + i);
}
printf("\n");
for (int i = 0; i < HEIGHT * WIDTH; ++i) {
if (i % V_SHIFT == 0) {
printf("%d", i / V_SHIFT);
}
puyos_t p = (1ULL << i);
int any = 0;
for (int k = 0; k < num_colors; ++k) {
if (p & floor[k]) {
printf("\x1b[3%d;1m", k % 6 + 1);
if (k < num_links) {
printf(" %c", color_label(k));
} else {
printf(" @");
}
any = 1;
break;
}
}
printf("\x1b[0m");
if (!any) {
printf(" ");
}
if (i % V_SHIFT == V_SHIFT - 1) {
printf("\n");
}
}
}
void print_bottom(puyos_t *floor, int num_colors) {
print_bottom_spam(floor, num_colors, num_colors);
}
int handle_bottom_gravity(puyos_t *floor, int num_colors) {
puyos_t all;
all = 0;
for (int j = 0; j < num_colors; ++j) {
all |= floor[j];
}
int iterations = 0;
puyos_t temp;
do {
temp = all;
puyos_t bellow, falling;
bellow = (all >> V_SHIFT) | BOTTOM;
all = 0;
for (int i = 0; i < num_colors; ++i) {
falling = floor[i] & ~bellow;
floor[i] = (falling << V_SHIFT) | (floor[i] & bellow);
all |= floor[i];
}
++iterations;
} while (temp != all);
return iterations;
}
int clear_bottom_groups(puyos_t *floor, int num_colors, int *color_cleared) {
int num_cleared = 0;
for (int i = 0; i < num_colors; ++i) {
puyos_t bottom = floor[i];
for (int j = WIDTH * HEIGHT - 2; j >= 0; j -= 2) {
puyos_t bottom_group = 3ULL << j;
bottom_group = flood(bottom_group, bottom);
bottom ^= bottom_group;
int group_size = popcount(bottom_group);
if (group_size >= CLEAR_THRESHOLD) {
floor[i] ^= bottom_group;
num_cleared += group_size;
*color_cleared = i;
}
if (!bottom) {
break;
}
}
}
return num_cleared;
}
int resolve_bottom(puyos_t *floor, int num_colors, int *color_order) {
int chain = -1;
while(1) {
++chain;
int iterations = handle_bottom_gravity(floor, num_colors);
if (iterations == 1 && chain > 0) {
break;
}
int color_cleared;
if (!clear_bottom_groups(floor, num_colors, &color_cleared)) {
break;
}
if (color_order) {
color_order[chain] = color_cleared;
}
}
return chain;
}
char* color_conflicts(puyos_t *floor, int num_colors) {
char *conflicts = malloc(num_colors * num_colors * sizeof(char));
puyos_t *temp = malloc(num_colors * sizeof(puyos_t));
memcpy(temp, floor, num_colors * sizeof(puyos_t));
int chain = resolve_bottom(temp, num_colors, NULL);
for (int i = 0; i < num_colors; ++i) {
for (int j = 0; j < num_colors; ++j) {
memcpy(temp, floor, num_colors * sizeof(puyos_t));
temp[i] |= temp[j];
if (i != j) {
temp[j] = 0;
}
int new_chain = resolve_bottom(temp, num_colors, NULL);
conflicts[i + num_colors * j] = (new_chain != chain);
}
}
return conflicts;
}
void print_conflicts(char* conflicts, int num_colors) {
printf(" ");
for (int i = 0; i < num_colors; ++i) {
printf(" %c", color_label(i));
}
printf("\n");
for (int i = 0; i < num_colors; ++i) {
printf("%c", color_label(i));
for (int j = 0; j < num_colors; ++j) {
if (conflicts[i + j * num_colors]) {
printf(" @");
} else {
printf(" ");
}
}
printf("\n");
}
}