rbx-scrambler
Version:
A puzzle scrambler in Javascript
640 lines (639 loc) • 21.5 kB
JavaScript
/* Base script written by Jaap Scherphuis, jaapsch a t yahoo d o t com */
/* Javascript written by Syoji Takamatsu, , red_dragon a t honki d o t net */
/* Random-State modification by Lucas Garron (lucasg a t gmx d o t de / garron.us) in collaboration with Michael Gottlieb (mzrg.com)*/
/* Optimal modification by Michael Gottlieb (qqwref a t gmail d o t com) from Jaap's code */
/* Version 1.0*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.scramblerPyram = void 0;
if (typeof scramblers == 'undefined') {
var scramblers = {};
}
exports.scramblerPyram = (function () {
var numcub = 1;
var colorString = 'xgryb'; //In dlburf order. May use any colours in colorList below
// list of available colours
var colorList = [
'g',
'green.jpg',
'green',
'r',
'red.jpg',
'red',
'y',
'yellow.jpg',
'yellow',
'b',
'blue.jpg',
'blue',
'w',
'white.jpg',
'white',
'o',
'orange.jpg',
'orange',
'p',
'purple.jpg',
'purple',
'0',
'gray.jpg',
'grey', // used for unrecognised letters, or when zero used.
];
// layout
var layout = [
1, 2, 1, 2, 1, 0, 2, 0, 1, 2, 1, 2, 1, 0, 1, 2, 1, 0, 2, 1, 2, 0, 1, 2, 1, 0, 0, 0, 1, 0, 2, 1, 2, 1, 2, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
];
var seq = []; // move sequences
var colmap = []; // color map
var colors = []; //stores colours used
var scramblestring = [];
function parse() {
/*
var s = "";
var urlquery = location.href.split("?")
if(urlquery.length > 1) {
var urlterms = urlquery[1].split("&")
for( var i = 0; i < urlterms.length; i++) {
var urllr = urlterms[i].split("=");
if(urllr[0] == "num") {
if(urllr[1] - 0 >= 1 )
numcub = urllr[1] - 0;
}
else if(urllr[0] == "col") {
if(urllr[1].length==4)
colorString = urllr[1];
}
}
}
*/
// expand colour string into 6 actual html color names
for (var k = 0; k < 6; k++) {
colors[k + 1] = colorList.length - 3; // gray
for (var i = 0; i < colorList.length; i += 3) {
if (colorString.charAt(k) == colorList[i]) {
colors[k + 1] = i; // not use index 0
break;
}
}
}
}
parse();
function init_colors(n) {
colmap[n] = [
1, 1, 1, 1, 1, 0, 2, 0, 3, 3, 3, 3, 3, 0, 1, 1, 1, 0, 2, 2, 2, 0, 3, 3, 3, 0, 0, 0, 1, 0, 2, 2, 2, 2, 2, 0, 3, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
];
}
function scramble() {
var i, j, n, ls, t;
for (n = 0; n < numcub; n++) {
initbrd();
dosolve();
scramblestring[n] = '';
init_colors(n);
for (i = 0; i < sol.length; i++) {
scramblestring[n] += ['U', 'L', 'R', 'B'][sol[i] & 7] + ['', "'"][(sol[i] & 8) / 8] + ' ';
picmove([3, 0, 1, 2][sol[i] & 7], 1 + (sol[i] & 8) / 8, n);
}
var tips = ['l', 'r', 'b', 'u'];
for (i = 0; i < 4; i++) {
var j = Math.floor(randomSource.random() * 3);
if (j < 2) {
scramblestring[n] += tips[i] + ['', "'"][j] + ' ';
picmove(4 + i, 1 + j, n);
}
}
}
}
var posit = [];
var mode;
var edt;
var perm = []; // pruning table for edge permutation
var twst = []; // pruning table for edge orientation+twist
var permmv = []; // transition table for edge permutation
var twstmv = []; // transition table for edge orientation+twist
var sol = [];
var pcperm = [];
var pcori = [];
var soltimer;
function initbrd() {
if (mode == 4)
clearTimeout(soltimer);
posit = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
];
mode = 0;
sol.length = 0;
}
function solved() {
for (var i = 1; i < 9; i++) {
if (posit[i] != posit[0])
return false;
if (posit[i + 9] != posit[9])
return false;
if (posit[i + 18] != posit[18])
return false;
if (posit[i + 27] != posit[27])
return false;
}
return true;
}
var edges = [2, 11, 1, 20, 4, 31, 10, 19, 13, 29, 22, 28];
var movelist = [];
movelist[0] = [0, 18, 9, 6, 24, 15, 1, 19, 11, 2, 20, 10]; //U
movelist[1] = [23, 3, 30, 26, 7, 34, 22, 1, 31, 20, 4, 28]; //L
movelist[2] = [5, 14, 32, 8, 17, 35, 4, 11, 29, 2, 13, 31]; //R
movelist[3] = [12, 21, 27, 16, 25, 33, 13, 19, 28, 10, 22, 29]; //B
function domove(m) {
for (var i = 0; i < movelist[m].length; i += 3) {
var c = posit[movelist[m][i]];
posit[movelist[m][i]] = posit[movelist[m][i + 2]];
posit[movelist[m][i + 2]] = posit[movelist[m][i + 1]];
posit[movelist[m][i + 1]] = c;
}
}
function dosolve() {
var a, b, c, l, t = 0, q = 0;
// Get a random permutation and orientation.
var parity = 0;
pcperm = [0, 1, 2, 3, 4, 5];
for (var i = 0; i < 4; i++) {
var other = i + Math.floor((6 - i) * randomSource.random());
var temp = pcperm[i];
pcperm[i] = pcperm[other];
pcperm[other] = temp;
if (i != other)
parity++;
}
if (parity % 2 == 1) {
var temp = pcperm[4];
pcperm[4] = pcperm[5];
pcperm[5] = temp;
}
parity = 0;
pcori = [];
for (var i = 0; i < 5; i++) {
pcori[i] = Math.floor(2 * randomSource.random());
parity += pcori[i];
}
pcori[5] = parity % 2;
for (var i = 6; i < 10; i++) {
pcori[i] = Math.floor(3 * randomSource.random());
}
for (a = 0; a < 6; a++) {
b = 0;
for (c = 0; c < 6; c++) {
if (pcperm[c] == a)
break;
if (pcperm[c] > a)
b++;
}
q = q * (6 - a) + b;
}
//corner orientation
for (a = 9; a >= 6; a--) {
t = t * 3 + pcori[a];
}
//edge orientation
for (a = 4; a >= 0; a--) {
t = t * 2 + pcori[a];
}
// solve it
if (q != 0 || t != 0) {
for (l = 7; l < 12; l++) {
//allow solutions from 7 through 11 moves
if (search(q, t, l, -1))
break;
}
}
}
function search(q, t, l, lm) {
//searches for solution, from position q|t, in l moves exactly. last move was lm, current depth=d
if (l == 0) {
if (q == 0 && t == 0) {
return true;
}
}
else {
if (perm[q] > l || twst[t] > l)
return false;
var p, s, a, m;
for (m = 0; m < 4; m++) {
if (m != lm) {
p = q;
s = t;
for (a = 0; a < 2; a++) {
p = permmv[p][m];
s = twstmv[s][m];
sol[sol.length] = m + 8 * a;
if (search(p, s, l - 1, m))
return true;
sol.length--;
}
}
}
}
return false;
}
function calcperm() {
var c, p, q, l, m, n;
//calculate solving arrays
//first permutation
// initialise arrays
for (p = 0; p < 720; p++) {
perm[p] = -1;
permmv[p] = [];
for (m = 0; m < 4; m++) {
permmv[p][m] = getprmmv(p, m);
}
}
//fill it
perm[0] = 0;
for (l = 0; l <= 6; l++) {
n = 0;
for (p = 0; p < 720; p++) {
if (perm[p] == l) {
for (m = 0; m < 4; m++) {
q = p;
for (c = 0; c < 2; c++) {
q = permmv[q][m];
if (perm[q] == -1) {
perm[q] = l + 1;
n++;
}
}
}
}
}
}
//then twist
// initialise arrays
for (p = 0; p < 2592; p++) {
twst[p] = -1;
twstmv[p] = [];
for (m = 0; m < 4; m++) {
twstmv[p][m] = gettwsmv(p, m);
}
}
//fill it
twst[0] = 0;
for (l = 0; l <= 5; l++) {
n = 0;
for (p = 0; p < 2592; p++) {
if (twst[p] == l) {
for (m = 0; m < 4; m++) {
q = p;
for (c = 0; c < 2; c++) {
q = twstmv[q][m];
if (twst[q] == -1) {
twst[q] = l + 1;
n++;
}
}
}
}
}
}
}
function getprmmv(p, m) {
//given position p<720 and move m<4, return new position number
//convert number into array
var a, b, c;
var ps = [];
var q = p;
for (a = 1; a <= 6; a++) {
c = Math.floor(q / a);
b = q - a * c;
q = c;
for (c = a - 1; c >= b; c--)
ps[c + 1] = ps[c];
ps[b] = 6 - a;
}
//perform move on array
if (m == 0) {
//U
cycle3(ps, 0, 3, 1);
}
else if (m == 1) {
//L
cycle3(ps, 1, 5, 2);
}
else if (m == 2) {
//R
cycle3(ps, 0, 2, 4);
}
else if (m == 3) {
//B
cycle3(ps, 3, 4, 5);
}
//convert array back to number
q = 0;
for (a = 0; a < 6; a++) {
b = 0;
for (c = 0; c < 6; c++) {
if (ps[c] == a)
break;
if (ps[c] > a)
b++;
}
q = q * (6 - a) + b;
}
return q;
}
function gettwsmv(p, m) {
//given position p<2592 and move m<4, return new position number
//convert number into array;
var a, b, c, d = 0;
var ps = [];
var q = p;
//first edge orientation
for (a = 0; a <= 4; a++) {
ps[a] = q & 1;
q >>= 1;
d ^= ps[a];
}
ps[5] = d;
//next corner orientation
for (a = 6; a <= 9; a++) {
c = Math.floor(q / 3);
b = q - 3 * c;
q = c;
ps[a] = b;
}
//perform move on array
if (m == 0) {
//U
ps[6]++;
if (ps[6] == 3)
ps[6] = 0;
cycle3(ps, 0, 3, 1);
ps[1] ^= 1;
ps[3] ^= 1;
}
else if (m == 1) {
//L
ps[7]++;
if (ps[7] == 3)
ps[7] = 0;
cycle3(ps, 1, 5, 2);
ps[2] ^= 1;
ps[5] ^= 1;
}
else if (m == 2) {
//R
ps[8]++;
if (ps[8] == 3)
ps[8] = 0;
cycle3(ps, 0, 2, 4);
ps[0] ^= 1;
ps[2] ^= 1;
}
else if (m == 3) {
//B
ps[9]++;
if (ps[9] == 3)
ps[9] = 0;
cycle3(ps, 3, 4, 5);
ps[3] ^= 1;
ps[4] ^= 1;
}
//convert array back to number
q = 0;
//corner orientation
for (a = 9; a >= 6; a--) {
q = q * 3 + ps[a];
}
//corner orientation
for (a = 4; a >= 0; a--) {
q = q * 2 + ps[a];
}
return q;
}
function picmove(type, direction, n) {
switch (type) {
case 0: // L
rotate3(n, 14, 58, 18, direction);
rotate3(n, 15, 57, 31, direction);
rotate3(n, 16, 70, 32, direction);
rotate3(n, 30, 28, 56, direction);
break;
case 1: // R
rotate3(n, 32, 72, 22, direction);
rotate3(n, 33, 59, 23, direction);
rotate3(n, 20, 58, 24, direction);
rotate3(n, 34, 60, 36, direction);
break;
case 2: // B
rotate3(n, 14, 10, 72, direction);
rotate3(n, 1, 11, 71, direction);
rotate3(n, 2, 24, 70, direction);
rotate3(n, 0, 12, 84, direction);
break;
case 3: // U
rotate3(n, 2, 18, 22, direction);
rotate3(n, 3, 19, 9, direction);
rotate3(n, 16, 20, 10, direction);
rotate3(n, 4, 6, 8, direction);
break;
case 4: // l
rotate3(n, 30, 28, 56, direction);
break;
case 5: // r
rotate3(n, 34, 60, 36, direction);
break;
case 6: // b
rotate3(n, 0, 12, 84, direction);
break;
case 7: // u
rotate3(n, 4, 6, 8, direction);
break;
}
}
function rotate3(n, v1, v2, v3, clockwise) {
if (clockwise == 2) {
cycle3(colmap[n], v3, v2, v1);
}
else {
cycle3(colmap[n], v1, v2, v3);
}
}
function cycle3(arr, i1, i2, i3) {
var c = arr[i1];
arr[i1] = arr[i2];
arr[i2] = arr[i3];
arr[i3] = c;
}
function draw_triangle(pat, color, val) {
var s = '';
if (pat == 1) {
s += '<table border=0 cellpadding=0 cellspacing=0>';
s += '<tr>';
for (var c = 1; c <= 12; c++) {
s +=
"<td width=1 height=2><img src='scrbg/" + colorList[colors[color] + 1] + "' height='2px' width='1px'></td>";
}
s += '</tr>';
for (var i = 1; i <= 5; i++) {
s += '<tr>';
s += '<td colspan=' + i + ' width=' + i + ' height=2 bgcolor=silver></td>';
s +=
'<td colspan=' +
(12 - i * 2) +
' width=' +
(12 - i * 2) +
" height=2><img src='scrbg/" +
colorList[colors[color] + 1] +
"' height='2px' width='" +
(12 - i * 2) +
"px'></td>";
s += '<td colspan=' + i + ' width=' + i + ' height=2 bgcolor=silver></td>';
s += '</tr>';
}
s += '</table>';
}
else if (pat == 2) {
s += '<table border=0 cellpadding=0 cellspacing=0>';
for (var i = 5; i >= 1; i--) {
s += '<tr>';
s += '<td colspan=' + i + ' width=' + i + ' height=2 bgcolor=silver></td>';
s +=
'<td colspan=' +
(12 - i * 2) +
' width=' +
(12 - i * 2) +
" height=2><img src='scrbg/" +
colorList[colors[color] + 1] +
"' height='2px' width='" +
(12 - i * 2) +
"px'></td>";
s += '<td colspan=' + i + ' width=' + i + ' height=2 bgcolor=silver></td>';
s += '</tr>';
}
s += '<tr>';
for (var c = 1; c <= 12; c++) {
s +=
"<td width=1 height=2><img src='scrbg/" + colorList[colors[color] + 1] + "' height='2px' width='1px'></td>";
}
s += '</tr>';
s += '</table>';
}
else {
s += ' ';
}
return s;
}
function imagetable(n) {
var x, y;
var s = '<table border=0 cellpadding=0 cellspacing=0>';
for (var y = 0; y < 7; y++) {
s += '<tr>';
for (var x = 0; x < 13; x++) {
s += '<td>';
s += draw_triangle(layout[y * 13 + x], colmap[n][y * 13 + x], '');
s += '</td>';
}
s += '</tr>';
}
s += '</table>';
return s;
}
/* Methods added by Lucas. */
var randomSource = undefined;
// If we have a better (P)RNG:
var setRandomSource = function (src) {
randomSource = src;
};
var getRandomScramble = function () {
scramble();
return {
state: colmap,
scramble_string: scramblestring[0],
};
};
var initializeFull = function (continuation, iniRandomSource) {
setRandomSource(iniRandomSource);
parse();
calcperm();
if (continuation) {
setTimeout(continuation, 0);
}
};
var border = 15;
var width = 18;
//URFLBD
var drawingCenters = [
[border + (width / 2) * 1, border + (width / 2) * 1],
[border + (width / 2) * 5, border + (width / 2) * 3],
[border + (width / 2) * 3, border + (width / 2) * 3],
[border + (width / 2) * 1, border + (width / 2) * 3],
[border + (width / 2) * 7, border + (width / 2) * 3],
[border + (width / 2) * 3, border + (width / 2) * 5],
];
function colorGet(col) {
if (col == 'r')
return '#FF0000';
if (col == 'o')
return '#FF8000';
if (col == 'b')
return '#0000FF';
if (col == 'g')
return '#00FF00';
if (col == 'y')
return '#FFFF00';
if (col == 'w')
return '#FFFFFF';
if (col == 'x')
return '#000000';
}
var scalePoint = function (w, h, ptIn) {
var defaultWidth = border * 2 + width * 9;
var defaultHeight = border * 2 + width * 5.3;
var scale = Math.min(w / defaultWidth, h / defaultHeight);
var x = ptIn[0] * scale + (w - defaultWidth * scale) / 2;
var y = ptIn[1] * scale + (h - defaultHeight * scale) / 2;
return [x, y];
};
function drawTriangle(r, canvasWidth, canvasHeight, cx, cy, w, h, direction, fillColor) {
var dM = 1; // Direction Multiplier
if (direction == 2) {
dM = -1;
}
var arrx = [cx, cx - w, cx + w];
var arry = [cy + h * dM, cy - h * dM, cy - h * dM];
var pathString = '';
for (var i = 0; i < arrx.length; i++) {
var scaledPoint = scalePoint(canvasWidth, canvasHeight, [arrx[i], arry[i]]);
pathString += (i === 0 ? 'M' : 'L') + scaledPoint[0] + ',' + scaledPoint[1];
}
pathString += 'z';
r.path(pathString).attr({ fill: colorGet(fillColor), stroke: '#000' });
}
var drawScramble = function (parentElement, state, w, h) {
var r = Raphael(parentElement, w, h);
for (var y = 0; y < 7; y++) {
for (var x = 0; x < 13; x++) {
var col = state[0][y * 13 + x];
if (col != 0) {
var xx = border + width + (((x * width) / 2) * 2) / Math.sqrt(3);
var yy = border + y * width;
if (y > 3) {
yy -= width / 2;
}
drawTriangle(r, w, h, xx, yy, ((width / 2) * 2) / Math.sqrt(3), width / 2, layout[y * 13 + x], colorString[col]);
}
}
}
};
return {
/* mark2 interface */
version: 'December 29, 2011',
initialize: initializeFull,
setRandomSource: setRandomSource,
getRandomScramble: getRandomScramble,
drawScramble: drawScramble,
/* Other methods */
};
})();