UNPKG

deltascrambler

Version:

Scramble and scramble image generator for all WCA and lots of non-WCA puzzles

312 lines (281 loc) 9.76 kB
var scramble_special_222 = (function() { //Using https://github.com/FrederikHutfless/FastVirtual2x2 const UBL = 0; const UBR = 1; const UFR = 2; const UFL = 3; const DBL = 4; const DBR = 5; const DFR = 6; const DFL = 7; //Solved Cube var cp = [UBL, UBR, UFR, UFL, DBL, DBR, DFR, DFL]; var co = [0, 0, 0, 0, 0, 0, 0, 0]; const moveU = 0; const moveUP = 1; const moveU2 = 2; const moveR = 3; const moveRP = 4; const moveR2 = 5; const moveF = 6; const moveFP = 7; const moveF2 = 8;const movey = 9; const moveyP = 10; const movey2 = 11; const cpMaps = [ [3, 0, 1, 2, 4, 5, 6, 7], [1, 2, 3, 0, 4, 5, 6, 7], [2, 3, 0, 1, 4, 5, 6, 7], [0, UFR, DFR, 3, 4, UBR, DBR, 7], [0, DBR, UBR, 3, 4, DFR, UFR, 7], [0, DFR, DBR, 3, 4, 2, 1, 7], [0, 1, UFL, DFL, 4, 5, UFR, DFR], [0, 1, DFR, UFR, 4, 5, DFL, UFL], [0, 1, DFL, DFR, 4, 5, UFL, UFR], [3,0,1,2,7,4,5,6], [1,2,3,0,5,6,7,4], [2,3,0,1,6,7,4,5] ]; const coMaps = [ [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 2, 1, 0, 0, 1, 2, 0], [0, 2, 1, 0, 0, 1, 2, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 2, 1, 0, 0, 1, 2], [0, 0, 2, 1, 0, 0, 1, 2], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0] ]; const inverseMoves = [1, 0, 2, 4, 3, 5, 7, 6, 8]; function applyCpMove(cp, map) { return [cp[map[0]], cp[map[1]], cp[map[2]], cp[map[3]], cp[map[4]], cp[map[5]], cp[map[6]], cp[map[7]]]; } function applyCoMove(co, map) { return [(co[0] + map[0]) % 3, (co[1] + map[1]) % 3, (co[2] + map[2]) % 3, (co[3] + map[3]) % 3, (co[4] + map[4]) % (2+1), (co[5] + map[5]) % 3, (co[6] + map[6]) % 3, (co[7] + map[7]) % 3]; } function applyMove(co, cp, move) { return [applyCoMove(applyCpMove(co, cpMaps[move]), coMaps[move]), applyCpMove(cp, cpMaps[move])]; } function applyMoves(moves, co, cp) { var i, s; for (i = 0; i < moves.length; ++i) { s = applyMove(co, cp, moves[i]); cp = s[1]; co = s[0]; } return [co, cp]; } function generateOrientations(cube) { return [ cube, applyMoves([moveR, movey2, moveRP, movey2], ...cube), //x applyMoves([moveRP, movey2, moveR, movey2], ...cube), //x' applyMoves([movey], ...cube), //y applyMoves([moveyP], ...cube), //y' applyMoves([movey2], ...cube), //y2 applyMoves([moveF, movey2, moveFP, movey2], ...cube), //z applyMoves([moveFP, movey2, moveF, movey2], ...cube), //z' applyMoves([moveR2, movey2, moveR2], ...cube), //z2 applyMoves([moveR2, movey2, moveR2, movey], ...cube), //z2 y applyMoves([moveR2, movey2, moveR2, movey2], ...cube), //z2 y2 applyMoves([moveR2, movey2, moveR2, moveyP], ...cube), //z2 y' applyMoves([moveF, movey2, moveFP], ...cube), //z y2 applyMoves([moveF, movey2, moveFP, moveyP], ...cube), //z y applyMoves([moveF, movey2, moveFP, movey], ...cube), //z y' applyMoves([moveFP, movey2, moveF, moveyP], ...cube), //z' y applyMoves([moveFP, movey2, moveF, movey], ...cube), //z' y' applyMoves([moveFP, movey2, moveF], ...cube), //z' y2 applyMoves([moveR, movey2, moveRP, movey], ...cube), //x y' applyMoves([moveRP, movey2, moveR, movey], ...cube), //x' y' applyMoves([moveR, movey2, moveRP], ...cube), //x y2 applyMoves([moveRP, movey2, moveR], ...cube), //x' y2 applyMoves([moveR, movey2, moveRP, moveyP], ...cube), //x y applyMoves([moveRP, movey2, moveR, moveyP], ...cube) //x' y ]; } function checkScrambleCharacteristic(cube, fn) { var orientations = generateOrientations(cube); for (var i = 0; i < orientations.length; ++i) { var orientedCube = orientations[i]; if (fn(...orientedCube)) return true; } return false; } function isSideBlock(co, cp) { return pieceToStickers(cp[DFL])[(co[DFL] + 0) % 3] == pieceToStickers(cp[DBL])[(co[DBL] + 0) % 3]; } function is112Block(co, cp) { return isSideBlock(co, cp) && pieceToStickers(cp[DBL])[(co[DBL] + 2) % 3] == pieceToStickers(cp[DFL])[(co[DFL] + 1) % 3]; } function convertMoves(moves) { return moves.split(" ").map(function(a) { return { "U": 0, "U'": 1, "U2": 2, "R": 3, "R'": 4, "R2": 5, "F": 6, "F'": 7, "F2": 8} [a] }); } function movesReadable(moves) { return moves.map(function(a) { return ["U", "U'", "U2", "R", "R'", "R2", "F", "F'", "F2"][a] }).join(" "); } function pieceToStickers(piece) { return ["WOB", "WBR", "WRG", "WGO", "YBO", "YRB", "YGR", "YOG"][piece]; } function cancel(alg) { return alg.split("R R'").join("").split("F F'").join("").split("U U'").join("") .split("R2 R2").join("").split("F2 F2").join("").split("U2 U2").join("") .split("R' R").join("").split("F' F").join("").split("U' U").join(""); } function get112BlockScramble() { var s = puzzles["222"].generateScramble(); s = convertMoves(s); var c = applyMoves(s, co, cp); if (checkScrambleCharacteristic(c, is112Block)) return movesReadable(s).split(" "); for (var i = 0; i < 9; ++i) { if (Math.floor(s[s.length - 1] / 3) != Math.floor(i / 3) || s[s.length - 1] == i) { c = applyMove(c[0], c[1], i); if (checkScrambleCharacteristic(c, is112Block)) return cancel(movesReadable([...s, i])).split(" "); c = applyMove(c[0], c[1], inverseMoves[i]); } } return get112BlockScramble(); } function getNoBarScramble() { var s = puzzles["222"].generateScramble(); s = convertMoves(s); var c = applyMoves(s, co, cp); if (!checkScrambleCharacteristic(c, is112Block)) return movesReadable(s).split(" "); for (var i = 0; i < 9; ++i) { if (Math.floor(s[s.length - 1] / 3) != Math.floor(i / 3) || s[s.length - 1] == i) { c = applyMove(c[0], c[1], i); if (!checkScrambleCharacteristic(c, is112Block)) return cancel(movesReadable([...s, i])).split(" "); c = applyMove(c[0], c[1], inverseMoves[i]); } } return get112BlockScramble(); } function getSideBlockScramble() { var s = puzzles["222"].generateScramble(); s = convertMoves(s); var c = applyMoves(s, co, cp); if (checkScrambleCharacteristic(c, isSideBlock)) return movesReadable(s).split(" "); for (var i = 0; i < 9; ++i) { if (Math.floor(s[s.length - 1] / 3) != Math.floor(i / 3) || s[s.length - 1] == i) { c = applyMove(c[0], c[1], i); if (checkScrambleCharacteristic(c, isSideBlock)) return cancel(movesReadable([...s, i])).split(" "); c = applyMove(c[0], c[1], inverseMoves[i]); } } return getSideBlockScramble(); } function genMoves(config) { if (config.type == "112Block") return get112BlockScramble(); if (config.type == "SideBlock") return getSideBlockScramble(); if (config.type == "NoBar") return getNoBarScramble(); if (config.type == "Any") return randomScramble(); return getSideBlockScramble(); } function genImage(moves, config) { if (moves.join) moves = moves.join(" "); var c = tnoodlejs.scrambleToSvg(moves, puzzles["222"], 0, 0); return scramble_colors.changeImageColors(c); } //Solver attempt var statesfound = {}; function recurse1(c, isdepth, shoulddepth, movesdone) { var lm = movesdone[movesdone.length - 1]; for (var i = 0; i < 9; ++i) { if (movesdone.length == 0 || Math.floor(lm / 3) != Math.floor(i / 3)) { c = applyMove(c[0], c[1], i); statesfound[c[0].join("") + c[1].join("")] = [...movesdone,i].join(""); if (isdepth < shoulddepth) recurse1(c, isdepth + 1, shoulddepth, [...movesdone, i]); c = applyMove(c[0], c[1], inverseMoves[i]); } } } function phase1() { recurse1([co, cp], 1 - 1, 6 - 1, []); } function recurse2(c, isdepth, shoulddepth, movesdone) { var lm = movesdone[movesdone.length - 1], z, i; for (i = 0; i < 9; ++i) { if (movesdone.length == 0 || Math.floor(lm / 3) != Math.floor(i / 3)) { c = applyMove(c[0], c[1], i); if (statesfound[c[0].join("") + c[1].join("")]) { return [statesfound[c[0].join("") + c[1].join("")].split(""), [...movesdone,i]]; } if (isdepth < shoulddepth) z = recurse2(c, isdepth + 1, shoulddepth, [...movesdone, i]); if (z != "no" && z !== undefined) return z; c = applyMove(c[0], c[1], inverseMoves[i]); } } return "no"; } function phase2(s) { if (Object.keys(statesfound).length == 0) phase1(); s = convertMoves(s); var c = applyMoves(s, co, cp); var zz = recurse2([co,cp], 1 - 1, 5 - 1, []); return m2sol(zz[0], zz[1]); } function randomScramble() { if (Object.keys(statesfound).length == 0) phase1(); function shuffleArray(arr) { var i,j; for (i = arr.length - 1; i > 0; --i) { j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; } var cp = shuffleArray([UBL, UBR, UFR, UFL, DBR, DFR, DFL]); cp = [cp[0], cp[1], cp[2], cp[3], DBL, cp[4], cp[5], cp[6]]; var co = [0, 0, 0, 0, 0, 0, 0, 0]; var parity = 0; for(var i=0;i<7;++i){ var x = Math.floor(Math.random()*3); if(i==4) x=0; co[i]=x; parity += x; } co[7] = [0,2,1][parity%3]; var zz = recurse2([co,cp], 1 - 1, 5 - 1, []); return m2sol(zz[0], zz[1]); } function cancel2(p){ var h = []; for(var i=0;i<p.length;++i){ if((i < p.length && p[i+1] === undefined) || Math.floor(p[i]/3) != Math.floor(p[i+1]/3)){ h.push(p[i]); }else{ var tg = [1,-1,2][p[i]%3]+[1,-1,2][p[i+1]%3]; ++i; if(tg == 1) h.push(Math.floor(p[i]/3)*3); else if(tg == 2) h.push(Math.floor(p[i]/3)*3+2); else if(tg == 3) h.push(Math.floor(p[i]/3)*3+1); } } return h; } function m2sol(m,p){ p = p.reverse(); p = p.map(function(a){return inverseMoves[a]}); p = [...m, ...p]; p=cancel2(p); return movesReadable(p).split(" "); } return { genMoves: genMoves, genImage: genImage, solve: phase2, statesfound: statesfound, randomScramble: randomScramble }; })();