/**
* Copyright (C) 2023 Shuang Chen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
-----------------------------------------------------------------------
Modified by Isaac Vega
*/
import {
acycle,
coord,
fillFacelet,
get8Perm,
idxArray,
rn,
rndPerm,
set8Perm,
Solver,
valuedArray,
} from "../lib/mathlib";
import { fixCase, regScrambler } from "./scramble";
const solv = new Solver(3, 3, [
[0, [doPermMove, "p", 7], 5040],
[0, [doOriMove, "o", 7, -3], 729],
]);
const movePieces = [
[0, 2, 3, 1],
[0, 1, 5, 4],
[0, 4, 6, 2],
];
const moveOris = [undefined, [0, 1, 0, 1, 3], [1, 0, 1, 0, 3]];
// @ts-ignore
const oriCoord = new coord("o", 7, -3);
function doPermMove(arr: number[], m: number) {
acycle(arr, movePieces[m]);
}
function doOriMove(arr: number[], m: number) {
acycle(arr, movePieces[m], 1, moveOris[m]);
}
const cFacelet = [
[3, 4, 9],
[1, 20, 5],
[2, 8, 17],
[0, 16, 21],
[13, 11, 6],
[15, 7, 22],
[12, 19, 10],
];
function checkNoBar(pidx: number, oidx: any) {
const perm = set8Perm([], pidx, 7);
const ori = oriCoord.set([], oidx);
const f = [];
for (let i = 0; i < 24; i++) {
f[i] = i >> 2;
}
fillFacelet(cFacelet, f, perm, ori, 4);
for (let i = 0; i < 24; i += 4) {
if (((1 << f[i]) | (1 << f[i + 3])) & ((1 << f[i + 1]) | (1 << f[i + 2]))) {
return false;
}
}
return true;
}
const egprobs = [
1, 2, 4, 4, 4, 4, 4, 4, 1, 2, 4, 4, 4, 4, 4, 4, 1, 2, 4, 4, 4, 4, 4, 4, 1, 2, 4, 4, 4, 4, 4, 4, 1,
2, 4, 4, 4, 4, 4, 4, 1, 2, 4, 4, 4, 4, 4, 4,
];
const egmap = [0, 17, 5, 14, 8, 1, 2, 4];
const egfilter = [
"EG0-O",
"EG0-H",
"EG0-L",
"EG0-Pi",
"EG0-S",
"EG0-T",
"EG0-U",
"EG0-aS",
"EG1B-O",
"EG1B-H",
"EG1B-L",
"EG1B-Pi",
"EG1B-S",
"EG1B-T",
"EG1B-U",
"EG1B-aS",
"EG1L-O",
"EG1L-H",
"EG1L-L",
"EG1L-Pi",
"EG1L-S",
"EG1L-T",
"EG1L-U",
"EG1L-aS",
"EG1F-O",
"EG1F-H",
"EG1F-L",
"EG1F-Pi",
"EG1F-S",
"EG1F-T",
"EG1F-U",
"EG1F-aS",
"EG1R-O",
"EG1R-H",
"EG1R-L",
"EG1R-Pi",
"EG1R-S",
"EG1R-T",
"EG1R-U",
"EG1R-aS",
"EG2-O",
"EG2-H",
"EG2-L",
"EG2-Pi",
"EG2-S",
"EG2-T",
"EG2-U",
"EG2-aS",
];
const egperms = [
[4, 5, 6],
[4, 6, 5],
[6, 5, 4],
[5, 4, 6],
[5, 6, 4],
[6, 4, 5],
];
const egll_map = [
[0x3210, 0x1221, 2, "H-1"],
[0x3120, 0x1221, 2, "H-2"],
[0x2310, 0x1221, 4, "H-3"],
[0x3012, 0x1221, 4, "H-4"],
[0x0312, 0x0210, 4, "L-1"],
[0x2310, 0x0210, 4, "L-2"],
[0x0213, 0x0210, 4, "L-3"],
[0x3210, 0x0210, 4, "L-4"],
[0x2013, 0x0210, 4, "L-5"],
[0x3012, 0x0210, 4, "L-6"],
[0x3210, 0x1212, 4, "Pi-1"],
[0x0213, 0x1212, 4, "Pi-2"],
[0x2310, 0x1212, 4, "Pi-3"],
[0x2013, 0x1212, 4, "Pi-4"],
[0x3012, 0x1212, 4, "Pi-5"],
[0x0312, 0x1212, 4, "Pi-6"],
[0x3210, 0x2220, 4, "S-1"],
[0x0213, 0x2220, 4, "S-2"],
[0x0312, 0x2220, 4, "S-3"],
[0x3012, 0x2220, 4, "S-4"],
[0x2013, 0x2220, 4, "S-5"],
[0x2310, 0x2220, 4, "S-6"],
[0x2310, 0x1020, 4, "T-1"],
[0x2013, 0x1020, 4, "T-2"],
[0x0213, 0x1020, 4, "T-3"],
[0x3210, 0x1020, 4, "T-4"],
[0x3012, 0x1020, 4, "T-5"],
[0x0312, 0x1020, 4, "T-6"],
[0x0213, 0x2010, 4, "U-1"],
[0x3210, 0x2010, 4, "U-2"],
[0x0312, 0x2010, 4, "U-3"],
[0x3012, 0x2010, 4, "U-4"],
[0x2310, 0x2010, 4, "U-5"],
[0x2013, 0x2010, 4, "U-6"],
[0x3210, 0x1011, 4, "aS-1"],
[0x0213, 0x1011, 4, "aS-2"],
[0x0312, 0x1011, 4, "aS-3"],
[0x3012, 0x1011, 4, "aS-4"],
[0x2310, 0x1011, 4, "aS-5"],
[0x2013, 0x1011, 4, "aS-6"],
];
const tcllp_map: { 0: number; 1: number; 2: number; 3: string }[] = [
[0x0123, 0x0221, 4, "Hammer-1"],
[0x3021, 0x0221, 4, "Hammer-2"],
[0x0132, 0x0221, 4, "Hammer-3"],
[0x0231, 0x0221, 4, "Hammer-4"],
[0x0321, 0x0221, 4, "Hammer-5"],
[0x2301, 0x0221, 4, "Hammer-6"],
[0x0123, 0x1022, 4, "Spaceship-1"],
[0x2301, 0x1022, 4, "Spaceship-2"],
[0x1320, 0x1022, 4, "Spaceship-3"],
[0x3021, 0x1022, 4, "Spaceship-4"],
[0x3012, 0x1022, 4, "Spaceship-5"],
[0x0231, 0x1022, 4, "Spaceship-6"],
[0x2031, 0x0002, 4, "Stollery-1"],
[0x3120, 0x0002, 4, "Stollery-2"],
[0x3201, 0x0002, 4, "Stollery-3"],
[0x2103, 0x0002, 4, "Stollery-4"],
[0x0231, 0x0002, 4, "Stollery-5"],
[0x2130, 0x0002, 4, "Stollery-6"],
[0x0123, 0x2222, 1, "Pinwheel-1"],
[0x1032, 0x2222, 1, "Pinwheel-2"],
[0x3201, 0x2222, 4, "Pinwheel-3"],
[0x2031, 0x0110, 2, "2Face-1"],
[0x3102, 0x0110, 4, "2Face-2"],
[0x0213, 0x0110, 2, "2Face-3"],
[0x3021, 0x0110, 4, "2Face-4"],
[0x1302, 0x0122, 4, "Turtle-1"],
[0x1032, 0x0122, 4, "Turtle-2"],
[0x3201, 0x0122, 4, "Turtle-3"],
[0x1230, 0x0122, 4, "Turtle-4"],
[0x2310, 0x0122, 4, "Turtle-5"],
[0x0321, 0x0122, 4, "Turtle-6"],
[0x3210, 0x1112, 4, "Pinwheel Poser-1"],
[0x3120, 0x1112, 4, "Pinwheel Poser-2"],
[0x3201, 0x1112, 4, "Pinwheel Poser-3"],
[0x2103, 0x1112, 4, "Pinwheel Poser-4"],
[0x2310, 0x1112, 4, "Pinwheel Poser-5"],
[0x2130, 0x1112, 4, "Pinwheel Poser-6"],
[0x2031, 0x0011, 4, "Gun-1"],
[0x1032, 0x0011, 4, "Gun-2"],
[0x0132, 0x0011, 4, "Gun-3"],
[0x3021, 0x0011, 4, "Gun-4"],
[0x2310, 0x0011, 4, "Gun-5"],
[0x2130, 0x0011, 4, "Gun-6"],
];
const tclln_map = [
[0x1302, 0x1201, 4, "Hammer-1"],
[0x3021, 0x1201, 4, "Hammer-2"],
[0x2310, 0x1201, 4, "Hammer-3"],
[0x3201, 0x1201, 4, "Hammer-4"],
[0x1203, 0x1201, 4, "Hammer-5"],
[0x3120, 0x1201, 4, "Hammer-6"],
[0x0123, 0x1012, 4, "Spaceship-1"],
[0x1032, 0x1012, 4, "Spaceship-2"],
[0x0312, 0x1012, 4, "Spaceship-3"],
[0x3201, 0x1012, 4, "Spaceship-4"],
[0x1023, 0x1012, 4, "Spaceship-5"],
[0x2130, 0x1012, 4, "Spaceship-6"],
[0x0123, 0x0001, 4, "Stollery-1"],
[0x3120, 0x0001, 4, "Stollery-2"],
[0x0132, 0x0001, 4, "Stollery-3"],
[0x2103, 0x0001, 4, "Stollery-4"],
[0x3102, 0x0001, 4, "Stollery-5"],
[0x1203, 0x0001, 4, "Stollery-6"],
[0x0123, 0x1111, 1, "Pinwheel-1"],
[0x1032, 0x1111, 1, "Pinwheel-2"],
[0x1320, 0x1111, 4, "Pinwheel-3"],
[0x2031, 0x2002, 2, "2Face-1"],
[0x0132, 0x2002, 4, "2Face-2"],
[0x1032, 0x2002, 2, "2Face-3"],
[0x3021, 0x2002, 4, "2Face-4"],
[0x2031, 0x1102, 4, "Turtle-1"],
[0x3120, 0x1102, 4, "Turtle-2"],
[0x1023, 0x1102, 4, "Turtle-3"],
[0x3021, 0x1102, 4, "Turtle-4"],
[0x0132, 0x1102, 4, "Turtle-5"],
[0x1203, 0x1102, 4, "Turtle-6"],
[0x1302, 0x2122, 4, "Pinwheel Poser-1"],
[0x0213, 0x2122, 4, "Pinwheel Poser-2"],
[0x2013, 0x2122, 4, "Pinwheel Poser-3"],
[0x0312, 0x2122, 4, "Pinwheel Poser-4"],
[0x2310, 0x2122, 4, "Pinwheel Poser-5"],
[0x0321, 0x2122, 4, "Pinwheel Poser-6"],
[0x0123, 0x0022, 4, "Gun-1"],
[0x1032, 0x0022, 4, "Gun-2"],
[0x0132, 0x0022, 4, "Gun-3"],
[0x2310, 0x0022, 4, "Gun-4"],
[0x0312, 0x0022, 4, "Gun-5"],
[0x2130, 0x0022, 4, "Gun-6"],
];
const lsall_map = [
[0x00000, "LS1-PBL"],
[0x00222, "LS1-Sune"],
[0x00111, "LS1-aSune"],
[0x00102, "LS1-Ua"],
[0x00021, "LS1-Ub"],
[0x00120, "LS1-La"],
[0x00210, "LS1-Lb"],
[0x00201, "LS1-Ta"],
[0x00012, "LS1-Tb"],
[0x10221, "LS2-Hammer"],
[0x10212, "LS2-Spaceship"],
[0x10200, "LS2-StolleryA"],
[0x10002, "LS2-StolleryB"],
[0x10020, "LS2-StolleryC"],
[0x10110, "LS2-2Face"],
[0x10122, "LS2-Turtle"],
[0x10011, "LS2-GunA"],
[0x10101, "LS2-GunB"],
[0x20112, "LS3-Hammer"],
[0x20211, "LS3-Spaceship"],
[0x20100, "LS3-StolleryA"],
[0x20001, "LS3-StolleryB"],
[0x20010, "LS3-StolleryC"],
[0x20220, "LS3-2Face"],
[0x20121, "LS3-Turtle"],
[0x20022, "LS3-GunA"],
[0x20202, "LS3-GunB"],
[0x02022, "LS4-SuneA"],
[0x02220, "LS4-SuneB"],
[0x02202, "LS4-SuneC"],
[0x02211, "LS4-PiA"],
[0x02121, "LS4-PiB"],
[0x02010, "LS4-U"],
[0x02001, "LS4-L"],
[0x02100, "LS4-T"],
[0x02112, "LS4-H"],
[0x12012, "LS5-HammerA"],
[0x12102, "LS5-HammerB"],
[0x12120, "LS5-SpaceshipA"],
[0x12201, "LS5-SpaceshipB"],
[0x12000, "LS5-Stollery"],
[0x12222, "LS5-Pinwheel"],
[0x12021, "LS5-TurtleA"],
[0x12210, "LS5-TurtleB"],
[0x12111, "LS5-Pinwheel Poser"],
[0x22110, "LS6-Hammer"],
[0x22101, "LS6-Spaceship"],
[0x22002, "LS6-2Face"],
[0x22011, "LS6-Turtle"],
[0x22122, "LS6-Pinwheel PoserA"],
[0x22221, "LS6-Pinwheel PoserB"],
[0x22212, "LS6-Pinwheel PoserC"],
[0x22200, "LS6-GunA"],
[0x22020, "LS6-GunB"],
[0x01011, "LS7-aSuneA"],
[0x01110, "LS7-aSuneB"],
[0x01101, "LS7-aSuneC"],
[0x01212, "LS7-PiA"],
[0x01122, "LS7-PiB"],
[0x01200, "LS7-U"],
[0x01002, "LS7-L"],
[0x01020, "LS7-T"],
[0x01221, "LS7-H"],
[0x11220, "LS8-Hammer"],
[0x11022, "LS8-Spaceship"],
[0x11001, "LS8-2Face"],
[0x11202, "LS8-Turtle"],
[0x11121, "LS8-Pinwheel PoserA"],
[0x11112, "LS8-Pinwheel PoserB"],
[0x11211, "LS8-Pinwheel PoserC"],
[0x11010, "LS8-GunA"],
[0x11100, "LS8-GunB"],
[0x21201, "LS9-HammerA"],
[0x21021, "LS9-HammerB"],
[0x21012, "LS9-SpaceshipA"],
[0x21120, "LS9-SpaceshipB"],
[0x21000, "LS9-Stollery"],
[0x21111, "LS9-Pinwheel"],
[0x21102, "LS9-TurtleA"],
[0x21210, "LS9-TurtleB"],
[0x21222, "LS9-Pinwheel Poser"],
];
const egllprobs = idxArray(egll_map, 2);
const egllfilter = idxArray(egll_map, 3);
const tcllpprobs = idxArray(tcllp_map, 2);
const tcllpfilter = idxArray(tcllp_map, 3);
const tcllnprobs = idxArray(tclln_map, 2);
const tcllnfilter = idxArray(tclln_map, 3);
const lsallprobs = valuedArray(lsall_map.length, 1);
const lsallfilter = idxArray(lsall_map, 1);
function getScramble(type: string, length: number, state: number) {
void length;
let ori: any, perm: any, lim;
const maxl = type == "222o" ? 0 : 9;
do {
lim = 2;
if (type == "222o" || type == "222so") {
perm = rn(5040);
ori = rn(729);
lim = 3;
} else if (type == "222eg") {
ori = egmap[state & 0x7];
perm = [0, 2, 3, 4, 5, 1][state >> 3];
const arr = set8Perm([0, 0, 0, 0].concat(egperms[perm]), rn(24), 4);
perm = get8Perm(arr, 7);
let rndU = rn(4);
ori = oriCoord.set([], ori);
while (rndU-- > 0) {
doOriMove(ori, 0);
}
ori = oriCoord.get(ori);
} else if (/^222eg[012]$/.exec(type)) {
return getScramble("222eg", length, [0, 8, 40][~~type[5]] + state);
} else if (type == "222nb") {
do {
perm = rn(5040);
ori = rn(729);
} while (!checkNoBar(perm, ori));
}
} while ((perm == 0 && ori == 0) || solv.search([perm, ori], 0, lim) != null);
return solv.toStr(solv.search([perm, ori], maxl)?.reverse() || [], "URF", "'2 ");
}
function getLLScramble(type: string, length: number, cases: any) {
let llcase: any;
let ncubie = 4;
let perm = [0, 1, 2, 3];
let ori = [0, 0, 0, 0, 0, 0, 0];
if (type == "222tcp") {
llcase = tcllp_map[fixCase(cases, tcllpprobs)];
ori = [0, 0, 0, 0, 1, 0, 0];
perm = perm.concat(egperms[0]);
} else if (type == "222tcn") {
llcase = tclln_map[fixCase(cases, tcllnprobs)];
ori = [0, 0, 0, 0, 2, 0, 0];
perm = perm.concat(egperms[0]);
} else if (type == "222eg0") {
llcase = egll_map[fixCase(cases, egllprobs)];
perm = perm.concat(egperms[0]);
} else if (type == "222eg1") {
llcase = egll_map[fixCase(cases, egllprobs)];
perm = perm.concat(egperms[2 + rn(4)]);
} else if (type == "222eg2") {
llcase = egll_map[fixCase(cases, egllprobs)];
perm = perm.concat(egperms[1]);
} else if (type == "222lsall") {
perm = perm.concat(egperms[0]);
const perm4 = rndPerm(4);
perm4.push(perm4[3]);
perm4[3] = 4;
llcase = [0, lsall_map[fixCase(cases, lsallprobs)][0]];
for (let i = 0; i < 5; i++) {
llcase[0] |= perm4[i] << (i * 4);
}
ncubie = 5;
}
let rndA = rn(4);
while (rndA-- > 0) {
doPermMove(perm, 0);
}
const perm0 = perm.slice();
for (let i = 0; i < ncubie; i++) {
perm[i] = perm0[(llcase[0] >> (i * 4)) & 0xf];
ori[i] = (llcase[1] >> (i * 4)) & 0xf;
}
let rndU = rn(4);
while (rndU-- > 0) {
doOriMove(ori, 0);
doPermMove(perm, 0);
}
const p = get8Perm(perm, 7);
const o = oriCoord.get(ori);
return solv.toStr(solv.search([p, o], 9)?.reverse() || [], "URF", "'2 ");
}
regScrambler(["222o", "222so", "222nb"], getScramble)("222eg0", getLLScramble, [
egllfilter,
egllprobs,
])("222eg1", getLLScramble, [egllfilter, egllprobs])("222eg2", getLLScramble, [
egllfilter,
egllprobs,
])("222tcp", getLLScramble, [tcllpfilter, tcllpprobs])("222tcn", getLLScramble, [
tcllnfilter,
tcllnprobs,
])("222lsall", getLLScramble, [lsallfilter, lsallprobs])("222eg", getScramble, [egfilter, egprobs]);