cubegin 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +674 -0
  3. package/NOTICE +11 -0
  4. package/README.md +49 -0
  5. package/dist/scramble-core/src/batch.mjs +18 -0
  6. package/dist/scramble-core/src/generator.d.mts +35 -0
  7. package/dist/scramble-core/src/generator.mjs +136 -0
  8. package/dist/scramble-core/src/generators/clock.d.mts +11 -0
  9. package/dist/scramble-core/src/generators/clock.mjs +32 -0
  10. package/dist/scramble-core/src/generators/cube-random-turns.d.mts +11 -0
  11. package/dist/scramble-core/src/generators/cube-random-turns.mjs +54 -0
  12. package/dist/scramble-core/src/generators/four-by-four.d.mts +14 -0
  13. package/dist/scramble-core/src/generators/four-by-four.mjs +43 -0
  14. package/dist/scramble-core/src/generators/megaminx.d.mts +11 -0
  15. package/dist/scramble-core/src/generators/megaminx.mjs +18 -0
  16. package/dist/scramble-core/src/generators/pyraminx.d.mts +11 -0
  17. package/dist/scramble-core/src/generators/pyraminx.mjs +17 -0
  18. package/dist/scramble-core/src/generators/skewb.d.mts +11 -0
  19. package/dist/scramble-core/src/generators/skewb.mjs +17 -0
  20. package/dist/scramble-core/src/generators/square1.d.mts +11 -0
  21. package/dist/scramble-core/src/generators/square1.mjs +28 -0
  22. package/dist/scramble-core/src/generators/three-by-three.d.mts +25 -0
  23. package/dist/scramble-core/src/generators/three-by-three.mjs +85 -0
  24. package/dist/scramble-core/src/generators/two-by-two.d.mts +11 -0
  25. package/dist/scramble-core/src/generators/two-by-two.mjs +17 -0
  26. package/dist/scramble-core/src/random-source.d.mts +7 -0
  27. package/dist/scramble-core/src/random-source.mjs +8 -0
  28. package/dist/scramble-core/src/solvers/min2phase/coord-cube.mjs +10 -0
  29. package/dist/scramble-core/src/solvers/min2phase/cubie-cube.mjs +246 -0
  30. package/dist/scramble-core/src/solvers/min2phase/engine.mjs +1281 -0
  31. package/dist/scramble-core/src/solvers/min2phase/search-wca.mjs +21 -0
  32. package/dist/scramble-core/src/solvers/min2phase/search.mjs +25 -0
  33. package/dist/scramble-core/src/solvers/min2phase/tools.mjs +169 -0
  34. package/dist/scramble-core/src/solvers/min2phase/util.mjs +30 -0
  35. package/dist/scramble-core/src/solvers/pyraminx-solver.d.mts +17 -0
  36. package/dist/scramble-core/src/solvers/pyraminx-solver.mjs +350 -0
  37. package/dist/scramble-core/src/solvers/skewb-solver.d.mts +15 -0
  38. package/dist/scramble-core/src/solvers/skewb-solver.mjs +399 -0
  39. package/dist/scramble-core/src/solvers/sq12phase/full-cube.mjs +212 -0
  40. package/dist/scramble-core/src/solvers/sq12phase/search.mjs +520 -0
  41. package/dist/scramble-core/src/solvers/sq12phase/shape.mjs +214 -0
  42. package/dist/scramble-core/src/solvers/sq12phase/square.mjs +135 -0
  43. package/dist/scramble-core/src/solvers/threephase/center.mjs +798 -0
  44. package/dist/scramble-core/src/solvers/threephase/edge.mjs +632 -0
  45. package/dist/scramble-core/src/solvers/threephase/full-cube.mjs +554 -0
  46. package/dist/scramble-core/src/solvers/threephase/search.mjs +262 -0
  47. package/dist/scramble-core/src/solvers/threephase/tables.mjs +201 -0
  48. package/dist/scramble-core/src/solvers/two-by-two-solver.d.mts +15 -0
  49. package/dist/scramble-core/src/solvers/two-by-two-solver.mjs +298 -0
  50. package/dist/scramble-core.d.mts +15 -0
  51. package/dist/scramble-core.mjs +15 -0
  52. package/dist/scramble-image/src/color.d.mts +12 -0
  53. package/dist/scramble-image/src/color.mjs +11 -0
  54. package/dist/scramble-image/src/render.d.mts +10 -0
  55. package/dist/scramble-image/src/render.mjs +71 -0
  56. package/dist/scramble-image/src/renderers/clock.d.mts +6 -0
  57. package/dist/scramble-image/src/renderers/clock.mjs +145 -0
  58. package/dist/scramble-image/src/renderers/cube-isometric.d.mts +8 -0
  59. package/dist/scramble-image/src/renderers/cube-isometric.mjs +204 -0
  60. package/dist/scramble-image/src/renderers/cube-net.d.mts +8 -0
  61. package/dist/scramble-image/src/renderers/cube-net.mjs +52 -0
  62. package/dist/scramble-image/src/renderers/megaminx-isometric.d.mts +9 -0
  63. package/dist/scramble-image/src/renderers/megaminx-isometric.mjs +320 -0
  64. package/dist/scramble-image/src/renderers/megaminx.d.mts +9 -0
  65. package/dist/scramble-image/src/renderers/megaminx.mjs +173 -0
  66. package/dist/scramble-image/src/renderers/pyraminx-isometric.d.mts +9 -0
  67. package/dist/scramble-image/src/renderers/pyraminx-isometric.mjs +185 -0
  68. package/dist/scramble-image/src/renderers/pyraminx.d.mts +9 -0
  69. package/dist/scramble-image/src/renderers/pyraminx.mjs +111 -0
  70. package/dist/scramble-image/src/renderers/skewb-isometric.d.mts +9 -0
  71. package/dist/scramble-image/src/renderers/skewb-isometric.mjs +233 -0
  72. package/dist/scramble-image/src/renderers/skewb.d.mts +9 -0
  73. package/dist/scramble-image/src/renderers/skewb.mjs +187 -0
  74. package/dist/scramble-image/src/renderers/square1.d.mts +10 -0
  75. package/dist/scramble-image/src/renderers/square1.mjs +253 -0
  76. package/dist/scramble-image/src/svg/svg-document.d.mts +6 -0
  77. package/dist/scramble-image/src/svg/svg-document.mjs +7 -0
  78. package/dist/scramble-image/src/svg/svg-elements.d.mts +15 -0
  79. package/dist/scramble-image/src/svg/svg-elements.mjs +25 -0
  80. package/dist/scramble-image/src/svg/svg-serialize.mjs +29 -0
  81. package/dist/scramble-image.d.mts +15 -0
  82. package/dist/scramble-image.mjs +15 -0
  83. package/dist/scramble-puzzle/src/algorithm.d.mts +8 -0
  84. package/dist/scramble-puzzle/src/algorithm.mjs +16 -0
  85. package/dist/scramble-puzzle/src/algorithm2.mjs +16 -0
  86. package/dist/scramble-puzzle/src/clock/clock-definition.d.mts +8 -0
  87. package/dist/scramble-puzzle/src/clock/clock-definition.mjs +18 -0
  88. package/dist/scramble-puzzle/src/clock/clock-definition2.mjs +18 -0
  89. package/dist/scramble-puzzle/src/clock/clock-parser.d.mts +18 -0
  90. package/dist/scramble-puzzle/src/clock/clock-parser.mjs +35 -0
  91. package/dist/scramble-puzzle/src/clock/clock-parser2.mjs +35 -0
  92. package/dist/scramble-puzzle/src/clock/clock-state.d.mts +8 -0
  93. package/dist/scramble-puzzle/src/clock/clock-state.mjs +212 -0
  94. package/dist/scramble-puzzle/src/clock/clock-state2.d.mts +13 -0
  95. package/dist/scramble-puzzle/src/clock/clock-state2.mjs +212 -0
  96. package/dist/scramble-puzzle/src/cube/cube-definition.d.mts +9 -0
  97. package/dist/scramble-puzzle/src/cube/cube-definition.mjs +18 -0
  98. package/dist/scramble-puzzle/src/cube/cube-definition2.mjs +18 -0
  99. package/dist/scramble-puzzle/src/cube/cube-move.d.mts +4 -0
  100. package/dist/scramble-puzzle/src/cube/cube-move2.d.mts +17 -0
  101. package/dist/scramble-puzzle/src/cube/cube-parser.d.mts +7 -0
  102. package/dist/scramble-puzzle/src/cube/cube-parser.mjs +60 -0
  103. package/dist/scramble-puzzle/src/cube/cube-parser2.mjs +60 -0
  104. package/dist/scramble-puzzle/src/cube/cube-state.d.mts +12 -0
  105. package/dist/scramble-puzzle/src/cube/cube-state.mjs +187 -0
  106. package/dist/scramble-puzzle/src/cube/cube-state2.d.mts +15 -0
  107. package/dist/scramble-puzzle/src/cube/cube-state2.mjs +187 -0
  108. package/dist/scramble-puzzle/src/errors.d.mts +15 -0
  109. package/dist/scramble-puzzle/src/errors.mjs +24 -0
  110. package/dist/scramble-puzzle/src/errors2.mjs +30 -0
  111. package/dist/scramble-puzzle/src/events.d.mts +5 -0
  112. package/dist/scramble-puzzle/src/events.mjs +90 -0
  113. package/dist/scramble-puzzle/src/events2.d.mts +98 -0
  114. package/dist/scramble-puzzle/src/events2.mjs +109 -0
  115. package/dist/scramble-puzzle/src/index.mjs +22 -0
  116. package/dist/scramble-puzzle/src/megaminx/megaminx-definition.d.mts +8 -0
  117. package/dist/scramble-puzzle/src/megaminx/megaminx-definition.mjs +18 -0
  118. package/dist/scramble-puzzle/src/megaminx/megaminx-definition2.mjs +18 -0
  119. package/dist/scramble-puzzle/src/megaminx/megaminx-parser.d.mts +5 -0
  120. package/dist/scramble-puzzle/src/megaminx/megaminx-parser.mjs +57 -0
  121. package/dist/scramble-puzzle/src/megaminx/megaminx-parser2.d.mts +20 -0
  122. package/dist/scramble-puzzle/src/megaminx/megaminx-parser2.mjs +57 -0
  123. package/dist/scramble-puzzle/src/megaminx/megaminx-state.d.mts +9 -0
  124. package/dist/scramble-puzzle/src/megaminx/megaminx-state.mjs +112 -0
  125. package/dist/scramble-puzzle/src/megaminx/megaminx-state2.d.mts +14 -0
  126. package/dist/scramble-puzzle/src/megaminx/megaminx-state2.mjs +112 -0
  127. package/dist/scramble-puzzle/src/puzzle-definition.d.mts +19 -0
  128. package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition.d.mts +8 -0
  129. package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition.mjs +18 -0
  130. package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition2.mjs +18 -0
  131. package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser.d.mts +5 -0
  132. package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser.mjs +34 -0
  133. package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser2.d.mts +21 -0
  134. package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser2.mjs +34 -0
  135. package/dist/scramble-puzzle/src/pyraminx/pyraminx-state.d.mts +11 -0
  136. package/dist/scramble-puzzle/src/pyraminx/pyraminx-state.mjs +90 -0
  137. package/dist/scramble-puzzle/src/pyraminx/pyraminx-state2.d.mts +14 -0
  138. package/dist/scramble-puzzle/src/pyraminx/pyraminx-state2.mjs +90 -0
  139. package/dist/scramble-puzzle/src/registry.d.mts +11 -0
  140. package/dist/scramble-puzzle/src/registry.mjs +13 -0
  141. package/dist/scramble-puzzle/src/skewb/skewb-definition.d.mts +8 -0
  142. package/dist/scramble-puzzle/src/skewb/skewb-definition.mjs +18 -0
  143. package/dist/scramble-puzzle/src/skewb/skewb-definition2.mjs +18 -0
  144. package/dist/scramble-puzzle/src/skewb/skewb-parser.d.mts +5 -0
  145. package/dist/scramble-puzzle/src/skewb/skewb-parser.mjs +33 -0
  146. package/dist/scramble-puzzle/src/skewb/skewb-parser2.d.mts +14 -0
  147. package/dist/scramble-puzzle/src/skewb/skewb-parser2.mjs +33 -0
  148. package/dist/scramble-puzzle/src/skewb/skewb-state.d.mts +11 -0
  149. package/dist/scramble-puzzle/src/skewb/skewb-state.mjs +75 -0
  150. package/dist/scramble-puzzle/src/skewb/skewb-state2.d.mts +14 -0
  151. package/dist/scramble-puzzle/src/skewb/skewb-state2.mjs +75 -0
  152. package/dist/scramble-puzzle/src/square1/square1-definition.d.mts +8 -0
  153. package/dist/scramble-puzzle/src/square1/square1-definition.mjs +18 -0
  154. package/dist/scramble-puzzle/src/square1/square1-definition2.mjs +18 -0
  155. package/dist/scramble-puzzle/src/square1/square1-parser.d.mts +17 -0
  156. package/dist/scramble-puzzle/src/square1/square1-parser.mjs +43 -0
  157. package/dist/scramble-puzzle/src/square1/square1-parser2.mjs +47 -0
  158. package/dist/scramble-puzzle/src/square1/square1-state.d.mts +9 -0
  159. package/dist/scramble-puzzle/src/square1/square1-state.mjs +115 -0
  160. package/dist/scramble-puzzle/src/square1/square1-state2.d.mts +21 -0
  161. package/dist/scramble-puzzle/src/square1/square1-state2.mjs +115 -0
  162. package/dist/scramble-puzzle.d.mts +25 -0
  163. package/dist/scramble-puzzle.mjs +23 -0
  164. package/package.json +37 -0
