-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcalisson_grid.cpp
197 lines (167 loc) · 5.26 KB
/
calisson_grid.cpp
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#include "calisson_grid.hpp"
#include <cassert>
#include "grid.hpp"
#include "helper.hpp"
#include "weighted_grid.hpp"
using namespace Calissons;
Grid::Grid(int size) : size_(size), grid_(12 * size * size, Ext) {}
Grid::Grid(const Dominos::Grid &g)
: Grid(Dominos::hex_size_from_wg_size(g.size())) {
init_empty();
for (int y = 0; y < size_; y++) {
for (int x = 0; x < y + size_; x++) {
const int gx = size_ - y + 2 * x - 1;
const int gy = g.size() - size_ + y;
const int ci = 1 + y;
const int cj = size_ - y + x;
if (g.cell(gx, gy) == Dominos::HL) set_edge({ci - 1, cj, 0}, Losange);
if (g.cell(gx, gy) == Dominos::VT) set_edge({ci, cj - 1, 1}, Losange);
if (g.cell(gx + 1, gy) == Dominos::HL) set_edge({ci - 1, cj, 2}, Losange);
const int gx2 = size_ - y + 2 * x - 1;
const int gy2 = g.size() + size_ - y - 2;
const int ci2 = 2 * size_ - 1 - y;
const int cj2 = 1 + x;
if (g.cell(gx2, gy2 + 1) == Dominos::HL)
set_edge({ci2, cj2 - 1, 2}, Losange);
if (g.cell(gx2 + 1, gy2 + 1) == Dominos::HL)
set_edge({ci2, cj2, 0}, Losange);
if (g.cell(gx2 + 2, gy2) == Dominos::VT) set_edge({ci2, cj2, 1}, Losange);
}
// On the end
const int gx = 3 * size_ + y - 1;
const int gy = g.size() - size_ + y;
if (g.cell(gx, gy) == Dominos::VT)
set_edge({1 + y, 2 * size_ - 1, 1}, Losange);
const int gx2 = size_ - y - 1;
const int gy2 = g.size() + size_ - y - 2;
if (g.cell(gx2, gy2) == Dominos::VT)
set_edge({2 * size_ - 1 - y, 0, 1}, Losange);
}
}
void Grid::init_empty() {
for (int i = 0; i < 2 * size_; i++) {
const int str = start_j(i);
const int end = end_j(i);
for (int j = str; j < end; j++) {
if (j > str || i < size_) set_edge({i, j, 0}, None);
if (i > 0) set_edge({i, j, 1}, None);
if (j < end - 1 || i < size_) set_edge({i, j, 2}, None);
}
}
}
void Grid::segmentify_seg(const Coord &c) {
const EdgesNei nei = get_edg_nei(c);
if ((is_edg_inside(nei.e[0]) && is_edg_inside(nei.e[2]) &&
edge(nei.e[0]) == Losange && edge(nei.e[2]) == Losange) ||
(is_edg_inside(nei.e[1]) && is_edg_inside(nei.e[3]) &&
edge(nei.e[1]) == Losange && edge(nei.e[3]) == Losange)) {
set_edge(c, Edge);
}
}
void Grid::segmentify() {
for (int i = 0; i < 2 * size_; i++) {
const int str = start_j(i);
const int end = end_j(i);
for (int j = str; j < end; j++) {
if (j > str || i < size_) segmentify_seg({i, j, 0});
if (i > 0) segmentify_seg({i, j, 1});
if (j < end - 1 || i < size_) segmentify_seg({i, j, 2});
}
}
}
int Grid::start_j(int i) const {
if (i > size_) return 0;
return size_ - i;
}
int Grid::end_j(int i) const {
if (i > size_) return 3 * size_ - i;
return 2 * size_;
}
bool Grid::is_edg_inside(const Coord &c) const {
const int str = start_j(c.i);
const int end = end_j(c.i);
return 0 <= c.i && c.i < 2 * size_ && str <= c.j && c.j < end &&
((c.d == 0 && (c.j > str || c.i < size_)) || (c.d == 1 && c.i > 0) ||
(c.d == 2 && (c.j < end - 1 || c.i < size_)));
}
EdgesNei Grid::get_edg_nei(const Coord &c) {
EdgesNei res;
res.e[0].d = (c.d + 1) % 3;
res.e[0].i = c.i;
res.e[0].j = c.j;
res.e[1].d = (c.d + 2) % 3;
res.e[1].i = c.i;
res.e[1].j = c.j;
if (c.d == 0) {
res.e[2].d = 2;
res.e[2].i = c.i;
res.e[2].j = c.j - 1;
res.e[3].d = 1;
res.e[3].i = c.i + 1;
res.e[3].j = c.j - 1;
} else if (c.d == 1) {
res.e[2].d = 0;
res.e[2].i = c.i - 1;
res.e[2].j = c.j + 1;
res.e[3].d = 2;
res.e[3].i = c.i - 1;
res.e[3].j = c.j;
} else {
res.e[2].d = 1;
res.e[2].i = c.i + 1;
res.e[2].j = c.j;
res.e[3].d = 0;
res.e[3].i = c.i;
res.e[3].j = c.j + 1;
}
return res;
}
int Grid::size() const { return size_; }
CalissonEdge Grid::edge(const Coord &c) const { return grid_[linearise(c)]; }
void Grid::set_edge(const Coord &c, CalissonEdge e) { grid_[linearise(c)] = e; }
int Grid::linearise(const Coord &c) const {
return c.d + 3 * c.j + 6 * size_ * c.i;
}
std::ostream &operator<<(std::ostream &os, const Grid &c) {
ByteCompressor bc(os, 2);
os << (char)(c.size() + 2 * 0x20);
for (int i = 0; i < 2 * c.size_; i++) {
const int str = c.start_j(i);
const int end = c.end_j(i);
for (int j = str; j < end; j++) {
if (j > str || i < c.size_) bc << c.edge({i, j, 0});
if (i > 0) bc << c.edge({i, j, 1});
if (j < end - 1 || i < c.size_) bc << c.edge({i, j, 2});
}
}
bc.end();
return os;
}
void Grid::to_image_blueprint_seg(std::ostream &os, const Coord &c) {
switch (edge(c)) {
case Calissons::Edge:
os << "E ";
break;
case Calissons::Losange:
os << "L ";
break;
case Calissons::EdgeVar:
os << "e ";
break;
default:
return;
}
os << c.i << " " << c.j << " " << c.d << "\n";
}
void Grid::to_image_blueprint(std::ostream &os) {
os << size_ << "\n";
for (int i = 0; i < 2 * size_; i++) {
const int str = start_j(i);
const int end = end_j(i);
for (int j = str; j < end; j++) {
if (j > str || i < size_) to_image_blueprint_seg(os, {i, j, 0});
if (i > 0) to_image_blueprint_seg(os, {i, j, 1});
if (j < end - 1 || i < size_) to_image_blueprint_seg(os, {i, j, 2});
}
}
}