Skip to content

Commit c1461fd

Browse files
committed
[scramble] Add experimentalDeriveScrambleForEvent(…).
Example usage: ```js import { experimentalDeriveScrambleForEvent } from "cubing/scramble"; import { setSearchDebug } from "cubing/search"; setSearchDebug({ allowDerivedScrambles: true }); ( await experimentalDeriveScrambleForEvent( "67002dfc95e6d4288f418fbaa9150aa65b239fd5581f2d067d0293b9321a8b67", ["222", "222-r4", "set1", "attempt3-extra2", "scramble1"], "222", ) ).log(); ```
1 parent 607fd25 commit c1461fd

File tree

6 files changed

+104
-44
lines changed

6 files changed

+104
-44
lines changed

script/test/dist/lib/cubing/node/scramble/test.js

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
import assert from "node:assert";
12
import { Alg } from "cubing/alg";
23
import { cube2x2x2 } from "cubing/puzzles";
3-
import { randomScrambleForEvent } from "cubing/scramble";
4+
import {
5+
experimentalDeriveScrambleForEvent,
6+
randomScrambleForEvent,
7+
} from "cubing/scramble";
48
import { experimentalSolveTwsearch, setSearchDebug } from "cubing/search";
59

610
setSearchDebug({ disableStringWorker: true });
711

