/
bb3StateRule.js
125 lines (114 loc) · 3.48 KB
/
bb3StateRule.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
* implements the BusyBoxes reversible CA as outlined here:
* http://arxiv.org/abs/1206.2060
*/
STATES=3;
bb3StateRule = function(grid, x, y, z, frm) {
var offx, offy, offz, swpx, swpy, swpz;
var coi = grid.get(x, y, z);
if ((x + y + z & 1) != (frm & 1)) return coi; // only process if field parity is correct
function getSwap(x, y, z) { // return valid swap offset or null if there is contention
var swapx = null, swapy = null;
for (var i=0; i<8; i++) {
var xx = x+offx[i];
var yy = y+offy[i];
var zz = z+offz[i];
if (grid.get(xx, yy, zz)) {
if ((swapx != null) && (swapx != swpx[i] || swapy != swpy[i] || swapz != swpz[i]) ) { // swap confict, forgeddaboudit
return null;
}
swapx = swpx[i];
swapy = swpy[i];
swapz = swpz[i];
}
}
if (swapx == null) return null;
return [swapx, swapy, swapz];
}
function getSwap2(x, y, z) { // return valid swap offset or null if there is contention
var swapx = null, swapy = null;
for (var i=0; i<8; i++) {
var xx = x+offx[i];
var yy = y+offy[i];
var zz = z+offz[i];
if (grid.get(xx, yy, zz)) {
if ((swapx != null) && (swapx != swpx[i] || swapy != swpy[i] || swapz != swpz[i]) ) { // swap confict, forgeddaboudit
return null;
}
swapx = swpx[i];
swapy = swpy[i];
swapz = swpz[i];
}
}
if (swapx == null) return null;
return [swapx, swapy, swapz];
}
function onePlane() { // process one of 3 planes dep on phase
var swap = getSwap(x, y, z); // proposed swap cell as delta from xyz
if (swap != null) { // if valid (no immediate conflicts)
var swapper = grid.get(x+swap[0], y+swap[1], z+swap[2]); // get state at swap cell
if (swapper != coi) { // if state is different from ours, we might swap
var revswap = getSwap(x+swap[0], y+swap[1], z+swap[2]); // proposed swap for swap cell
if (revswap != null) {
if ( (swap[0] + revswap[0] == 0) &&
(swap[1] + revswap[1] == 0) && // if it matches (mutual proposed swaps), do this thing
(swap[2] + revswap[2] == 0)) { // we return his state; he will return ours.
return swapper; // That's what we call a swap, Scooby Doo
}
}
}
}
return coi;
}
var m = trueMod(frame, 3); // set up offsets & swap coords dep on phase
if (m==0) {
offx = bb_offsetx;
offy = bb_offsety;
offz = bb_offsetz;
swpx = bb_swapx;
swpy = bb_swapy;
swpz = bb_swapz;
}
if (m==1) {
offx = bb_offsetz;
offy = bb_offsetx;
offz = bb_offsety;
swpx = bb_swapz;
swpy = bb_swapx;
swpz = bb_swapy;
}
if (m==2) {
offx = bb_offsety;
offy = bb_offsetz;
offz = bb_offsetx;
swpx = bb_swapy;
swpy = bb_swapz;
swpz = bb_swapx;
}
return onePlane();
}
// Knight's move offsets
var bb_offsetx = [+2, +1, -1, -2, +2, +1, -1, -2];
var bb_offsety = [+1, +2, +2, +1, -1, -2, -2, -1];
var bb_offsetz = [0, 0, 0, 0, 0, 0, 0, 0];
// corresponding swap offsets
var bb_swapx = [+1, -1, +1, -1, +1, -1, +1, -1];
var bb_swapy = [-1, +1, +1, -1, +1, -1, -1, +1];
var bb_swapz = [0, 0, 0, 0, 0, 0, 0, 0];
// Javascript ftw
function trueMod(v, base) {
if (v < 0) {
return ((v % base) + base) % base;
}
return v % base;
}
// and TDD also ftw
bb_TEST=0;
if(bb_TEST) {
var grid = new Grid(10, 10, 10);
grid.put(0, 0, 0, 1);
grid.put(1, 2, 0, 1);
// grid.put(-1, 2, 0, 1);
console.log("bbRule returns:", bbRule(grid, 0, 0, 0));
console.log("bbRule returns:", bbRule(grid, -1, 1, 0));
}