spectre-tables-extra.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * Further data tables used to generate the final transition maps.
  3. */
  4. /*
  5. * Locations in the plane of the centres of the 8 hexagons in the
  6. * expansion of each hex.
  7. *
  8. * We take the centre-to-centre distance to be 6 units, so that other
  9. * locations in the hex tiling (e.g. edge midpoints and vertices) will
  10. * still have integer coefficients.
  11. *
  12. * These locations are represented using the same Point type used for
  13. * the whole tiling, but all our angles are 60 degrees, so we don't
  14. * ever need the coefficients of d or d^3, only of 1 and d^2.
  15. */
  16. static const Point hex_centres[] = {
  17. {{0, 0, 0, 0}}, {{6, 0, 0, 0}}, /* 0 1 */
  18. {{0, 0, -6, 0}}, {{6, 0, -6, 0}}, /* 2 3 */
  19. {{0, 0, -12, 0}}, {{6, 0, -12, 0}}, {{12, 0, -12, 0}}, /* 4 5 6 */
  20. {{12, 0, -18, 0}}, /* 7 */
  21. };
  22. /*
  23. * Orientations of all the sub-hexes in the expansion of each hex.
  24. * Measured anticlockwise (that is, as a power of s) from 0, where 0
  25. * means the hex is upright, with its own vertex #0 at the top.
  26. */
  27. static const unsigned orientations_G[] = {
  28. 2, /* HEX_F */
  29. 1, /* HEX_X */
  30. 0, /* HEX_G */
  31. 1, /* HEX_S */
  32. 4, /* HEX_P */
  33. 5, /* HEX_D */
  34. 0, /* HEX_J */
  35. /* hex #7 is not present for this tile */
  36. };
  37. static const unsigned orientations_D[] = {
  38. 2, /* HEX_F */
  39. 1, /* HEX_P */
  40. 0, /* HEX_G */
  41. 1, /* HEX_S */
  42. 4, /* HEX_X */
  43. 5, /* HEX_D */
  44. 0, /* HEX_F */
  45. 5, /* HEX_X */
  46. };
  47. static const unsigned orientations_J[] = {
  48. 2, /* HEX_F */
  49. 1, /* HEX_P */
  50. 0, /* HEX_G */
  51. 1, /* HEX_S */
  52. 4, /* HEX_Y */
  53. 5, /* HEX_D */
  54. 0, /* HEX_F */
  55. 5, /* HEX_P */
  56. };
  57. static const unsigned orientations_L[] = {
  58. 2, /* HEX_F */
  59. 1, /* HEX_P */
  60. 0, /* HEX_G */
  61. 1, /* HEX_S */
  62. 4, /* HEX_Y */
  63. 5, /* HEX_D */
  64. 0, /* HEX_F */
  65. 5, /* HEX_X */
  66. };
  67. static const unsigned orientations_X[] = {
  68. 2, /* HEX_F */
  69. 1, /* HEX_Y */
  70. 0, /* HEX_G */
  71. 1, /* HEX_S */
  72. 4, /* HEX_Y */
  73. 5, /* HEX_D */
  74. 0, /* HEX_F */
  75. 5, /* HEX_P */
  76. };
  77. static const unsigned orientations_P[] = {
  78. 2, /* HEX_F */
  79. 1, /* HEX_Y */
  80. 0, /* HEX_G */
  81. 1, /* HEX_S */
  82. 4, /* HEX_Y */
  83. 5, /* HEX_D */
  84. 0, /* HEX_F */
  85. 5, /* HEX_X */
  86. };
  87. static const unsigned orientations_S[] = {
  88. 2, /* HEX_L */
  89. 1, /* HEX_P */
  90. 0, /* HEX_G */
  91. 1, /* HEX_S */
  92. 4, /* HEX_X */
  93. 5, /* HEX_D */
  94. 0, /* HEX_F */
  95. 5, /* HEX_X */
  96. };
  97. static const unsigned orientations_F[] = {
  98. 2, /* HEX_F */
  99. 1, /* HEX_P */
  100. 0, /* HEX_G */
  101. 1, /* HEX_S */
  102. 4, /* HEX_Y */
  103. 5, /* HEX_D */
  104. 0, /* HEX_F */
  105. 5, /* HEX_Y */
  106. };
  107. static const unsigned orientations_Y[] = {
  108. 2, /* HEX_F */
  109. 1, /* HEX_Y */
  110. 0, /* HEX_G */
  111. 1, /* HEX_S */
  112. 4, /* HEX_Y */
  113. 5, /* HEX_D */
  114. 0, /* HEX_F */
  115. 5, /* HEX_Y */
  116. };
  117. /*
  118. * For each hex type, indicate the point on the boundary of the
  119. * expansion that corresponds to vertex 0 of the superhex. Also,
  120. * indicate the initial direction we head in to go round the edge.
  121. */
  122. #define HEX_OUTLINE_START_COMMON {{ -4, 0, -10, 0 }}, {{ +2, 0, +2, 0 }}
  123. #define HEX_OUTLINE_START_RARE {{ -2, 0, -14, 0 }}, {{ -2, 0, +4, 0 }}
  124. #define HEX_OUTLINE_START_G HEX_OUTLINE_START_COMMON
  125. #define HEX_OUTLINE_START_D HEX_OUTLINE_START_RARE
  126. #define HEX_OUTLINE_START_J HEX_OUTLINE_START_COMMON
  127. #define HEX_OUTLINE_START_L HEX_OUTLINE_START_COMMON
  128. #define HEX_OUTLINE_START_X HEX_OUTLINE_START_COMMON
  129. #define HEX_OUTLINE_START_P HEX_OUTLINE_START_COMMON
  130. #define HEX_OUTLINE_START_S HEX_OUTLINE_START_RARE
  131. #define HEX_OUTLINE_START_F HEX_OUTLINE_START_COMMON
  132. #define HEX_OUTLINE_START_Y HEX_OUTLINE_START_COMMON
  133. /*
  134. * Similarly, for each hex type, indicate the point on the boundary of
  135. * its Spectre expansion that corresponds to hex vertex 0.
  136. *
  137. * This time, it's easiest just to indicate which vertex of which
  138. * sub-Spectre we take in each case, because the Spectre outlines
  139. * don't take predictable turns between the edge expansions, so the
  140. * routine consuming this data will have to look things up in its
  141. * edgemap anyway.
  142. */
  143. #define SPEC_OUTLINE_START_COMMON 0, 9
  144. #define SPEC_OUTLINE_START_RARE 0, 8
  145. #define SPEC_OUTLINE_START_G SPEC_OUTLINE_START_COMMON
  146. #define SPEC_OUTLINE_START_D SPEC_OUTLINE_START_RARE
  147. #define SPEC_OUTLINE_START_J SPEC_OUTLINE_START_COMMON
  148. #define SPEC_OUTLINE_START_L SPEC_OUTLINE_START_COMMON
  149. #define SPEC_OUTLINE_START_X SPEC_OUTLINE_START_COMMON
  150. #define SPEC_OUTLINE_START_P SPEC_OUTLINE_START_COMMON
  151. #define SPEC_OUTLINE_START_S SPEC_OUTLINE_START_RARE
  152. #define SPEC_OUTLINE_START_F SPEC_OUTLINE_START_COMMON
  153. #define SPEC_OUTLINE_START_Y SPEC_OUTLINE_START_COMMON
  154. /*
  155. * The paper also defines a set of 8 different classes of edges for
  156. * the hexagons. (You can imagine these as different shapes of
  157. * jigsaw-piece tab, constraining how the hexes can fit together). So
  158. * for each hex, we need a list of its edge types.
  159. *
  160. * Most edge types come in two matching pairs, which the paper labels
  161. * with the same lowercase Greek letter and a + or - superscript, e.g.
  162. * alpha^+ and alpha^-. The usual rule is that when two edges meet,
  163. * they have to be the + and - versions of the same letter. The
  164. * exception to this rule is the 'eta' edge, which has no sign: it's
  165. * symmetric, so any two eta edges can validly meet.
  166. *
  167. * We express this here by defining an enumeration in which eta = 0
  168. * and all other edge types have positive values, so that integer
  169. * negation can be used to indicate the other edge that fits with this
  170. * one (and for eta, it doesn't change the value).
  171. */
  172. enum Edge {
  173. edge_eta = 0,
  174. edge_alpha,
  175. edge_beta,
  176. edge_gamma,
  177. edge_delta,
  178. edge_epsilon,
  179. edge_zeta,
  180. edge_theta,
  181. };
  182. /*
  183. * Edge types for each hex are specified anticlockwise, starting from
  184. * the top vertex, so that edge #0 is the top-left diagonal edge, edge
  185. * #1 the left-hand vertical edge, etc.
  186. */
  187. static const int edges_G[6] = {
  188. -edge_beta, -edge_alpha, +edge_alpha,
  189. -edge_gamma, -edge_delta, +edge_beta,
  190. };
  191. static const int edges_D[6] = {
  192. -edge_zeta, +edge_gamma, +edge_beta,
  193. -edge_epsilon, +edge_alpha, -edge_gamma,
  194. };
  195. static const int edges_J[6] = {
  196. -edge_beta, +edge_gamma, +edge_beta,
  197. +edge_theta, +edge_beta, edge_eta,
  198. };
  199. static const int edges_L[6] = {
  200. -edge_beta, +edge_gamma, +edge_beta,
  201. -edge_epsilon, +edge_alpha, -edge_theta,
  202. };
  203. static const int edges_X[6] = {
  204. -edge_beta, -edge_alpha, +edge_epsilon,
  205. +edge_theta, +edge_beta, edge_eta,
  206. };
  207. static const int edges_P[6] = {
  208. -edge_beta, -edge_alpha, +edge_epsilon,
  209. -edge_epsilon, +edge_alpha, -edge_theta,
  210. };
  211. static const int edges_S[6] = {
  212. +edge_delta, +edge_zeta, +edge_beta,
  213. -edge_epsilon, +edge_alpha, -edge_gamma,
  214. };
  215. static const int edges_F[6] = {
  216. -edge_beta, +edge_gamma, +edge_beta,
  217. -edge_epsilon, +edge_epsilon, edge_eta,
  218. };
  219. static const int edges_Y[6] = {
  220. -edge_beta, -edge_alpha, +edge_epsilon,
  221. -edge_epsilon, +edge_epsilon, edge_eta,
  222. };
  223. /*
  224. * Now specify the actual shape of each edge type, in terms of the
  225. * angles of turns as you traverse the edge.
  226. *
  227. * Edges around the outline of a hex expansion are traversed
  228. * _clockwise_, because each expansion step flips the handedness of
  229. * the whole system.
  230. *
  231. * Each array has one fewer element than the number of sub-edges in
  232. * the edge shape (for the usual reason - n edges in a path have only
  233. * n-1 vertices separating them).
  234. *
  235. * These arrays show the positive version of each edge type. The
  236. * negative version is obtained by reversing the order of the turns
  237. * and also the sign of each turn.
  238. */
  239. static const int hex_edge_shape_eta[] = { +2, +2, -2, -2 };
  240. static const int hex_edge_shape_alpha[] = { +2, -2 };
  241. static const int hex_edge_shape_beta[] = { -2 };
  242. static const int hex_edge_shape_gamma[] = { +2, -2, -2, +2 };
  243. static const int hex_edge_shape_delta[] = { -2, +2, -2, +2 };
  244. static const int hex_edge_shape_epsilon[] = { +2, -2, -2 };
  245. static const int hex_edge_shape_zeta[] = { -2, +2 };
  246. static const int hex_edge_shape_theta[] = { +2, +2, -2, -2, +2 };
  247. static const int *const hex_edge_shapes[] = {
  248. hex_edge_shape_eta,
  249. hex_edge_shape_alpha,
  250. hex_edge_shape_beta,
  251. hex_edge_shape_gamma,
  252. hex_edge_shape_delta,
  253. hex_edge_shape_epsilon,
  254. hex_edge_shape_zeta,
  255. hex_edge_shape_theta,
  256. };
  257. static const size_t hex_edge_lengths[] = {
  258. lenof(hex_edge_shape_eta) + 1,
  259. lenof(hex_edge_shape_alpha) + 1,
  260. lenof(hex_edge_shape_beta) + 1,
  261. lenof(hex_edge_shape_gamma) + 1,
  262. lenof(hex_edge_shape_delta) + 1,
  263. lenof(hex_edge_shape_epsilon) + 1,
  264. lenof(hex_edge_shape_zeta) + 1,
  265. lenof(hex_edge_shape_theta) + 1,
  266. };
  267. static const int spec_edge_shape_eta[] = { 0 };
  268. static const int spec_edge_shape_alpha[] = { -2, +3 };
  269. static const int spec_edge_shape_beta[] = { +3, -2 };
  270. static const int spec_edge_shape_gamma[] = { +2 };
  271. static const int spec_edge_shape_delta[] = { +2, +3, +2, -3, +2 };
  272. static const int spec_edge_shape_epsilon[] = { +3 };
  273. static const int spec_edge_shape_zeta[] = { -2 };
  274. /* In expansion to Spectres, a theta edge corresponds to just one
  275. * Spectre edge, so its turns array would be completely empty! */
  276. static const int *const spec_edge_shapes[] = {
  277. spec_edge_shape_eta,
  278. spec_edge_shape_alpha,
  279. spec_edge_shape_beta,
  280. spec_edge_shape_gamma,
  281. spec_edge_shape_delta,
  282. spec_edge_shape_epsilon,
  283. spec_edge_shape_zeta,
  284. NULL, /* theta has no turns */
  285. };
  286. static const size_t spec_edge_lengths[] = {
  287. lenof(spec_edge_shape_eta) + 1,
  288. lenof(spec_edge_shape_alpha) + 1,
  289. lenof(spec_edge_shape_beta) + 1,
  290. lenof(spec_edge_shape_gamma) + 1,
  291. lenof(spec_edge_shape_delta) + 1,
  292. lenof(spec_edge_shape_epsilon) + 1,
  293. lenof(spec_edge_shape_zeta) + 1,
  294. 1, /* theta is only one edge long */
  295. };
  296. /*
  297. * Each edge type corresponds to a fixed number of edges of the
  298. * hexagon layout in the expansion of each hex, and also to a fixed
  299. * number of edges of the Spectre(s) that each hex expands to in the
  300. * final step.
  301. */
  302. static const int edgelen_hex[] = {
  303. 5, /* edge_eta */
  304. 3, /* edge_alpha */
  305. 2, /* edge_beta */
  306. 5, /* edge_gamma */
  307. 5, /* edge_delta */
  308. 4, /* edge_epsilon */
  309. 3, /* edge_zeta */
  310. 6, /* edge_theta */
  311. };
  312. static const int edgelen_spectre[] = {
  313. 2, /* edge_eta */
  314. 3, /* edge_alpha */
  315. 3, /* edge_beta */
  316. 2, /* edge_gamma */
  317. 6, /* edge_delta */
  318. 2, /* edge_epsilon */
  319. 2, /* edge_zeta */
  320. 1, /* edge_theta */
  321. };