8-
(async () => {
12+
await (async () => {
913
(await randomScrambleForEvent("222")).log();
1014
(await randomScrambleForEvent("333")).log();
1115

@@ -31,7 +35,36 @@ setSearchDebug({ disableStringWorker: true });
3135
}
3236

3337
console.log("Success!");
38+
})();
39+
40+
await (async () => {
41+
{
42+
console.log("----------------");
43+
console.log("Deriving scrambles.");
44+
setSearchDebug({ allowDerivedScrambles: true });
45+
const scramble1 = await experimentalDeriveScrambleForEvent(
46+
"67002dfc95e6d4288f418fbaa9150aa65b239fd5581f2d067d0293b9321a8b67",
47+
["222", "222-r4", "set1", "attempt3-extra2", "scramble1"],
48+
"222",
49+
);
50+
console.log(scramble1.toString());
51+
const scramble2 = await experimentalDeriveScrambleForEvent(
52+
"67002dfc95e6d4288f418fbaa9150aa65b239fd5581f2d067d0293b9321a8b67",
53+
["222", "222-r4", "set1", "attempt3-extra2", "scramble1"],
54+
"222",
55+
);
56+
console.log(scramble2.toString());
57+
const scramble3 = await experimentalDeriveScrambleForEvent(
58+
"6700abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
59+
["222", "222-r4", "set1", "attempt3-extra2", "scramble1"],
60+
"222",
61+
);
62+
console.log(scramble3.toString());
3463

35-
// TODO(https://github.com/cubing/cubing.js/issues/358): this shouldn't be needed.
36-
(await import("node:process")).exit(0);
64+
assert(scramble1.isIdentical(scramble2));
65+
assert(!scramble1.isIdentical(scramble3));
66+
}
3767
})();
68+
69+
// TODO(https://github.com/cubing/cubing.js/issues/358): this shouldn't be needed.
70+
(await import("node:process")).exit(0);

src/cubing/scramble/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@
66
* @packageDocumentation
77
*/
88

9-
export { randomScrambleForEvent } from "../search/cubing-private";
9+
export {
10+
deriveScrambleForEvent as experimentalDeriveScrambleForEvent,
11+
randomScrambleForEvent,
12+
} from "../search/cubing-private";
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export { random333Scramble as rawRandom333Scramble } from "../inside/solve/puzzles/3x3x3";
2-
export { randomScrambleForEvent } from "../outside";
2+
export { deriveScrambleForEvent, randomScrambleForEvent } from "../outside";

src/cubing/search/inside/api.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { randomRediCubeScramble } from "./solve/puzzles/redi_cube";
2828
import { solveSkewb } from "./solve/puzzles/skewb";
2929
import {
3030
type TwsearchOptions,
31+
wasmDeriveScrambleForEvent,
3132
wasmRandomScrambleForEvent,
3233
wasmTwsearch,
3334
} from "./solve/twsearch";
@@ -231,6 +232,23 @@ export const insideAPI = {
231232
return (await insideAPI.randomScrambleForEvent(eventID)).toString();
232233
},
233234

235+
deriveScrambleStringForEvent: async (
236+
derivationSeedHex: string,
237+
derivationSaltHierarchy: string[],
238+
eventID: string,
239+
): Promise<string> => {
240+
const scramble = await measurePerf(
241+
`deriveScrambleForEvent(…, ${JSON.stringify(eventID)})`,
242+
() =>
243+
wasmDeriveScrambleForEvent(
244+
derivationSeedHex,
245+
derivationSaltHierarchy,
246+
eventID,
247+
),
248+
);
249+
return scramble.toString();
250+
},
251+
234252
solve333ToString: async (patternData: KPatternData): Promise<string> => {
235253
const pattern = new KPattern(await puzzles["3x3x3"].kpuzzle(), patternData);
236254
return (await solve333(pattern)).toString();

src/cubing/search/inside/solve/twsearch.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,16 @@ export async function wasmRandomScrambleForEvent(
3333
const { wasmRandomScrambleForEvent } = await twsearchPromise;
3434
return wasmRandomScrambleForEvent(eventID);
3535
}
36+
37+
export async function wasmDeriveScrambleForEvent(
38+
derivationSeedHex: string,
39+
derivationSaltHierarchy: string[],
40+
eventID: string,
41+
): Promise<Alg> {
42+
const { wasmDeriveScrambleForEvent } = await twsearchPromise;
43+
return wasmDeriveScrambleForEvent(
44+
derivationSeedHex,
45+
derivationSaltHierarchy,
46+
eventID,
47+
);
48+
}

src/cubing/search/outside.ts

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import type { KPuzzle } from "../kpuzzle";
33
// import { preInitialize222 } from "../implementations/2x2x2";
44
import type { KPattern } from "../kpuzzle/KPattern";
55
import type { PrefetchLevel } from "./inside/api";
6-
import { randomClockScrambleString } from "./inside/solve/puzzles/clock"; // TODO: don't reach into `inside` code.
76
import type { TwsearchOptions } from "./inside/solve/twsearch";
87
import {
98
type InsideOutsideAPI,
@@ -48,34 +47,31 @@ export function _preInitializationHintForEvent(
4847
}
4948

5049
export async function randomScrambleForEvent(eventID: string): Promise<Alg> {
51-
switch (eventID) {
52-
case "clock":
53-
return Alg.fromString(await randomClockScrambleString());
54-
}
55-
const prom = _randomScrambleStringForEvent(eventID);
56-
const wat = await prom;
57-
return Alg.fromString(wat);
58-
}
59-
60-
export async function _randomScrambleStringForEvent(
61-
eventID: string,
62-
): Promise<string> {
63-
if (searchOutsideDebugGlobals.forceNewWorkerForEveryScramble) {
64-
}
6550
const worker = searchOutsideDebugGlobals.forceNewWorkerForEveryScramble
6651
? await instantiateWorker()
6752
: await getCachedWorkerInstance();
68-
return worker.insideAPI.randomScrambleStringForEvent(eventID);
53+
const scrambleString =
54+
await worker.insideAPI.randomScrambleStringForEvent(eventID);
55+
return Alg.fromString(scrambleString);
6956
}
7057

71-
export async function randomScrambleStringForEvent(
58+
export async function deriveScrambleForEvent(
59+
derivationSeedHex: string,
60+
derivationSaltHierarchy: string[],
7261
eventID: string,
73-
): Promise<string> {
74-
switch (eventID) {
75-
case "clock":
76-
return randomClockScrambleString();
62+
): Promise<Alg> {
63+
if (!searchOutsideDebugGlobals.allowDerivedScrambles) {
64+
throw new Error("Derived scrambles are not allowed.");
7765
}
78-
return await _randomScrambleStringForEvent(eventID);
66+
const worker = searchOutsideDebugGlobals.forceNewWorkerForEveryScramble
67+
? await instantiateWorker()
68+
: await getCachedWorkerInstance();
69+
const scrambleString = await worker.insideAPI.deriveScrambleStringForEvent(
70+
derivationSeedHex,
71+
derivationSaltHierarchy,
72+
eventID,
73+
);
74+
return Alg.fromString(scrambleString);
7975
}
8076

8177
export async function experimentalSolve3x3x3IgnoringCenters(
@@ -159,6 +155,7 @@ interface SearchOutsideDebugGlobals {
159155
showWorkerInstantiationWarnings: boolean;
160156
// This can prevent a request to `search-worker-entry.js` when it doesn't exist, if the library semantics have been mangled by `esbuild`.
161157
prioritizeEsbuildWorkaroundForWorkerInstantiation: boolean;
158+
allowDerivedScrambles: boolean;
162159
}
163160

164161
export const searchOutsideDebugGlobals: SearchOutsideDebugGlobals = {
@@ -168,6 +165,7 @@ export const searchOutsideDebugGlobals: SearchOutsideDebugGlobals = {
168165
forceNewWorkerForEveryScramble: false,
169166
showWorkerInstantiationWarnings: true,
170167
prioritizeEsbuildWorkaroundForWorkerInstantiation: false,
168+
allowDerivedScrambles: false,
171169
};
172170

173171
export function setSearchDebug(
@@ -186,21 +184,16 @@ export function setSearchDebug(
186184
),
187185
);
188186
}
189-
if ("disableStringWorker" in options) {
190-
searchOutsideDebugGlobals.disableStringWorker =
191-
options.disableStringWorker ??
192-
searchOutsideDebugGlobals.disableStringWorker;
193-
}
194-
if ("forceNewWorkerForEveryScramble" in options) {
195-
searchOutsideDebugGlobals.forceNewWorkerForEveryScramble =
196-
!!options.forceNewWorkerForEveryScramble;
197-
}
198-
if ("showWorkerInstantiationWarnings" in options) {
199-
searchOutsideDebugGlobals.showWorkerInstantiationWarnings =
200-
!!options.showWorkerInstantiationWarnings;
201-
}
202-
if ("prioritizeEsbuildWorkaroundForWorkerInstantiation" in options) {
203-
searchOutsideDebugGlobals.prioritizeEsbuildWorkaroundForWorkerInstantiation =
204-
!!options.prioritizeEsbuildWorkaroundForWorkerInstantiation;
187+
for (const booleanField of [
188+
"disableStringWorker",
189+
"forceNewWorkerForEveryScramble",
190+
"showWorkerInstantiationWarnings",
191+
"prioritizeEsbuildWorkaroundForWorkerInstantiation",
192+
"allowDerivedScrambles",
193+
] as const) {
194+
if (booleanField in options) {
195+
searchOutsideDebugGlobals[booleanField] =
196+
options[booleanField] ?? searchOutsideDebugGlobals[booleanField];
197+
}
205198
}
206199
}

0 commit comments

Comments
 (0)