aboutsummaryrefslogtreecommitdiff
path: root/src/solvers
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2025-08-05 09:04:00 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2025-08-05 09:04:00 +0200
commit3e7bb9b87ef9b47d8f643dbcae19a64ddbc81dbb (patch)
tree122faba06273ae0450a2994e22bad42202f11da7 /src/solvers
parentf6efc882a279cddb624fe2f2470797561a6997b8 (diff)
downloadnissy-core-3e7bb9b87ef9b47d8f643dbcae19a64ddbc81dbb.tar.gz
nissy-core-3e7bb9b87ef9b47d8f643dbcae19a64ddbc81dbb.zip
Added DRFIN solver
Diffstat (limited to 'src/solvers')
-rw-r--r--src/solvers/coord/checkdata.h75
-rw-r--r--src/solvers/coord/common.h15
-rw-r--r--src/solvers/coord/coord.h3
-rw-r--r--src/solvers/coord/cpepe.h36
-rw-r--r--src/solvers/coord/drfin.h17
-rw-r--r--src/solvers/coord/gendata.h66
-rw-r--r--src/solvers/coord/list.h6
-rw-r--r--src/solvers/coord/multisolve.h298
-rw-r--r--src/solvers/coord/solve.h18
-rw-r--r--src/solvers/coord/types_macros.h9
-rw-r--r--src/solvers/coord/utils.h53
-rw-r--r--src/solvers/dispatch.h9
-rw-r--r--src/solvers/tables.h12
-rw-r--r--src/solvers/tables_types_macros.h1
14 files changed, 543 insertions, 75 deletions
diff --git a/src/solvers/coord/checkdata.h b/src/solvers/coord/checkdata.h
index e448e8f..51265a8 100644
--- a/src/solvers/coord/checkdata.h
+++ b/src/solvers/coord/checkdata.h
@@ -1,14 +1,39 @@
1STATIC long long checkdata_coord( 1STATIC long long checkdata_coord_dispatch(
2 const char *, unsigned long long, const unsigned char *); 2 const char *, unsigned long long, const unsigned char *);
3STATIC long long checkdata_coord(
4 const coord_t *, unsigned long long, const unsigned char *);
5STATIC long long checkdata_multicoord(
6 const multicoord_t *, unsigned long long, const unsigned char *);
3 7
4STATIC long long 8STATIC long long
5checkdata_coord( 9checkdata_coord_dispatch(
6 const char *solver, 10 const char *solver,
7 unsigned long long data_size, 11 unsigned long long data_size,
8 const unsigned char *data 12 const unsigned char *data
9) 13)
10{ 14{
11 coord_t *coord; 15 coord_t *c;
16 multicoord_t *mc;
17
18 parse_coord_and_trans(solver, &c, &mc, NULL);
19
20 if (c != NULL)
21 return checkdata_coord(c, data_size, data);
22
23 if (mc != NULL)
24 return checkdata_multicoord(mc, data_size, data);
25
26 LOG("[cehckdata] Unknown coordinate solver '%s'\n", solver);
27 return NISSY_ERROR_DATA;
28}
29
30STATIC long long
31checkdata_coord(
32 const coord_t *coord,
33 unsigned long long data_size,
34 const unsigned char *data
35)
36{
12 const unsigned char *table; 37 const unsigned char *table;
13 tableinfo_t info; 38 tableinfo_t info;
14 int64_t err; 39 int64_t err;
@@ -19,12 +44,6 @@ checkdata_coord(
19 return NISSY_ERROR_DATA; 44 return NISSY_ERROR_DATA;
20 } 45 }
21 46
22 parse_coord_and_trans(solver, &coord, NULL);
23 if (coord == NULL) {
24 LOG("[cehckdata] Unknown coordinate solver '%s'\n", solver);
25 return NISSY_ERROR_DATA;
26 }
27
28 table = data + INFOSIZE; 47 table = data + INFOSIZE;
29 err = readtableinfo(data_size, data, &info); 48 err = readtableinfo(data_size, data, &info);
30 if (err != NISSY_OK) { 49 if (err != NISSY_OK) {
@@ -63,3 +82,41 @@ checkdata_coord(
63 82
64 return NISSY_OK; 83 return NISSY_OK;
65} 84}
85
86STATIC long long
87checkdata_multicoord(
88 const multicoord_t *mcoord,
89 unsigned long long data_size,
90 const unsigned char *data
91)
92{
93 long long r;
94 size_t i, of, s;
95
96 for (of = INFOSIZE, i = 0; mcoord->coordinates[i] != NULL; i++) {
97 LOG("[checkdata] %s: checking data for %s\n", mcoord->name,
98 mcoord->coordinates[i]->name);
99 s = gendata_coord(mcoord->coordinates[i], NULL);
100 if (s > data_size-of)
101 return NISSY_ERROR_DATA;
102
103 r = checkdata_coord(mcoord->coordinates[i], s, data + of);
104 if (r != NISSY_OK)
105 return r;
106
107 LOG("[checkdata] Ok\n");
108
109 of += s;
110
111 /* Skip padding */
112 while (of % 8 != 0) {
113 if (data[of] != 0)
114 LOG("[checkdata] Warning: some unused bytes "
115 "are not set to zero. Please report this "
116 "bug.\n");
117 of++;
118 }
119 }
120
121 return NISSY_OK;
122}
diff --git a/src/solvers/coord/common.h b/src/solvers/coord/common.h
index 901b8bd..5b5f57b 100644
--- a/src/solvers/coord/common.h
+++ b/src/solvers/coord/common.h
@@ -6,7 +6,6 @@ STATIC bool coord_isnasty_generic(
6 const coord_t [static 1], uint64_t, const unsigned char *); 6 const coord_t [static 1], uint64_t, const unsigned char *);
7STATIC size_t coord_gendata_generic(const coord_t [static 1], unsigned char *); 7STATIC size_t coord_gendata_generic(const coord_t [static 1], unsigned char *);
8 8
9STATIC void append_coord_name(const coord_t [static 1], char *);
10STATIC bool solution_lastqt_cw(const solution_moves_t [static 1]); 9STATIC bool solution_lastqt_cw(const solution_moves_t [static 1]);
11STATIC bool coord_can_switch(const coord_t [static 1], const unsigned char *, 10STATIC bool coord_can_switch(const coord_t [static 1], const unsigned char *,
12 size_t, const uint8_t *); 11 size_t, const uint8_t *);
@@ -106,7 +105,7 @@ coord_gendata_generic(
106 .maxvalue = 0, 105 .maxvalue = 0,
107 .next = 0 106 .next = 0
108 }; 107 };
109 append_coord_name(coord, info.solver); 108 append_name(&info, coord->name);
110 109
111 for (i = 0, n = 0; i < coord->sym.max; i++) { 110 for (i = 0, n = 0; i < coord->sym.max; i++) {
112 if (classttrep[i] != 0xFFFFFFFF) 111 if (classttrep[i] != 0xFFFFFFFF)
@@ -142,18 +141,6 @@ coord_gendata_generic(
142 return coord_datasize; 141 return coord_datasize;
143} 142}
144 143
145STATIC void
146append_coord_name(const coord_t coord[static 1], char *str)
147{
148 int i, j;
149
150 i = 0;
151 j = strlen(str);
152 while (coord->name[i]) str[j++] = coord->name[i++];
153
154 str[j] = '\0';
155}
156
157STATIC bool 144STATIC bool
158solution_lastqt_cw(const solution_moves_t s[static 1]) 145solution_lastqt_cw(const solution_moves_t s[static 1])
159{ 146{
diff --git a/src/solvers/coord/coord.h b/src/solvers/coord/coord.h
index 3b42e31..beb1b6a 100644
--- a/src/solvers/coord/coord.h
+++ b/src/solvers/coord/coord.h
@@ -5,8 +5,11 @@
5#include "dreo.h" 5#include "dreo.h"
6#include "drfinnoe.h" 6#include "drfinnoe.h"
7#include "drslice.h" 7#include "drslice.h"
8#include "cpepe.h"
9#include "drfin.h"
8#include "list.h" 10#include "list.h"
9#include "utils.h" 11#include "utils.h"
10#include "gendata.h" 12#include "gendata.h"
11#include "checkdata.h" 13#include "checkdata.h"
12#include "solve.h" 14#include "solve.h"
15#include "multisolve.h"
diff --git a/src/solvers/coord/cpepe.h b/src/solvers/coord/cpepe.h
index 37ec014..9c9bffc 100644
--- a/src/solvers/coord/cpepe.h
+++ b/src/solvers/coord/cpepe.h
@@ -15,29 +15,27 @@ STATIC coord_t coordinate_cpepe = {
15 .moves_mask_gendata = MM18_DR, 15 .moves_mask_gendata = MM18_DR,
16 .moves_mask_solve = MM18_DR, 16 .moves_mask_solve = MM18_DR,
17 .is_admissible = &solution_always_valid, 17 .is_admissible = &solution_always_valid,
18 .is_solvable = &is_drfin_solvable, 18 .is_solvable = &is_drfinnoe_solvable,
19 .is_solved = NULL, 19 .is_solved = NULL,
20 .allow_niss = false, 20 .allow_niss = false,
21 .pruning_distribution = { 21 .pruning_distribution = {
22 /* TODO */ 22 [0] = 1,
23 [0] = 0, 23 [1] = 3,
24 [1] = 0, 24 [2] = 10,
25 [2] = 0, 25 [3] = 44,
26 [3] = 0, 26 [4] = 214,
27 [4] = 0, 27 [5] = 846,
28 [5] = 0, 28 [6] = 2413,
29 [6] = 0, 29 [7] = 5122,
30 [7] = 0, 30 [8] = 8639,
31 [8] = 0, 31 [9] = 12128,
32 [9] = 0, 32 [10] = 12571,
33 [10] = 0, 33 [11] = 12985,
34 [11] = 0, 34 [12] = 7754,
35 [12] = 0, 35 [13] = 3366,
36 [13] = 0, 36 [14] = 336,
37 [14] = 0,
38 [15] = 0,
39 }, 37 },
40 .pruning_max = 15, /* TODO */ 38 .pruning_max = 14,
41 .sym = { 39 .sym = {
42 .classes = CLASSES_CP_16, 40 .classes = CLASSES_CP_16,
43 .max = FACT_8, 41 .max = FACT_8,
diff --git a/src/solvers/coord/drfin.h b/src/solvers/coord/drfin.h
new file mode 100644
index 0000000..569419b
--- /dev/null
+++ b/src/solvers/coord/drfin.h
@@ -0,0 +1,17 @@
1STATIC bool is_drfin_solvable(cube_t);
2
3STATIC multicoord_t multicoordinate_drfin = {
4 .name = "DRFIN",
5 .coordinates = { &coordinate_cpepe, &coordinate_drfinnoe, NULL },
6 .moves_mask = MM18_DR,
7 .is_solvable = is_drfin_solvable,
8};
9
10STATIC bool
11is_drfin_solvable(cube_t cube)
12{
13 return coord_eo(cube) == 0 &&
14 coord_eo(transform_edges(cube, TRANS_URr)) == 0 &&
15 coord_co(cube) == 0 &&
16 issolvable((oriented_cube_t){.cube = cube, .orientation = 0});
17}
diff --git a/src/solvers/coord/gendata.h b/src/solvers/coord/gendata.h
index 0b108cd..cbc8774 100644
--- a/src/solvers/coord/gendata.h
+++ b/src/solvers/coord/gendata.h
@@ -1,4 +1,6 @@
1STATIC size_t gendata_coord(const coord_t [static 1], unsigned char *); 1STATIC size_t gendata_coord(const coord_t [static 1], unsigned char *);
2STATIC size_t gendata_multicoord(
3 const multicoord_t [static 1], unsigned char *);
2STATIC long long gendata_coord_dispatch(const char *, unsigned long long, 4STATIC long long gendata_coord_dispatch(const char *, unsigned long long,
3 unsigned char *); 5 unsigned char *);
4STATIC tableinfo_t genptable_coord( 6STATIC tableinfo_t genptable_coord(
@@ -23,15 +25,18 @@ gendata_coord_dispatch(
23) 25)
24{ 26{
25 coord_t *coord; 27 coord_t *coord;
28 multicoord_t *mcoord;
26 29
27 parse_coord_and_trans(coordstr, &coord, NULL); 30 parse_coord_and_trans(coordstr, &coord, &mcoord, NULL);
28 31
29 if (coord == NULL) { 32 if (coord != NULL)
30 LOG("Error: could not parse coordinate '%s'\n", coordstr); 33 return gendata_coord(coord, buf);
31 return NISSY_ERROR_INVALID_SOLVER; 34
32 } 35 if (mcoord != NULL)
36 return gendata_multicoord(mcoord, buf);
33 37
34 return gendata_coord(coord, buf); 38 LOG("Error: could not parse coordinate '%s'\n", coordstr);
39 return NISSY_ERROR_INVALID_SOLVER;
35} 40}
36 41
37STATIC size_t 42STATIC size_t
@@ -70,8 +75,7 @@ gendata_coord(const coord_t coord[static 1], unsigned char *buf)
70 .maxvalue = 0, 75 .maxvalue = 0,
71 }; 76 };
72 77
73 append_coord_name(coord, coord_data_info.solver); 78 append_name(&coord_data_info, coord->name);
74
75 writetableinfo(&coord_data_info, INFOSIZE + coord_dsize, buf); 79 writetableinfo(&coord_data_info, INFOSIZE + coord_dsize, buf);
76 80
77 pruningbuf = buf + INFOSIZE + coord_dsize; 81 pruningbuf = buf + INFOSIZE + coord_dsize;
@@ -91,6 +95,50 @@ gendata_coord_error:
91 return 0; 95 return 0;
92} 96}
93 97
98STATIC size_t
99gendata_multicoord(const multicoord_t mcoord[static 1], unsigned char *buf)
100{
101 unsigned char *b;
102 size_t i, s, ret;
103 tableinfo_t info;
104
105 info = (tableinfo_t) {
106 .solver = "multicoordinate table for ",
107 .type = TABLETYPE_MULTI,
108 .infosize = INFOSIZE,
109 .fullsize = INFOSIZE,
110 .hash = 0,
111 .next = INFOSIZE,
112
113 /* Unknown / non-applicable values */
114 .entries = 0,
115 .classes = 0,
116 .bits = 0,
117 .base = 0,
118 .maxvalue = 0,
119 };
120
121 append_name(&info, mcoord->name);
122 if (buf != NULL)
123 writetableinfo(&info, INFOSIZE, buf);
124 ret = INFOSIZE;
125
126 for (i = 0; mcoord->coordinates[i] != NULL; i++) {
127 b = buf == NULL ? NULL : buf + ret;
128 s = gendata_coord(mcoord->coordinates[i], b);
129 if (s == 0)
130 return 0;
131
132 ret += s;
133
134 /* Pad so that each coordinate's table is 8-byte aligned */
135 while (ret % 8 != 0)
136 buf[ret++] = 0;
137 }
138
139 return ret;
140}
141
94STATIC tableinfo_t 142STATIC tableinfo_t
95genptable_coord( 143genptable_coord(
96 const coord_t coord[static 1], 144 const coord_t coord[static 1],
@@ -118,7 +166,7 @@ genptable_coord(
118 166
119 memset(table, 0xFF, tablesize); 167 memset(table, 0xFF, tablesize);
120 memset(info.distribution, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); 168 memset(info.distribution, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t));
121 append_coord_name(coord, info.solver); 169 append_name(&info, coord->name);
122 170
123 tot = info.distribution[0] = 171 tot = info.distribution[0] =
124 genptable_coord_init_solved(coord, data, table); 172 genptable_coord_init_solved(coord, data, table);
diff --git a/src/solvers/coord/list.h b/src/solvers/coord/list.h
index 929e0fd..7bc8041 100644
--- a/src/solvers/coord/list.h
+++ b/src/solvers/coord/list.h
@@ -4,5 +4,11 @@ coord_t *all_coordinates[] = {
4 &coordinate_dreo, 4 &coordinate_dreo,
5 &coordinate_drfinnoe, 5 &coordinate_drfinnoe,
6 &coordinate_drslice, 6 &coordinate_drslice,
7 &coordinate_cpepe,
8 NULL
9};
10
11multicoord_t *all_multicoordinates[] = {
12 &multicoordinate_drfin,
7 NULL 13 NULL
8}; 14};
diff --git a/src/solvers/coord/multisolve.h b/src/solvers/coord/multisolve.h
new file mode 100644
index 0000000..f3589e8
--- /dev/null
+++ b/src/solvers/coord/multisolve.h
@@ -0,0 +1,298 @@
1/*
2For now the only multicoordinate is DRFIN, and this solver reflects this.
3For example, NISS is not available.
4*/
5
6typedef struct {
7 cube_t cube;
8 cube_t inverse;
9 uint8_t target_depth;
10 solution_moves_t *solution_moves;
11 solution_settings_t *solution_settings;
12 solution_list_t *solution_list;
13 multicoord_t *mcoord;
14 const unsigned char *coord_data[MAX_MULTICOORD_NCOORDS];
15 const unsigned char *ptable[MAX_MULTICOORD_NCOORDS];
16} dfsarg_solve_multicoord_t;
17
18STATIC int64_t solve_multicoord(oriented_cube_t, multicoord_t [static 1],
19 uint8_t, uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t,
20 const unsigned char *, size_t, char *, int (*)(void *), void *);
21STATIC long long solve_multicoord_dispatch(oriented_cube_t, const char *,
22 unsigned, unsigned, unsigned, unsigned, unsigned, unsigned,
23 unsigned long long, const unsigned char *, unsigned, char *,
24 long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *);
25STATIC bool multicoord_solution_admissible(
26 const dfsarg_solve_multicoord_t [static 1]);
27STATIC bool multicoord_dfs_stop(const dfsarg_solve_multicoord_t [static 1]);
28STATIC int64_t solve_multicoord_dfs(dfsarg_solve_multicoord_t [static 1]);
29
30STATIC bool
31multicoord_solution_admissible(const dfsarg_solve_multicoord_t arg[static 1])
32{
33 uint8_t n, i;
34 const coord_t *c;
35
36 n = arg->solution_moves->nmoves + arg->solution_moves->npremoves;
37 if (arg->target_depth != n)
38 return false;
39
40 for (i = 0; arg->mcoord->coordinates[i] != NULL; i++) {
41 c = arg->mcoord->coordinates[i];
42 if (c->is_admissible != NULL &&
43 !c->is_admissible(arg->solution_moves))
44 return false;
45 }
46
47 return true;
48}
49
50STATIC bool
51multicoord_dfs_stop(const dfsarg_solve_multicoord_t arg[static 1])
52{
53 uint8_t pval, i;
54 uint64_t cval;
55 const coord_t *c;
56
57 for (i = 0, pval = 0; arg->mcoord->coordinates[i] != NULL; i++) {
58 c = arg->mcoord->coordinates[i];
59
60 cval = c->coord(arg->cube, arg->coord_data[i]);
61 pval = MAX(pval, get_coord_pval(c, arg->ptable[i], cval));
62
63 cval = c->coord(arg->inverse, arg->coord_data[i]);
64 pval = MAX(pval, get_coord_pval(c, arg->ptable[i], cval));
65 }
66
67 return arg->solution_moves->nmoves + pval > arg->target_depth;
68}
69
70STATIC int64_t
71solve_multicoord_dfs(dfsarg_solve_multicoord_t arg[static 1])
72{
73 uint8_t m, l, i;
74 uint32_t mm;
75 uint64_t coord;
76 int64_t n, ret;
77 const coord_t *c;
78 cube_t backup_cube, backup_inverse;
79
80 for (i = 0; arg->mcoord->coordinates[i] != NULL; i++) {
81 c = arg->mcoord->coordinates[i];
82 coord = c->coord(arg->cube, arg->coord_data[i]);
83 if (!coord_is_solved(c, coord, arg->coord_data[i]))
84 goto solve_multicoord_dfs_notsolved;
85 }
86
87 /* All coordinates are solved */
88 if (!multicoord_solution_admissible(arg))
89 return 0;
90 return appendsolution(arg->solution_moves,
91 arg->solution_settings, arg->solution_list);
92
93solve_multicoord_dfs_notsolved:
94 if (multicoord_dfs_stop(arg))
95 return 0;
96
97 backup_cube = arg->cube;
98 backup_inverse = arg->inverse;
99 ret = 0;
100
101 l = arg->solution_moves->nmoves;
102 mm = arg->mcoord->moves_mask;
103 if (l != 0) {
104 m = arg->solution_moves->moves[l-1];
105 mm &= allowedmask[movebase(m)];
106 }
107 arg->solution_moves->nmoves++;
108
109 for (m = 0; m < NMOVES; m++) {
110 if (!(mm & (UINT32_C(1) << (uint32_t)m)))
111 continue;
112
113 arg->solution_moves->moves[l] = m;
114 arg->cube = move(backup_cube, m);
115 arg->inverse = premove(backup_inverse, m);
116 n = solve_multicoord_dfs(arg);
117 if (n < 0)
118 return n;
119 ret += n;
120 }
121
122 arg->solution_moves->nmoves--;
123 arg->cube = backup_cube;
124 arg->inverse = backup_inverse;
125
126 return ret;
127}
128
129STATIC long long
130solve_multicoord_dispatch(
131 oriented_cube_t oc,
132 const char *coord_and_trans,
133 unsigned nissflag,
134 unsigned minmoves,
135 unsigned maxmoves,
136 unsigned maxsolutions,
137 unsigned optimal,
138 unsigned threads,
139 unsigned long long data_size,
140 const unsigned char *data,
141 unsigned solutions_size,
142 char *sols,
143 long long stats[static NISSY_SIZE_SOLVE_STATS],
144 int (*poll_status)(void *),
145 void *poll_status_data
146)
147{
148 multicoord_t *mcoord;
149 uint8_t trans;
150
151 parse_coord_and_trans(coord_and_trans, NULL, &mcoord, &trans);
152
153 if (mcoord == NULL) {
154 LOG("Error: could not parse coordinate from '%s'\n",
155 coord_and_trans);
156 return NISSY_ERROR_INVALID_SOLVER;
157 }
158
159 if (trans == UINT8_ERROR) {
160 LOG("Error: could not parse transformation from '%s'\n",
161 coord_and_trans);
162 return NISSY_ERROR_INVALID_SOLVER;
163 }
164
165 return solve_multicoord(oc, mcoord, trans, minmoves,
166 maxmoves, maxsolutions, optimal, threads, data_size, data,
167 solutions_size, sols, poll_status, poll_status_data);
168}
169
170STATIC int64_t
171solve_multicoord(
172 oriented_cube_t oc,
173 multicoord_t mcoord [static 1],
174 uint8_t trans,
175 uint8_t minmoves,
176 uint8_t maxmoves,
177 uint64_t maxsolutions,
178 uint8_t optimal,
179 uint8_t threads,
180 uint64_t data_size,
181 const unsigned char *data,
182 size_t solutions_size,
183 char *sols,
184 int (*poll_status)(void *),
185 void *poll_status_data
186)
187{
188 int8_t d;
189 size_t j, of;
190 uint64_t i;
191 int64_t err;
192 cube_t c;
193 const coord_t *coord;
194 dfsarg_solve_multicoord_t arg;
195 tableinfo_t info;
196 solution_moves_t solution_moves;
197 solution_settings_t solution_settings;
198 solution_list_t solution_list;
199
200 c = transform(oc.cube, trans);
201
202 if (!mcoord->is_solvable(c))
203 goto solve_multicoord_error_unsolvable;
204
205 if (!solution_list_init(&solution_list, solutions_size, sols))
206 goto solve_multicoord_error_buffer;
207
208 solution_moves_reset(&solution_moves);
209
210 solution_settings = (solution_settings_t) {
211 .tmask = TM_SINGLE(inverse_trans(trans)),
212 .unniss = false,
213 .maxmoves = maxmoves,
214 .maxsolutions = maxsolutions,
215 .optimal = optimal,
216 .orientation = oc.orientation,
217 };
218
219 arg = (dfsarg_solve_multicoord_t) {
220 .cube = c,
221 .inverse = inverse(c),
222 .mcoord = mcoord,
223 .solution_moves = &solution_moves,
224 .solution_settings = &solution_settings,
225 .solution_list = &solution_list,
226 };
227
228 for (j = 0, of = INFOSIZE; mcoord->coordinates[j] != NULL; j++) {
229 if (readtableinfo(data_size-of, data+of, &info) != NISSY_OK)
230 goto solve_multicoord_error_data;
231
232 if (info.type == TABLETYPE_PRUNING) {
233 /* Only the pruning table */
234 arg.coord_data[j] = NULL;
235 arg.ptable[j] = data + of + INFOSIZE;
236 of += info.fullsize;
237 } else {
238 /* Coordinate has extra data */
239 arg.coord_data[j] = data + of + INFOSIZE;
240 arg.ptable[j] = data + of + info.next + INFOSIZE;
241 of += info.fullsize;
242 if (readtableinfo(data_size-of, data+of, &info)
243 != NISSY_OK)
244 goto solve_multicoord_error_data;
245 of += info.fullsize;
246 }
247
248 /* Skip padding */
249 while (of % 8 != 0)
250 of++;
251 }
252
253 for (j = 0; mcoord->coordinates[j] != NULL; j++) {
254 coord = mcoord->coordinates[j];
255 i = coord->coord(c, arg.coord_data[j]);
256 if (!coord_is_solved(coord, i, arg.coord_data[j]))
257 goto solve_multicoord_notsolved;
258 }
259
260 /* All coordinates are solved */
261 if (minmoves == 0 && !appendsolution(&solution_moves,
262 &solution_settings, &solution_list))
263 goto solve_multicoord_error_buffer;
264 goto solve_multicoord_done;
265
266solve_multicoord_notsolved:
267 for (
268 d = MAX(minmoves, 1);
269 !solutions_done(&solution_list, &solution_settings, d);
270 d++
271 ) {
272 if (d >= 12)
273 LOG("[%s solve] Found %" PRIu64 " solutions, "
274 "searching at depth %" PRId8 "\n",
275 mcoord->name, solution_list.nsols, d);
276
277 arg.target_depth = d;
278 solution_moves_reset(arg.solution_moves);
279 if ((err = solve_multicoord_dfs(&arg)) < 0)
280 return err;
281 }
282
283solve_multicoord_done:
284 return (int64_t)solution_list.nsols;
285
286solve_multicoord_error_data:
287 LOG("[%s solve] Error reading table\n", mcoord->name);
288 return NISSY_ERROR_DATA;
289
290solve_multicoord_error_buffer:
291 LOG("[%s solve] Error appending solution to buffer: size too small\n",
292 mcoord->name);
293 return NISSY_ERROR_BUFFER_SIZE;
294
295solve_multicoord_error_unsolvable:
296 LOG("[%s solve] Error: cube not ready\n", mcoord->name);
297 return NISSY_ERROR_UNSOLVABLE_CUBE;
298}
diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h
index f9ee06e..72bc064 100644
--- a/src/solvers/coord/solve.h
+++ b/src/solvers/coord/solve.h
@@ -52,10 +52,6 @@ coord_continue_onnormal(const dfsarg_solve_coord_t arg[static 1])
52 /* If only inverse moves are allowed */ 52 /* If only inverse moves are allowed */
53 if (flag == NISSY_NISSFLAG_INVERSE) 53 if (flag == NISSY_NISSFLAG_INVERSE)
54 return false; 54 return false;
55
56 /* It's the first move */
57 if (nn + ni == 0)
58 return true;
59 55
60 /* Pruning table check */ 56 /* Pruning table check */
61 if (!(flag & NISSY_NISSFLAG_MIXED) || ni != 0) { 57 if (!(flag & NISSY_NISSFLAG_MIXED) || ni != 0) {
@@ -64,6 +60,10 @@ coord_continue_onnormal(const dfsarg_solve_coord_t arg[static 1])
64 if (nn + ni + pval > arg->target_depth) 60 if (nn + ni + pval > arg->target_depth)
65 return false; 61 return false;
66 } 62 }
63
64 /* It's the first move */
65 if (nn + ni == 0)
66 return true;
67 67
68 if (arg->lastisnormal) { 68 if (arg->lastisnormal) {
69 /* Can continue if we have already switched */ 69 /* Can continue if we have already switched */
@@ -106,10 +106,6 @@ coord_continue_oninverse(const dfsarg_solve_coord_t arg[static 1])
106 /* If only normal moves are allowed */ 106 /* If only normal moves are allowed */
107 if (flag == NISSY_NISSFLAG_NORMAL) 107 if (flag == NISSY_NISSFLAG_NORMAL)
108 return false; 108 return false;
109
110 /* It's the first move */
111 if (nn + ni == 0)
112 return true;
113 109
114 /* Pruning table check */ 110 /* Pruning table check */
115 if (!(flag & NISSY_NISSFLAG_MIXED) || nn != 0) { 111 if (!(flag & NISSY_NISSFLAG_MIXED) || nn != 0) {
@@ -118,6 +114,10 @@ coord_continue_oninverse(const dfsarg_solve_coord_t arg[static 1])
118 if (nn + ni + pval > arg->target_depth) 114 if (nn + ni + pval > arg->target_depth)
119 return false; 115 return false;
120 } 116 }
117
118 /* It's the first move */
119 if (nn + ni == 0)
120 return true;
121 121
122 if (!arg->lastisnormal) { 122 if (!arg->lastisnormal) {
123 /* Can continue if we have already switched */ 123 /* Can continue if we have already switched */
@@ -261,7 +261,7 @@ solve_coord_dispatch(
261 coord_t *coord; 261 coord_t *coord;
262 uint8_t trans; 262 uint8_t trans;
263 263
264 parse_coord_and_trans(coord_and_trans, &coord, &trans); 264 parse_coord_and_trans(coord_and_trans, &coord, NULL, &trans);
265 265
266 if (coord == NULL) { 266 if (coord == NULL) {
267 LOG("Error: could not parse coordinate from '%s'\n", 267 LOG("Error: could not parse coordinate from '%s'\n",
diff --git a/src/solvers/coord/types_macros.h b/src/solvers/coord/types_macros.h
index f36ecaf..73484ba 100644
--- a/src/solvers/coord/types_macros.h
+++ b/src/solvers/coord/types_macros.h
@@ -14,6 +14,8 @@
14#define COORD_ISNASTY_MASK (UINT32_C(0xFF) << COORD_ISNASTY_SHIFT) 14#define COORD_ISNASTY_MASK (UINT32_C(0xFF) << COORD_ISNASTY_SHIFT)
15#define COORD_ISNASTY(d) (((d) & COORD_ISNASTY_MASK) >> COORD_ISNASTY_SHIFT) 15#define COORD_ISNASTY(d) (((d) & COORD_ISNASTY_MASK) >> COORD_ISNASTY_SHIFT)
16 16
17#define MAX_MULTICOORD_NCOORDS 4
18
17typedef struct { 19typedef struct {
18 const char name[255]; 20 const char name[255];
19 uint64_t (*coord)(cube_t, const unsigned char *); 21 uint64_t (*coord)(cube_t, const unsigned char *);
@@ -42,3 +44,10 @@ typedef struct {
42 cube_t (*merge)(cube_t, cube_t); 44 cube_t (*merge)(cube_t, cube_t);
43 } sym; 45 } sym;
44} coord_t; 46} coord_t;
47
48typedef struct {
49 const char name[255];
50 coord_t *coordinates[MAX_MULTICOORD_NCOORDS];
51 uint64_t moves_mask;
52 bool (*is_solvable)(cube_t);
53} multicoord_t;
diff --git a/src/solvers/coord/utils.h b/src/solvers/coord/utils.h
index 93704cc..c8a9338 100644
--- a/src/solvers/coord/utils.h
+++ b/src/solvers/coord/utils.h
@@ -1,19 +1,35 @@
1STATIC coord_t *parse_coord(size_t, const char *); 1STATIC coord_t *parse_coord(size_t, const char *);
2STATIC void parse_coord_and_trans(const char *, coord_t **, uint8_t *); 2STATIC multicoord_t *parse_multicoord(size_t, const char *);
3STATIC void parse_coord_and_trans(
4 const char *, coord_t **, multicoord_t **, uint8_t *);
3STATIC long long dataid_coord(const char *, char [static NISSY_SIZE_DATAID]); 5STATIC long long dataid_coord(const char *, char [static NISSY_SIZE_DATAID]);
4 6
5STATIC coord_t * 7STATIC coord_t *
6parse_coord(size_t n, const char *coord) 8parse_coord(size_t n, const char *coord)
7{ 9{
8 int i; 10 int i;
11 const char *name;
9 12
10 /* 13 for (i = 0; all_coordinates[i] != NULL; i++) {
11 TODO Some coordinates are parsed incorrectly, e.g. DRFINNOE 14 name = all_coordinates[i]->name;
12 TODO is matched by DRFIN. Check that strncmp is used correctly. 15 if (n == strlen(name) && !strncmp(name, coord, n))
13 */
14 for (i = 0; all_coordinates[i] != NULL; i++)
15 if (!strncmp(all_coordinates[i]->name, coord, n))
16 return all_coordinates[i]; 16 return all_coordinates[i];
17 }
18
19 return NULL;
20}
21
22STATIC multicoord_t *
23parse_multicoord(size_t n, const char *coord)
24{
25 int i;
26 const char *name;
27
28 for (i = 0; all_multicoordinates[i] != NULL; i++) {
29 name = all_multicoordinates[i]->name;
30 if (n == strlen(name) && !strncmp(name, coord, n))
31 return all_multicoordinates[i];
32 }
17 33
18 return NULL; 34 return NULL;
19} 35}
@@ -22,18 +38,22 @@ STATIC void
22parse_coord_and_trans( 38parse_coord_and_trans(
23 const char *str, 39 const char *str,
24 coord_t **coord, 40 coord_t **coord,
41 multicoord_t **mcoord,
25 uint8_t *trans 42 uint8_t *trans
26) 43)
27{ 44{
28 size_t i; 45 size_t i;
29 46
30 for (i = 6; i < strlen(str); i++) 47 for (i = 7; i < strlen(str); i++)
31 if (str[i] == '_') 48 if (str[i] == '_')
32 break; 49 break;
33 50
34 if (coord != NULL) 51 if (coord != NULL)
35 *coord = parse_coord(i-6, str+6); 52 *coord = parse_coord(i-6, str+6);
36 53
54 if (mcoord != NULL)
55 *mcoord = parse_multicoord(i-7, str+7);
56
37 if (trans != NULL) 57 if (trans != NULL)
38 *trans = i == strlen(str) ? 58 *trans = i == strlen(str) ?
39 UINT8_ERROR : readrotation(str+i+1); 59 UINT8_ERROR : readrotation(str+i+1);
@@ -43,15 +63,20 @@ STATIC long long
43dataid_coord(const char *ca, char dataid[static NISSY_SIZE_DATAID]) 63dataid_coord(const char *ca, char dataid[static NISSY_SIZE_DATAID])
44{ 64{
45 coord_t *c; 65 coord_t *c;
66 multicoord_t *mc;
46 67
47 parse_coord_and_trans(ca, &c, NULL); 68 parse_coord_and_trans(ca, &c, &mc, NULL);
48 69
49 if (c == NULL) { 70 if (c != NULL) {
50 LOG("Error: cannot parse coordinate from '%s'\n", ca); 71 strcpy(dataid, c->name);
51 return NISSY_ERROR_INVALID_SOLVER; 72 return NISSY_OK;
52 } 73 }
53 74
54 strcpy(dataid, c->name); 75 if (mc != NULL) {
76 strcpy(dataid, mc->name);
77 return NISSY_OK;
78 }
55 79
56 return NISSY_OK; 80 LOG("Error: cannot parse coordinate from '%s'\n", ca);
81 return NISSY_ERROR_INVALID_SOLVER;
57} 82}
diff --git a/src/solvers/dispatch.h b/src/solvers/dispatch.h
index 484983e..013468c 100644
--- a/src/solvers/dispatch.h
+++ b/src/solvers/dispatch.h
@@ -26,10 +26,17 @@ solver_dispatch_t solver_dispatchers[] = {
26 .prefix = "coord_", 26 .prefix = "coord_",
27 .dataid = dataid_coord, 27 .dataid = dataid_coord,
28 .gendata = gendata_coord_dispatch, 28 .gendata = gendata_coord_dispatch,
29 .checkdata = checkdata_coord, 29 .checkdata = checkdata_coord_dispatch,
30 .solve = solve_coord_dispatch, 30 .solve = solve_coord_dispatch,
31}, 31},
32{ 32{
33 .prefix = "mcoord_",
34 .dataid = dataid_coord,
35 .gendata = gendata_coord_dispatch,
36 .checkdata = checkdata_coord_dispatch,
37 .solve = solve_multicoord_dispatch,
38},
39{
33 .prefix = NULL 40 .prefix = NULL
34} 41}
35}; 42};
diff --git a/src/solvers/tables.h b/src/solvers/tables.h
index 1e76fc1..b7a1079 100644
--- a/src/solvers/tables.h
+++ b/src/solvers/tables.h
@@ -8,6 +8,7 @@ STATIC int64_t readtableinfo_n(
8 size_t, const unsigned char *, uint8_t, tableinfo_t [static 1]); 8 size_t, const unsigned char *, uint8_t, tableinfo_t [static 1]);
9STATIC int64_t writetableinfo( 9STATIC int64_t writetableinfo(
10 const tableinfo_t [static 1], size_t, unsigned char *); 10 const tableinfo_t [static 1], size_t, unsigned char *);
11STATIC void append_name(tableinfo_t [static 1], const char *);
11 12
12STATIC uint64_t 13STATIC uint64_t
13read_unaligned_u64(const unsigned char buf[static sizeof(uint64_t)]) 14read_unaligned_u64(const unsigned char buf[static sizeof(uint64_t)])
@@ -135,3 +136,14 @@ writetableinfo(
135 136
136 return NISSY_OK; 137 return NISSY_OK;
137} 138}
139
140STATIC void
141append_name(tableinfo_t info[static 1], const char *str)
142{
143 int i, j;
144
145 for (i = 0, j = strlen(info->solver); str[i] != '\0'; i++, j++)
146 info->solver[j] = str[i];
147
148 info->solver[j] = '\0';
149}
diff --git a/src/solvers/tables_types_macros.h b/src/solvers/tables_types_macros.h
index 16e1346..b2809b7 100644
--- a/src/solvers/tables_types_macros.h
+++ b/src/solvers/tables_types_macros.h
@@ -6,6 +6,7 @@
6 6
7#define TABLETYPE_PRUNING UINT64_C(0) 7#define TABLETYPE_PRUNING UINT64_C(0)
8#define TABLETYPE_SPECIAL UINT64_C(1) 8#define TABLETYPE_SPECIAL UINT64_C(1)
9#define TABLETYPE_MULTI UINT64_C(2)
9 10
10#define INFO_OFFSET_DISTRIBUTION 0 11#define INFO_OFFSET_DISTRIBUTION 0
11#define INFO_OFFSET_TYPE (INFO_DISTRIBUTION_LEN * sizeof(uint64_t)) 12#define INFO_OFFSET_TYPE (INFO_DISTRIBUTION_LEN * sizeof(uint64_t))

Generated with cgit - Back to sebastiano.tronto.net