@@ -0,0 +1,399 @@
1
+ //#region .build/vendor/scramble-core/src/solvers/skewb-solver.ts
2
+ const ERROR_PREFIX = "@cubegin/scramble-core";
3
+ const N_MOVES = 4;
4
+ const N_PERM = 4320;
5
+ const N_TWIST = 2187;
6
+ const MAX_SOLUTION_LENGTH = 12;
7
+ const MAX_TWIST_ATTEMPTS = 100;
8
+ const FACT = [
9
+ 1,
10
+ 1,
11
+ 1,
12
+ 3,
13
+ 12,
14
+ 60,
15
+ 360
16
+ ];
17
+ const CORNER_PERM_MOVES = [
18
+ [
19
+ 6,
20
+ 5,
21
+ 10,
22
+ 1
23
+ ],
24
+ [
25
+ 9,
26
+ 7,
27
+ 4,
28
+ 2
29
+ ],
30
+ [
31
+ 3,
32
+ 11,
33
+ 8,
34
+ 0
35
+ ],
36
+ [
37
+ 10,
38
+ 1,
39
+ 6,
40
+ 5
41
+ ],
42
+ [
43
+ 0,
44
+ 8,
45
+ 11,
46
+ 3
47
+ ],
48
+ [
49
+ 7,
50
+ 9,
51
+ 2,
52
+ 4
53
+ ],
54
+ [
55
+ 4,
56
+ 2,
57
+ 9,
58
+ 7
59
+ ],
60
+ [
61
+ 11,
62
+ 3,
63
+ 0,
64
+ 8
65
+ ],
66
+ [
67
+ 1,
68
+ 10,
69
+ 5,
70
+ 6
71
+ ],
72
+ [
73
+ 8,
74
+ 0,
75
+ 3,
76
+ 11
77
+ ],
78
+ [
79
+ 2,
80
+ 4,
81
+ 7,
82
+ 9
83
+ ],
84
+ [
85
+ 5,
86
+ 6,
87
+ 1,
88
+ 10
89
+ ]
90
+ ];
91
+ const ORIENTATION_BY_CORNER = [
92
+ 0,
93
+ 1,
94
+ 2,
95
+ 0,
96
+ 2,
97
+ 1,
98
+ 1,
99
+ 2,
100
+ 0,
101
+ 2,
102
+ 1,
103
+ 0
104
+ ];
105
+ const SOLUTION_MOVES = [
106
+ "L",
107
+ "R",
108
+ "B",
109
+ "U"
110
+ ];
111
+ let cachedTables;
112
+ const createAvailableCenters = () => [
113
+ 0,
114
+ 1,
115
+ 2,
116
+ 3,
117
+ 4,
118
+ 5
119
+ ];
120
+ const unpackCenterPerm = (centerIndex) => {
121
+ let remaining = centerIndex;
122
+ let parity = 0;
123
+ const available = createAvailableCenters();
124
+ const centerPerm = Array.from({ length: 6 }, () => 0);
125
+ for (let position = 0; position < 5; position += 1) {
126
+ const divisor = FACT[5 - position];
127
+ const selectedIndex = Math.floor(remaining / divisor);
128
+ remaining -= selectedIndex * divisor;
129
+ parity ^= selectedIndex;
130
+ centerPerm[position] = available.splice(selectedIndex, 1)[0];
131
+ }
132
+ if ((parity & 1) === 0) centerPerm[5] = available[0];
133
+ else {
134
+ centerPerm[5] = centerPerm[4];
135
+ centerPerm[4] = available[0];
136
+ }
137
+ return centerPerm;
138
+ };
139
+ const packCenterPerm = (centerPerm) => {
140
+ const available = createAvailableCenters();
141
+ let centerIndex = 0;
142
+ for (let position = 0; position < 4; position += 1) {
143
+ const selectedIndex = available.indexOf(centerPerm[position]);
144
+ centerIndex *= 6 - position;
145
+ centerIndex += selectedIndex;
146
+ available.splice(selectedIndex, 1);
147
+ }
148
+ return centerIndex;
149
+ };
150
+ const moveCenterPerm = (centerPerm, move) => {
151
+ let savedCenter;
152
+ switch (move) {
153
+ case 0:
154
+ savedCenter = centerPerm[0];
155
+ centerPerm[0] = centerPerm[1];
156
+ centerPerm[1] = centerPerm[3];
157
+ centerPerm[3] = savedCenter;
158
+ break;
159
+ case 1:
160
+ savedCenter = centerPerm[0];
161
+ centerPerm[0] = centerPerm[4];
162
+ centerPerm[4] = centerPerm[2];
163
+ centerPerm[2] = savedCenter;
164
+ break;
165
+ case 2:
166
+ savedCenter = centerPerm[1];
167
+ centerPerm[1] = centerPerm[2];
168
+ centerPerm[2] = centerPerm[5];
169
+ centerPerm[5] = savedCenter;
170
+ break;
171
+ case 3:
172
+ savedCenter = centerPerm[3];
173
+ centerPerm[3] = centerPerm[5];
174
+ centerPerm[5] = centerPerm[4];
175
+ centerPerm[4] = savedCenter;
176
+ break;
177
+ }
178
+ };
179
+ const getPermMove = (index, move) => {
180
+ const centerPerm = unpackCenterPerm(Math.floor(index / 12));
181
+ const cornerIndex = index % 12;
182
+ moveCenterPerm(centerPerm, move);
183
+ return packCenterPerm(centerPerm) * 12 + CORNER_PERM_MOVES[cornerIndex][move];
184
+ };
185
+ const getTwistMove = (index, move) => {
186
+ const fixedTwist = Array.from({ length: 4 }, () => 0);
187
+ const twist = Array.from({ length: 4 }, () => 0);
188
+ let remaining = index;
189
+ for (let position = 0; position < 4; position += 1) {
190
+ fixedTwist[position] = remaining % 3;
191
+ remaining = Math.floor(remaining / 3);
192
+ }
193
+ for (let position = 0; position < 3; position += 1) {
194
+ twist[position] = remaining % 3;
195
+ remaining = Math.floor(remaining / 3);
196
+ }
197
+ twist[3] = (6 - twist[0] - twist[1] - twist[2]) % 3;
198
+ fixedTwist[move] = (fixedTwist[move] + 1) % 3;
199
+ let savedTwist;
200
+ switch (move) {
201
+ case 0:
202
+ savedTwist = twist[0];
203
+ twist[0] = twist[2] + 2;
204
+ twist[2] = twist[1] + 2;
205
+ twist[1] = savedTwist + 2;
206
+ break;
207
+ case 1:
208
+ savedTwist = twist[0];
209
+ twist[0] = twist[1] + 2;
210
+ twist[1] = twist[3] + 2;
211
+ twist[3] = savedTwist + 2;
212
+ break;
213
+ case 2:
214
+ savedTwist = twist[0];
215
+ twist[0] = twist[3] + 2;
216
+ twist[3] = twist[2] + 2;
217
+ twist[2] = savedTwist + 2;
218
+ break;
219
+ case 3:
220
+ savedTwist = twist[1];
221
+ twist[1] = twist[2] + 2;
222
+ twist[2] = twist[3] + 2;
223
+ twist[3] = savedTwist + 2;
224
+ break;
225
+ }
226
+ for (let position = 2; position >= 0; position -= 1) remaining = remaining * 3 + twist[position] % 3;
227
+ for (let position = 3; position >= 0; position -= 1) remaining = remaining * 3 + fixedTwist[position];
228
+ return remaining;
229
+ };
230
+ const createMoveTables = () => {
231
+ const movePerm = Array.from({ length: N_PERM }, () => new Uint16Array(N_MOVES));
232
+ const moveTwist = Array.from({ length: N_TWIST }, () => new Uint16Array(N_MOVES));
233
+ for (let permutation = 0; permutation < N_PERM; permutation += 1) for (let move = 0; move < N_MOVES; move += 1) movePerm[permutation][move] = getPermMove(permutation, move);
234
+ for (let twist = 0; twist < N_TWIST; twist += 1) for (let move = 0; move < N_MOVES; move += 1) moveTwist[twist][move] = getTwistMove(twist, move);
235
+ return {
236
+ movePerm,
237
+ moveTwist
238
+ };
239
+ };
240
+ const createPermutationPruningTable = (movePerm) => {
241
+ const pruning = new Int8Array(N_PERM);
242
+ pruning.fill(-1);
243
+ pruning[0] = 0;
244
+ for (let length = 0; length < 6; length += 1) for (let permutation = 0; permutation < N_PERM; permutation += 1) {
245
+ if (pruning[permutation] !== length) continue;
246
+ for (let move = 0; move < N_MOVES; move += 1) {
247
+ let nextPermutation = permutation;
248
+ for (let count = 0; count < 2; count += 1) {
249
+ nextPermutation = movePerm[nextPermutation][move];
250
+ if (pruning[nextPermutation] !== -1) continue;
251
+ pruning[nextPermutation] = length + 1;
252
+ }
253
+ }
254
+ }
255
+ return pruning;
256
+ };
257
+ const createTwistPruningTable = (moveTwist) => {
258
+ const pruning = new Int8Array(N_TWIST);
259
+ pruning.fill(-1);
260
+ pruning[0] = 0;
261
+ for (let length = 0; length < 6; length += 1) for (let twist = 0; twist < N_TWIST; twist += 1) {
262
+ if (pruning[twist] !== length) continue;
263
+ for (let move = 0; move < N_MOVES; move += 1) {
264
+ let nextTwist = twist;
265
+ for (let count = 0; count < 2; count += 1) {
266
+ nextTwist = moveTwist[nextTwist][move];
267
+ if (pruning[nextTwist] !== -1) continue;
268
+ pruning[nextTwist] = length + 1;
269
+ }
270
+ }
271
+ }
272
+ return pruning;
273
+ };
274
+ const createTables = () => {
275
+ const { movePerm, moveTwist } = createMoveTables();
276
+ return {
277
+ movePerm,
278
+ moveTwist,
279
+ prunPerm: createPermutationPruningTable(movePerm),
280
+ prunTwist: createTwistPruningTable(moveTwist)
281
+ };
282
+ };
283
+ const getTables = () => {
284
+ cachedTables ??= createTables();
285
+ return cachedTables;
286
+ };
287
+ const validateCoordinate = (coordinateName, coordinate, maxExclusive) => {
288
+ if (!Number.isSafeInteger(coordinate) || coordinate < 0 || coordinate >= maxExclusive) throw new RangeError(`${ERROR_PREFIX}: Skewb ${coordinateName} must be an integer from 0 to ${maxExclusive - 1}`);
289
+ };
290
+ const validateState = (state) => {
291
+ validateCoordinate("perm", state.perm, N_PERM);
292
+ validateCoordinate("twst", state.twst, N_TWIST);
293
+ };
294
+ const validateLength = (length) => {
295
+ if (!Number.isSafeInteger(length) || length < 0 || length > MAX_SOLUTION_LENGTH) throw new RangeError(`${ERROR_PREFIX}: Skewb solve length must be an integer from 0 to ${MAX_SOLUTION_LENGTH}`);
296
+ };
297
+ const nextCoordinate = (random, coordinateName, maxExclusive) => {
298
+ const coordinate = random.nextInt(maxExclusive);
299
+ validateCoordinate(coordinateName, coordinate, maxExclusive);
300
+ return coordinate;
301
+ };
302
+ const isSolvable = (state) => ORIENTATION_BY_CORNER[state.perm % 12] === (state.twst + Math.floor(state.twst / 3) + Math.floor(state.twst / 9) + Math.floor(state.twst / 27)) % 3;
303
+ const search = ({ perm, twst, depth, length, lastMove, solution, random, tables }) => {
304
+ if (length === 0) return perm === 0 && twst === 0 ? depth : -1;
305
+ if (tables.prunPerm[perm] > length || tables.prunTwist[twst] > length) return -1;
306
+ const randomOffset = nextCoordinate(random, "searchMoveOffset", N_MOVES);
307
+ for (let move = 0; move < N_MOVES; move += 1) {
308
+ const randomMove = (move + randomOffset) % N_MOVES;
309
+ if (randomMove === lastMove) continue;
310
+ let nextPerm = perm;
311
+ let nextTwist = twst;
312
+ for (let amount = 0; amount < 2; amount += 1) {
313
+ nextPerm = tables.movePerm[nextPerm][randomMove];
314
+ nextTwist = tables.moveTwist[nextTwist][randomMove];
315
+ const searchResult = search({
316
+ perm: nextPerm,
317
+ twst: nextTwist,
318
+ depth: depth + 1,
319
+ length: length - 1,
320
+ lastMove: randomMove,
321
+ solution,
322
+ random,
323
+ tables
324
+ });
325
+ if (searchResult !== -1) {
326
+ solution[depth] = randomMove * 2 + amount;
327
+ return searchResult;
328
+ }
329
+ }
330
+ }
331
+ return -1;
332
+ };
333
+ const swapMoveNames = (moveNames) => {
334
+ const savedMove = moveNames[0];
335
+ moveNames[0] = moveNames[1];
336
+ moveNames[1] = moveNames[3];
337
+ moveNames[3] = savedMove;
338
+ };
339
+ const formatSolution = (solution, solutionLength) => {
340
+ const moves = [];
341
+ const moveNames = [...SOLUTION_MOVES];
342
+ for (let index = 0; index < solutionLength; index += 1) {
343
+ const axis = solution[index] >> 1;
344
+ const power = solution[index] & 1;
345
+ if (axis === 2) for (let count = 0; count <= power; count += 1) swapMoveNames(moveNames);
346
+ moves.push(`${moveNames[axis]}${power === 1 ? "'" : ""}`);
347
+ }
348
+ return moves.join(" ");
349
+ };
350
+ var SkewbSolver = class {
351
+ randomState(random) {
352
+ const state = {
353
+ perm: nextCoordinate(random, "perm", N_PERM),
354
+ twst: 0
355
+ };
356
+ for (let attempt = 0; attempt < MAX_TWIST_ATTEMPTS; attempt += 1) {
357
+ const sampledTwist = nextCoordinate(random, "twst", N_TWIST);
358
+ const sampledState = {
359
+ ...state,
360
+ twst: sampledTwist
361
+ };
362
+ if (!isSolvable(sampledState)) continue;
363
+ return sampledState;
364
+ }
365
+ throw new Error(`${ERROR_PREFIX}: could not sample a solvable Skewb twist after ${MAX_TWIST_ATTEMPTS} attempts`);
366
+ }
367
+ solveIn(state, length, random) {
368
+ return this.solve(state, length, false, random);
369
+ }
370
+ generateExactly(state, length, random) {
371
+ const scramble = this.solve(state, length, true, random);
372
+ if (scramble === null) throw new Error(`${ERROR_PREFIX}: could not generate a Skewb scramble exactly ${length} moves long`);
373
+ return scramble;
374
+ }
375
+ solve(state, desiredLength, exactLength, random) {
376
+ validateState(state);
377
+ validateLength(desiredLength);
378
+ const solution = Array.from({ length: MAX_SOLUTION_LENGTH }, () => 0);
379
+ const tables = getTables();
380
+ let length = exactLength ? desiredLength : 0;
381
+ while (length <= desiredLength) {
382
+ const solutionLength = search({
383
+ perm: state.perm,
384
+ twst: state.twst,
385
+ depth: 0,
386
+ length,
387
+ lastMove: -1,
388
+ solution,
389
+ random,
390
+ tables
391
+ });
392
+ if (solutionLength !== -1) return formatSolution(solution, solutionLength);
393
+ length += 1;
394
+ }
395
+ return null;
396
+ }
397
+ };
398
+ //#endregion
399
+ export { SkewbSolver };
@@ -0,0 +1,212 @@
1
+ import { getShape2Idx, getShapeTables } from "./shape.mjs";
2
+ import { createSquareCoordinate, get8Perm } from "./square.mjs";
3
+ //#region .build/vendor/scramble-core/src/solvers/sq12phase/full-cube.ts
4
+ const ERROR_PREFIX = "@cubegin/scramble-core";
5
+ const SOLVED_UL = 70195;
6
+ const SOLVED_UR = 4544119;
7
+ const SOLVED_DL = 10062778;
8
+ const SOLVED_DR = 14536702;
9
+ const FACE_MASK = 16777215;
10
+ const SQUARE_ONE_TO_FULL_CUBE_PIECE = [
11
+ 3,
12
+ 2,
13
+ 1,
14
+ 0,
15
+ 7,
16
+ 6,
17
+ 5,
18
+ 4,
19
+ 10,
20
+ 11,
21
+ 8,
22
+ 9,
23
+ 14,
24
+ 15,
25
+ 12,
26
+ 13
27
+ ];
28
+ const SQUARE_ONE_TO_FULL_CUBE_POSITION = [
29
+ 5,
30
+ 4,
31
+ 3,
32
+ 2,
33
+ 1,
34
+ 0,
35
+ 11,
36
+ 10,
37
+ 9,
38
+ 8,
39
+ 7,
40
+ 6,
41
+ 17,
42
+ 16,
43
+ 15,
44
+ 14,
45
+ 13,
46
+ 12,
47
+ 23,
48
+ 22,
49
+ 21,
50
+ 20,
51
+ 19,
52
+ 18
53
+ ];
54
+ var FullCube = class FullCube {
55
+ permutationScratch = Array.from({ length: 8 }, () => 0);
56
+ parityScratch = Array.from({ length: 16 }, () => 0);
57
+ ul = SOLVED_UL;
58
+ ur = SOLVED_UR;
59
+ dl = SOLVED_DL;
60
+ dr = SOLVED_DR;
61
+ ml = 0;
62
+ static randomCube(random) {
63
+ const { shapeIdx } = getShapeTables();
64
+ const shape = shapeIdx[drawRandomInt(random, 3678)];
65
+ const cube = new FullCube();
66
+ let corners = 324508639;
67
+ let edges = 38177486;
68
+ let remainingCorners = 8;
69
+ let remainingEdges = 8;
70
+ for (let index = 0; index < 24; index += 1) if ((shape >> index & 1) === 0) {
71
+ const randomEdge = drawRandomInt(random, remainingEdges) << 2;
72
+ cube.setPiece(23 - index, edges >> randomEdge & 15);
73
+ edges = removeNibble(edges, randomEdge);
74
+ remainingEdges -= 1;
75
+ } else {
76
+ const randomCorner = drawRandomInt(random, remainingCorners) << 2;
77
+ const corner = corners >> randomCorner & 15;
78
+ cube.setPiece(23 - index, corner);
79
+ cube.setPiece(22 - index, corner);
80
+ corners = removeNibble(corners, randomCorner);
81
+ remainingCorners -= 1;
82
+ index += 1;
83
+ }
84
+ cube.ml = drawRandomInt(random, 2);
85
+ return cube;
86
+ }
87
+ static fromSquareOneState(state) {
88
+ const cube = new FullCube();
89
+ for (let index = 0; index < 24; index += 1) cube.setPiece(SQUARE_ONE_TO_FULL_CUBE_POSITION[index], SQUARE_ONE_TO_FULL_CUBE_PIECE[state.pieces[index]]);
90
+ cube.setPiece(24, state.sliceSolved ? 0 : 1);
91
+ return cube;
92
+ }
93
+ copy(cube) {
94
+ this.ul = cube.ul;
95
+ this.ur = cube.ur;
96
+ this.dl = cube.dl;
97
+ this.dr = cube.dr;
98
+ this.ml = cube.ml;
99
+ }
100
+ isSolved() {
101
+ return this.ul === SOLVED_UL && this.ur === SOLVED_UR && this.dl === SOLVED_DL && this.dr === SOLVED_DR && this.ml === 0;
102
+ }
103
+ doMove(move) {
104
+ let turn = move << 2;
105
+ if (turn > 24) {
106
+ turn = 48 - turn;
107
+ const oldUl = this.ul;
108
+ this.ul = (this.ul >> turn | this.ur << 24 - turn) & FACE_MASK;
109
+ this.ur = (this.ur >> turn | oldUl << 24 - turn) & FACE_MASK;
110
+ } else if (turn > 0) {
111
+ const oldUl = this.ul;
112
+ this.ul = (this.ul << turn | this.ur >> 24 - turn) & FACE_MASK;
113
+ this.ur = (this.ur << turn | oldUl >> 24 - turn) & FACE_MASK;
114
+ } else if (turn === 0) {
115
+ const oldUr = this.ur;
116
+ this.ur = this.dl;
117
+ this.dl = oldUr;
118
+ this.ml = 1 - this.ml;
119
+ } else if (turn >= -24) {
120
+ turn = -turn;
121
+ const oldDl = this.dl;
122
+ this.dl = (this.dl << turn | this.dr >> 24 - turn) & FACE_MASK;
123
+ this.dr = (this.dr << turn | oldDl >> 24 - turn) & FACE_MASK;
124
+ } else {
125
+ turn = 48 + turn;
126
+ const oldDl = this.dl;
127
+ this.dl = (this.dl >> turn | this.dr << 24 - turn) & FACE_MASK;
128
+ this.dr = (this.dr >> turn | oldDl << 24 - turn) & FACE_MASK;
129
+ }
130
+ }
131
+ setPiece(index, value) {
132
+ if (index < 6) {
133
+ const shift = 5 - index << 2;
134
+ this.ul &= ~(15 << shift);
135
+ this.ul |= value << shift;
136
+ } else if (index < 12) {
137
+ const shift = 11 - index << 2;
138
+ this.ur &= ~(15 << shift);
139
+ this.ur |= value << shift;
140
+ } else if (index < 18) {
141
+ const shift = 17 - index << 2;
142
+ this.dl &= ~(15 << shift);
143
+ this.dl |= value << shift;
144
+ } else if (index < 24) {
145
+ const shift = 23 - index << 2;
146
+ this.dr &= ~(15 << shift);
147
+ this.dr |= value << shift;
148
+ } else this.ml = value;
149
+ }
150
+ getShapeIdx() {
151
+ const urShape = extractShapeBits(this.ur);
152
+ const ulShape = extractShapeBits(this.ul);
153
+ const drShape = extractShapeBits(this.dr);
154
+ const dlShape = extractShapeBits(this.dl);
155
+ return getShape2Idx(this.getParity() << 24 | ulShape << 18 | urShape << 12 | dlShape << 6 | drShape);
156
+ }
157
+ getSquare(square = createSquareCoordinate()) {
158
+ const pieces = this.permutationScratch;
159
+ for (let index = 0; index < 8; index += 1) pieces[index] = this.pieceAt(index * 3 + 1) >> 1;
160
+ square.cornPerm = get8Perm(pieces);
161
+ square.topEdgeFirst = this.pieceAt(0) === this.pieceAt(1);
162
+ let position = square.topEdgeFirst ? 2 : 0;
163
+ let pieceIndex = 0;
164
+ for (; pieceIndex < 4; position += 3, pieceIndex += 1) pieces[pieceIndex] = this.pieceAt(position) >> 1;
165
+ square.botEdgeFirst = this.pieceAt(12) === this.pieceAt(13);
166
+ position = square.botEdgeFirst ? 14 : 12;
167
+ for (; pieceIndex < 8; position += 3, pieceIndex += 1) pieces[pieceIndex] = this.pieceAt(position) >> 1;
168
+ square.edgePerm = get8Perm(pieces);
169
+ square.ml = this.ml;
170
+ return square;
171
+ }
172
+ pieceAt(index) {
173
+ let piece;
174
+ if (index < 6) piece = this.ul >> (5 - index << 2);
175
+ else if (index < 12) piece = this.ur >> (11 - index << 2);
176
+ else if (index < 18) piece = this.dl >> (17 - index << 2);
177
+ else piece = this.dr >> (23 - index << 2);
178
+ return piece & 15;
179
+ }
180
+ getParity() {
181
+ const pieces = this.parityScratch;
182
+ let pieceCount = 0;
183
+ pieces[0] = this.pieceAt(0);
184
+ for (let index = 1; index < 24; index += 1) {
185
+ const piece = this.pieceAt(index);
186
+ if (piece !== pieces[pieceCount]) {
187
+ pieceCount += 1;
188
+ pieces[pieceCount] = piece;
189
+ }
190
+ }
191
+ let parity = 0;
192
+ for (let first = 0; first < 16; first += 1) for (let second = first + 1; second < 16; second += 1) if (pieces[first] > pieces[second]) parity ^= 1;
193
+ return parity;
194
+ }
195
+ };
196
+ const extractShapeBits = (face) => {
197
+ let shape = face & 1118481;
198
+ shape |= shape >> 3;
199
+ shape |= shape >> 6;
200
+ return shape & 15 | shape >> 12 & 48;
201
+ };
202
+ const removeNibble = (value, shift) => {
203
+ const mask = (1 << shift) - 1;
204
+ return (value & mask) + (value >> 4 & ~mask);
205
+ };
206
+ const drawRandomInt = (random, maxExclusive) => {
207
+ const value = random.nextInt(maxExclusive);
208
+ if (!Number.isSafeInteger(value) || value < 0 || value >= maxExclusive) throw new RangeError(`${ERROR_PREFIX}: Square-1 random source returned ${value} for max ${maxExclusive}`);
209
+ return value;
210
+ };
211
+ //#endregion
212
+ export { FullCube };