Finish BoardObj engine moves.
authorOleksandr Gavenko <gavenkoa@gmail.com>
Tue, 23 Sep 2014 01:03:32 +0300
changeset 115 9e01c6c0c679
parent 114 1c3fdde0d481
child 116 61f7f1f03a8d
Finish BoardObj engine moves.
board.js
--- a/board.js	Tue Sep 23 00:37:34 2014 +0300
+++ b/board.js	Tue Sep 23 01:03:32 2014 +0300
@@ -997,3 +997,1602 @@
     return false;
 }
 
+BoardObj.prototype.right = function(brd) {
+    var updated = false;
+    var from = this.brd, to = brd.brd;
+    var moved = true;
+    var f0 = from.aa, f1 = from.ab, f2 = from.ac, f3 = from.ad;
+    if (f3 === 0) {
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 0
+                if (f0 === 0)
+                    moved = false;
+                f3 = f0;
+                f2 = 0;
+            } else {         // a b 0 0
+                f3 = f1;
+                f2 = f0;
+            }
+            f1 = 0;
+        } else {             // f2 !== 0 && f3 === 0
+            if (f1 === 0) {  // a 0 b 0
+                f3 = f2;
+                f2 = f0;
+            } else {         // a b c 0
+                f3 = f2;
+                f2 = f1;
+                f1 = f0;
+            }
+        }
+        f0 = 0;
+    } else {                 // f3 !== 0
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 b
+                if (f0 === 0)
+                    moved = false;
+                f2 = f0;
+            } else {         // a b 0 c
+                f2 = f1;
+                f1 = f0;
+            }
+            f0 = 0;
+        } else {             // f2 !== 0 && f3 !== 0
+            if (f1 === 0) {  // a 0 b c
+                if (f0 === 0)
+                    moved = false;
+                f1 = f0;
+                f0 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f2 === 0) {
+        to.aa = 0;
+        to.ab = 0;
+        to.ac = 0;
+        to.ad = f3;
+        continue;
+    }
+    if (f1 === 0) {
+        to.aa = 0;
+        to.ab = 0;
+        if (f2 === f3) {
+            updated = true;
+            to.ac = 0;
+            to.ad = f3 + 1;
+        } else {
+            to.ac = f2;
+            to.ad = f3;
+        }
+        continue;
+    }
+    if (f2 === f3) {
+        updated = true;
+        to.aa = 0;
+        to.ad = f3 + 1;
+        if (f0 === f1) {
+            to.ab = 0;
+            to.ac = f1 + 1;
+        } else {
+            to.ab = f0;
+            to.ac = f1;
+        }
+    } else {
+        to.ad = f3;
+        if (f1 === f2) {
+            updated = true;
+            to.aa = 0;
+            to.ab = f0;
+            to.ac = f2 + 1;
+        } else {
+            if (f0 === f1) {
+                updated = true;
+                to.aa = 0;
+                to.ab = f1+1;
+                to.ac = f2;
+            } else {
+                to.aa = f0;
+                to.ab = f1;
+                to.ac = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.ba, f1 = from.bb, f2 = from.bc, f3 = from.bd;
+    if (f3 === 0) {
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 0
+                if (f0 === 0)
+                    moved = false;
+                f3 = f0;
+                f2 = 0;
+            } else {         // a b 0 0
+                f3 = f1;
+                f2 = f0;
+            }
+            f1 = 0;
+        } else {             // f2 !== 0 && f3 === 0
+            if (f1 === 0) {  // a 0 b 0
+                f3 = f2;
+                f2 = f0;
+            } else {         // a b c 0
+                f3 = f2;
+                f2 = f1;
+                f1 = f0;
+            }
+        }
+        f0 = 0;
+    } else {                 // f3 !== 0
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 b
+                if (f0 === 0)
+                    moved = false;
+                f2 = f0;
+            } else {         // a b 0 c
+                f2 = f1;
+                f1 = f0;
+            }
+            f0 = 0;
+        } else {             // f2 !== 0 && f3 !== 0
+            if (f1 === 0) {  // a 0 b c
+                if (f0 === 0)
+                    moved = false;
+                f1 = f0;
+                f0 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f2 === 0) {
+        to.ba = 0;
+        to.bb = 0;
+        to.bc = 0;
+        to.bd = f3;
+        continue;
+    }
+    if (f1 === 0) {
+        to.ba = 0;
+        to.bb = 0;
+        if (f2 === f3) {
+            updated = true;
+            to.bc = 0;
+            to.bd = f3 + 1;
+        } else {
+            to.bc = f2;
+            to.bd = f3;
+        }
+        continue;
+    }
+    if (f2 === f3) {
+        updated = true;
+        to.ba = 0;
+        to.bd = f3 + 1;
+        if (f0 === f1) {
+            to.bb = 0;
+            to.bc = f1 + 1;
+        } else {
+            to.bb = f0;
+            to.bc = f1;
+        }
+    } else {
+        to.bd = f3;
+        if (f1 === f2) {
+            updated = true;
+            to.ba = 0;
+            to.bb = f0;
+            to.bc = f2 + 1;
+        } else {
+            if (f0 === f1) {
+                updated = true;
+                to.ba = 0;
+                to.bb = f1+1;
+                to.bc = f2;
+            } else {
+                to.ba = f0;
+                to.bb = f1;
+                to.bc = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.ca, f1 = from.cb, f2 = from.cc, f3 = from.cd;
+    if (f3 === 0) {
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 0
+                if (f0 === 0)
+                    moved = false;
+                f3 = f0;
+                f2 = 0;
+            } else {         // a b 0 0
+                f3 = f1;
+                f2 = f0;
+            }
+            f1 = 0;
+        } else {             // f2 !== 0 && f3 === 0
+            if (f1 === 0) {  // a 0 b 0
+                f3 = f2;
+                f2 = f0;
+            } else {         // a b c 0
+                f3 = f2;
+                f2 = f1;
+                f1 = f0;
+            }
+        }
+        f0 = 0;
+    } else {                 // f3 !== 0
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 b
+                if (f0 === 0)
+                    moved = false;
+                f2 = f0;
+            } else {         // a b 0 c
+                f2 = f1;
+                f1 = f0;
+            }
+            f0 = 0;
+        } else {             // f2 !== 0 && f3 !== 0
+            if (f1 === 0) {  // a 0 b c
+                if (f0 === 0)
+                    moved = false;
+                f1 = f0;
+                f0 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f2 === 0) {
+        to.ca = 0;
+        to.cb = 0;
+        to.cc = 0;
+        to.cd = f3;
+        continue;
+    }
+    if (f1 === 0) {
+        to.ca = 0;
+        to.cb = 0;
+        if (f2 === f3) {
+            updated = true;
+            to.cc = 0;
+            to.cd = f3 + 1;
+        } else {
+            to.cc = f2;
+            to.cd = f3;
+        }
+        continue;
+    }
+    if (f2 === f3) {
+        updated = true;
+        to.ca = 0;
+        to.cd = f3 + 1;
+        if (f0 === f1) {
+            to.cb = 0;
+            to.cc = f1 + 1;
+        } else {
+            to.cb = f0;
+            to.cc = f1;
+        }
+    } else {
+        to.cd = f3;
+        if (f1 === f2) {
+            updated = true;
+            to.ca = 0;
+            to.cb = f0;
+            to.cc = f2 + 1;
+        } else {
+            if (f0 === f1) {
+                updated = true;
+                to.ca = 0;
+                to.cb = f1+1;
+                to.cc = f2;
+            } else {
+                to.ca = f0;
+                to.cb = f1;
+                to.cc = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.da, f1 = from.db, f2 = from.dc, f3 = from.dd;
+    if (f3 === 0) {
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 0
+                if (f0 === 0)
+                    moved = false;
+                f3 = f0;
+                f2 = 0;
+            } else {         // a b 0 0
+                f3 = f1;
+                f2 = f0;
+            }
+            f1 = 0;
+        } else {             // f2 !== 0 && f3 === 0
+            if (f1 === 0) {  // a 0 b 0
+                f3 = f2;
+                f2 = f0;
+            } else {         // a b c 0
+                f3 = f2;
+                f2 = f1;
+                f1 = f0;
+            }
+        }
+        f0 = 0;
+    } else {                 // f3 !== 0
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 b
+                if (f0 === 0)
+                    moved = false;
+                f2 = f0;
+            } else {         // a b 0 c
+                f2 = f1;
+                f1 = f0;
+            }
+            f0 = 0;
+        } else {             // f2 !== 0 && f3 !== 0
+            if (f1 === 0) {  // a 0 b c
+                if (f0 === 0)
+                    moved = false;
+                f1 = f0;
+                f0 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f2 === 0) {
+        to.da = 0;
+        to.db = 0;
+        to.dc = 0;
+        to.dd = f3;
+        continue;
+    }
+    if (f1 === 0) {
+        to.da = 0;
+        to.db = 0;
+        if (f2 === f3) {
+            updated = true;
+            to.dc = 0;
+            to.dd = f3 + 1;
+        } else {
+            to.dc = f2;
+            to.dd = f3;
+        }
+        continue;
+    }
+    if (f2 === f3) {
+        updated = true;
+        to.da = 0;
+        to.dd = f3 + 1;
+        if (f0 === f1) {
+            to.db = 0;
+            to.dc = f1 + 1;
+        } else {
+            to.db = f0;
+            to.dc = f1;
+        }
+    } else {
+        to.dd = f3;
+        if (f1 === f2) {
+            updated = true;
+            to.da = 0;
+            to.db = f0;
+            to.dc = f2 + 1;
+        } else {
+            if (f0 === f1) {
+                updated = true;
+                to.da = 0;
+                to.db = f1+1;
+                to.dc = f2;
+            } else {
+                to.da = f0;
+                to.db = f1;
+                to.dc = f2;
+            }
+        }
+    }
+    return updated;
+}
+
+BoardObj.prototype.down = function(brd) {
+    var updated = false;
+    var from = this.brd, to = brd.brd;
+    var moved = true;
+    var f0 = from.aa, f1 = from.ba, f2 = from.ca, f3 = from.da;
+    if (f3 === 0) {
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 0
+                if (f0 === 0)
+                    moved = false;
+                f3 = f0;
+                f2 = 0;
+            } else {         // a b 0 0
+                f3 = f1;
+                f2 = f0;
+            }
+            f1 = 0;
+        } else {             // f2 !== 0 && f3 === 0
+            if (f1 === 0) {  // a 0 b 0
+                f3 = f2;
+                f2 = f0;
+            } else {         // a b c 0
+                f3 = f2;
+                f2 = f1;
+                f1 = f0;
+            }
+        }
+        f0 = 0;
+    } else {                 // f3 !== 0
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 b
+                if (f0 === 0)
+                    moved = false;
+                f2 = f0;
+            } else {         // a b 0 c
+                f2 = f1;
+                f1 = f0;
+            }
+            f0 = 0;
+        } else {             // f2 !== 0 && f3 !== 0
+            if (f1 === 0) {  // a 0 b c
+                if (f0 === 0)
+                    moved = false;
+                f1 = f0;
+                f0 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f2 === 0) {
+        to.aa = 0;
+        to.ba = 0;
+        to.ca = 0;
+        to.da = f3;
+        continue;
+    }
+    if (f1 === 0) {
+        to.aa = 0;
+        to.ba = 0;
+        if (f2 === f3) {
+            to.ca = 0;
+            to.da = f3 + 1;
+            updated = true;
+        } else {
+            to.ca = f2;
+            to.da = f3;
+        }
+        continue;
+    }
+    if (f2 === f3) {
+        updated = true;
+        to.aa = 0;
+        to.da = f3 + 1;
+        if (f0 === f1) {
+            to.ba = 0;
+            to.ca = f1 + 1;
+        } else {
+            to.ba = f0;
+            to.ca = f1;
+        }
+    } else {
+        to.da = f3;
+        if (f1 === f2) {
+            updated = true;
+            to.aa = 0;
+            to.ba = f0;
+            to.ca = f2 + 1;
+        } else {
+            if (f0 === f1) {
+                updated = true;
+                to.aa = 0;
+                to.ba = f1+1;
+                to.ca = f2;
+            } else {
+                to.aa = f0;
+                to.ba = f1;
+                to.ca = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.ab, f1 = from.bb, f2 = from.cb, f3 = from.db;
+    if (f3 === 0) {
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 0
+                if (f0 === 0)
+                    moved = false;
+                f3 = f0;
+                f2 = 0;
+            } else {         // a b 0 0
+                f3 = f1;
+                f2 = f0;
+            }
+            f1 = 0;
+        } else {             // f2 !== 0 && f3 === 0
+            if (f1 === 0) {  // a 0 b 0
+                f3 = f2;
+                f2 = f0;
+            } else {         // a b c 0
+                f3 = f2;
+                f2 = f1;
+                f1 = f0;
+            }
+        }
+        f0 = 0;
+    } else {                 // f3 !== 0
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 b
+                if (f0 === 0)
+                    moved = false;
+                f2 = f0;
+            } else {         // a b 0 c
+                f2 = f1;
+                f1 = f0;
+            }
+            f0 = 0;
+        } else {             // f2 !== 0 && f3 !== 0
+            if (f1 === 0) {  // a 0 b c
+                if (f0 === 0)
+                    moved = false;
+                f1 = f0;
+                f0 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f2 === 0) {
+        to.ab = 0;
+        to.bb = 0;
+        to.cb = 0;
+        to.db = f3;
+        continue;
+    }
+    if (f1 === 0) {
+        to.ab = 0;
+        to.bb = 0;
+        if (f2 === f3) {
+            to.cb = 0;
+            to.db = f3 + 1;
+            updated = true;
+        } else {
+            to.cb = f2;
+            to.db = f3;
+        }
+        continue;
+    }
+    if (f2 === f3) {
+        updated = true;
+        to.ab = 0;
+        to.db = f3 + 1;
+        if (f0 === f1) {
+            to.bb = 0;
+            to.cb = f1 + 1;
+        } else {
+            to.bb = f0;
+            to.cb = f1;
+        }
+    } else {
+        to.db = f3;
+        if (f1 === f2) {
+            updated = true;
+            to.ab = 0;
+            to.bb = f0;
+            to.cb = f2 + 1;
+        } else {
+            if (f0 === f1) {
+                updated = true;
+                to.ab = 0;
+                to.bb = f1+1;
+                to.cb = f2;
+            } else {
+                to.ab = f0;
+                to.bb = f1;
+                to.cb = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.ac, f1 = from.bc, f2 = from.cc, f3 = from.dc;
+    if (f3 === 0) {
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 0
+                if (f0 === 0)
+                    moved = false;
+                f3 = f0;
+                f2 = 0;
+            } else {         // a b 0 0
+                f3 = f1;
+                f2 = f0;
+            }
+            f1 = 0;
+        } else {             // f2 !== 0 && f3 === 0
+            if (f1 === 0) {  // a 0 b 0
+                f3 = f2;
+                f2 = f0;
+            } else {         // a b c 0
+                f3 = f2;
+                f2 = f1;
+                f1 = f0;
+            }
+        }
+        f0 = 0;
+    } else {                 // f3 !== 0
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 b
+                if (f0 === 0)
+                    moved = false;
+                f2 = f0;
+            } else {         // a b 0 c
+                f2 = f1;
+                f1 = f0;
+            }
+            f0 = 0;
+        } else {             // f2 !== 0 && f3 !== 0
+            if (f1 === 0) {  // a 0 b c
+                if (f0 === 0)
+                    moved = false;
+                f1 = f0;
+                f0 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f2 === 0) {
+        to.ac = 0;
+        to.bc = 0;
+        to.cc = 0;
+        to.dc = f3;
+        continue;
+    }
+    if (f1 === 0) {
+        to.ac = 0;
+        to.bc = 0;
+        if (f2 === f3) {
+            to.cc = 0;
+            to.dc = f3 + 1;
+            updated = true;
+        } else {
+            to.cc = f2;
+            to.dc = f3;
+        }
+        continue;
+    }
+    if (f2 === f3) {
+        updated = true;
+        to.ac = 0;
+        to.dc = f3 + 1;
+        if (f0 === f1) {
+            to.bc = 0;
+            to.cc = f1 + 1;
+        } else {
+            to.bc = f0;
+            to.cc = f1;
+        }
+    } else {
+        to.dc = f3;
+        if (f1 === f2) {
+            updated = true;
+            to.ac = 0;
+            to.bc = f0;
+            to.cc = f2 + 1;
+        } else {
+            if (f0 === f1) {
+                updated = true;
+                to.ac = 0;
+                to.bc = f1+1;
+                to.cc = f2;
+            } else {
+                to.ac = f0;
+                to.bc = f1;
+                to.cc = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.ad, f1 = from.bd, f2 = from.cd, f3 = from.dd;
+    if (f3 === 0) {
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 0
+                if (f0 === 0)
+                    moved = false;
+                f3 = f0;
+                f2 = 0;
+            } else {         // a b 0 0
+                f3 = f1;
+                f2 = f0;
+            }
+            f1 = 0;
+        } else {             // f2 !== 0 && f3 === 0
+            if (f1 === 0) {  // a 0 b 0
+                f3 = f2;
+                f2 = f0;
+            } else {         // a b c 0
+                f3 = f2;
+                f2 = f1;
+                f1 = f0;
+            }
+        }
+        f0 = 0;
+    } else {                 // f3 !== 0
+        if (f2 === 0) {
+            if (f1 === 0) {  // a 0 0 b
+                if (f0 === 0)
+                    moved = false;
+                f2 = f0;
+            } else {         // a b 0 c
+                f2 = f1;
+                f1 = f0;
+            }
+            f0 = 0;
+        } else {             // f2 !== 0 && f3 !== 0
+            if (f1 === 0) {  // a 0 b c
+                if (f0 === 0)
+                    moved = false;
+                f1 = f0;
+                f0 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f2 === 0) {
+        to.ad = 0;
+        to.bd = 0;
+        to.cd = 0;
+        to.dd = f3;
+        continue;
+    }
+    if (f1 === 0) {
+        to.ad = 0;
+        to.bd = 0;
+        if (f2 === f3) {
+            to.cd = 0;
+            to.dd = f3 + 1;
+            updated = true;
+        } else {
+            to.cd = f2;
+            to.dd = f3;
+        }
+        continue;
+    }
+    if (f2 === f3) {
+        updated = true;
+        to.ad = 0;
+        to.dd = f3 + 1;
+        if (f0 === f1) {
+            to.bd = 0;
+            to.cd = f1 + 1;
+        } else {
+            to.bd = f0;
+            to.cd = f1;
+        }
+    } else {
+        to.dd = f3;
+        if (f1 === f2) {
+            updated = true;
+            to.ad = 0;
+            to.bd = f0;
+            to.cd = f2 + 1;
+        } else {
+            if (f0 === f1) {
+                updated = true;
+                to.ad = 0;
+                to.bd = f1+1;
+                to.cd = f2;
+            } else {
+                to.ad = f0;
+                to.bd = f1;
+                to.cd = f2;
+            }
+        }
+    }
+    return updated;
+}
+
+BoardObj.prototype.left = function(brd) {
+    var updated = false;
+    var from = this.brd, to = brd.brd;
+    var moved = true;
+    var f0 = from.aa, f1 = from.ab, f2 = from.ac, f3 = from.ad;
+    if (f0 === 0) {
+        if (f1 === 0) {
+            if (f2 === 0) {  // 0 0 0 a
+                if (f3 === 0)
+                    moved = false;
+                f0 = f3;
+                f1 = 0;
+            } else {         // 0 0 a b
+                f0 = f2;
+                f1 = f3;
+            }
+            f2 = 0;
+        } else {             // f1 !== 0 && f0 === 0
+            if (f2 === 0) {  // 0 a 0 b
+                f0 = f1;
+                f1 = f3;
+            } else {         // 0 a b c
+                f0 = f1;
+                f1 = f2;
+                f2 = f3;
+            }
+        }
+        f3 = 0;
+    } else {                 // f0 !== 0
+        if (f1 === 0) {
+            if (f2 === 0) {  // a 0 0 b
+                if (f3 === 0)
+                    moved = false;
+                f1 = f3;
+            } else {         // a 0 b c
+                f1 = f2;
+                f2 = f3;
+            }
+            f3 = 0;
+        } else {             // f1 !== 0 && f0 !== 0
+            if (f2 === 0) {  // a b 0 c
+                if (f3 === 0)
+                    moved = false;
+                f2 = f3;
+                f3 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f1 === 0) {          // a 0 0 0
+        to.ad = 0;
+        to.ac = 0;
+        to.ab = 0;
+        to.aa = f0;
+        continue;
+    }
+    if (f2 === 0) {
+        to.ad = 0;
+        to.ac = 0;
+        if (f1 === f0) {     // a a 0 0
+            updated = true;
+            to.ab = 0;
+            to.aa = f0 + 1;
+        } else {             // a b 0 0
+            to.ab = f1;
+            to.aa = f0;
+        }
+        continue;
+    }
+    if (f1 === f0) {
+        updated = true;
+        to.ad = 0;
+        to.aa = f0 + 1;
+        if (f3 === f2) {     // a a b b
+            to.ac = 0;
+            to.ab = f2 + 1;
+        } else {             // a a b c
+            to.ac = f3;
+            to.ab = f2;
+        }
+    } else {
+        to.aa = f0;
+        if (f2 === f1) {     // a b b c
+            updated = true;
+            to.ad = 0;
+            to.ac = f3;
+            to.ab = f1 + 1;
+        } else {
+            to.ab = f1;
+            if (f2 === f3) { // a b c c
+                updated = true;
+                to.ad = 0;
+                to.ac = f2+1;
+            } else {         // a b c d
+                to.ad = f3;
+                to.ac = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.ba, f1 = from.bb, f2 = from.bc, f3 = from.bd;
+    if (f0 === 0) {
+        if (f1 === 0) {
+            if (f2 === 0) {  // 0 0 0 a
+                if (f3 === 0)
+                    moved = false;
+                f0 = f3;
+                f1 = 0;
+            } else {         // 0 0 a b
+                f0 = f2;
+                f1 = f3;
+            }
+            f2 = 0;
+        } else {             // f1 !== 0 && f0 === 0
+            if (f2 === 0) {  // 0 a 0 b
+                f0 = f1;
+                f1 = f3;
+            } else {         // 0 a b c
+                f0 = f1;
+                f1 = f2;
+                f2 = f3;
+            }
+        }
+        f3 = 0;
+    } else {                 // f0 !== 0
+        if (f1 === 0) {
+            if (f2 === 0) {  // a 0 0 b
+                if (f3 === 0)
+                    moved = false;
+                f1 = f3;
+            } else {         // a 0 b c
+                f1 = f2;
+                f2 = f3;
+            }
+            f3 = 0;
+        } else {             // f1 !== 0 && f0 !== 0
+            if (f2 === 0) {  // a b 0 c
+                if (f3 === 0)
+                    moved = false;
+                f2 = f3;
+                f3 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f1 === 0) {          // a 0 0 0
+        to.bd = 0;
+        to.bc = 0;
+        to.bb = 0;
+        to.ba = f0;
+        continue;
+    }
+    if (f2 === 0) {
+        to.bd = 0;
+        to.bc = 0;
+        if (f1 === f0) {     // a a 0 0
+            updated = true;
+            to.bb = 0;
+            to.ba = f0 + 1;
+        } else {             // a b 0 0
+            to.bb = f1;
+            to.ba = f0;
+        }
+        continue;
+    }
+    if (f1 === f0) {
+        updated = true;
+        to.bd = 0;
+        to.ba = f0 + 1;
+        if (f3 === f2) {     // a a b b
+            to.bc = 0;
+            to.bb = f2 + 1;
+        } else {             // a a b c
+            to.bc = f3;
+            to.bb = f2;
+        }
+    } else {
+        to.ba = f0;
+        if (f2 === f1) {     // a b b c
+            updated = true;
+            to.bd = 0;
+            to.bc = f3;
+            to.bb = f1 + 1;
+        } else {
+            to.bb = f1;
+            if (f2 === f3) { // a b c c
+                updated = true;
+                to.bd = 0;
+                to.bc = f2+1;
+            } else {         // a b c d
+                to.bd = f3;
+                to.bc = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.ca, f1 = from.cb, f2 = from.cc, f3 = from.cd;
+    if (f0 === 0) {
+        if (f1 === 0) {
+            if (f2 === 0) {  // 0 0 0 a
+                if (f3 === 0)
+                    moved = false;
+                f0 = f3;
+                f1 = 0;
+            } else {         // 0 0 a b
+                f0 = f2;
+                f1 = f3;
+            }
+            f2 = 0;
+        } else {             // f1 !== 0 && f0 === 0
+            if (f2 === 0) {  // 0 a 0 b
+                f0 = f1;
+                f1 = f3;
+            } else {         // 0 a b c
+                f0 = f1;
+                f1 = f2;
+                f2 = f3;
+            }
+        }
+        f3 = 0;
+    } else {                 // f0 !== 0
+        if (f1 === 0) {
+            if (f2 === 0) {  // a 0 0 b
+                if (f3 === 0)
+                    moved = false;
+                f1 = f3;
+            } else {         // a 0 b c
+                f1 = f2;
+                f2 = f3;
+            }
+            f3 = 0;
+        } else {             // f1 !== 0 && f0 !== 0
+            if (f2 === 0) {  // a b 0 c
+                if (f3 === 0)
+                    moved = false;
+                f2 = f3;
+                f3 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f1 === 0) {          // a 0 0 0
+        to.cd = 0;
+        to.cc = 0;
+        to.cb = 0;
+        to.ca = f0;
+        continue;
+    }
+    if (f2 === 0) {
+        to.cd = 0;
+        to.cc = 0;
+        if (f1 === f0) {     // a a 0 0
+            updated = true;
+            to.cb = 0;
+            to.ca = f0 + 1;
+        } else {             // a b 0 0
+            to.cb = f1;
+            to.ca = f0;
+        }
+        continue;
+    }
+    if (f1 === f0) {
+        updated = true;
+        to.cd = 0;
+        to.ca = f0 + 1;
+        if (f3 === f2) {     // a a b b
+            to.cc = 0;
+            to.cb = f2 + 1;
+        } else {             // a a b c
+            to.cc = f3;
+            to.cb = f2;
+        }
+    } else {
+        to.ca = f0;
+        if (f2 === f1) {     // a b b c
+            updated = true;
+            to.cd = 0;
+            to.cc = f3;
+            to.cb = f1 + 1;
+        } else {
+            to.cb = f1;
+            if (f2 === f3) { // a b c c
+                updated = true;
+                to.cd = 0;
+                to.cc = f2+1;
+            } else {         // a b c d
+                to.cd = f3;
+                to.cc = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.da, f1 = from.db, f2 = from.dc, f3 = from.dd;
+    if (f0 === 0) {
+        if (f1 === 0) {
+            if (f2 === 0) {  // 0 0 0 a
+                if (f3 === 0)
+                    moved = false;
+                f0 = f3;
+                f1 = 0;
+            } else {         // 0 0 a b
+                f0 = f2;
+                f1 = f3;
+            }
+            f2 = 0;
+        } else {             // f1 !== 0 && f0 === 0
+            if (f2 === 0) {  // 0 a 0 b
+                f0 = f1;
+                f1 = f3;
+            } else {         // 0 a b c
+                f0 = f1;
+                f1 = f2;
+                f2 = f3;
+            }
+        }
+        f3 = 0;
+    } else {                 // f0 !== 0
+        if (f1 === 0) {
+            if (f2 === 0) {  // a 0 0 b
+                if (f3 === 0)
+                    moved = false;
+                f1 = f3;
+            } else {         // a 0 b c
+                f1 = f2;
+                f2 = f3;
+            }
+            f3 = 0;
+        } else {             // f1 !== 0 && f0 !== 0
+            if (f2 === 0) {  // a b 0 c
+                if (f3 === 0)
+                    moved = false;
+                f2 = f3;
+                f3 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f1 === 0) {          // a 0 0 0
+        to.dd = 0;
+        to.dc = 0;
+        to.db = 0;
+        to.da = f0;
+        continue;
+    }
+    if (f2 === 0) {
+        to.dd = 0;
+        to.dc = 0;
+        if (f1 === f0) {     // a a 0 0
+            updated = true;
+            to.db = 0;
+            to.da = f0 + 1;
+        } else {             // a b 0 0
+            to.db = f1;
+            to.da = f0;
+        }
+        continue;
+    }
+    if (f1 === f0) {
+        updated = true;
+        to.dd = 0;
+        to.da = f0 + 1;
+        if (f3 === f2) {     // a a b b
+            to.dc = 0;
+            to.db = f2 + 1;
+        } else {             // a a b c
+            to.dc = f3;
+            to.db = f2;
+        }
+    } else {
+        to.da = f0;
+        if (f2 === f1) {     // a b b c
+            updated = true;
+            to.dd = 0;
+            to.dc = f3;
+            to.db = f1 + 1;
+        } else {
+            to.db = f1;
+            if (f2 === f3) { // a b c c
+                updated = true;
+                to.dd = 0;
+                to.dc = f2+1;
+            } else {         // a b c d
+                to.dd = f3;
+                to.dc = f2;
+            }
+        }
+    }
+    return updated;
+}
+
+BoardObj.prototype.up = function(brd) {
+    var updated = false;
+    var from = this.brd, to = brd.brd;
+    var moved = true;
+    var f0 = from.aa, f1 = from.ba, f2 = from.ca, f3 = from.da;
+    if (f0 === 0) {
+        if (f1 === 0) {
+            if (f2 === 0) {  // 0 0 0 a
+                if (f3 === 0)
+                    moved = false;
+                f0 = f3;
+                f1 = 0;
+            } else {         // 0 0 a b
+                f0 = f2;
+                f1 = f3;
+            }
+            f2 = 0;
+        } else {             // f1 !== 0 && f0 === 0
+            if (f2 === 0) {  // 0 a 0 b
+                f0 = f1;
+                f1 = f3;
+            } else {         // 0 a b c
+                f0 = f1;
+                f1 = f2;
+                f2 = f3;
+            }
+        }
+        f3 = 0;
+    } else {                 // f0 !== 0
+        if (f1 === 0) {
+            if (f2 === 0) {  // a 0 0 b
+                if (f3 === 0)
+                    moved = false;
+                f1 = f3;
+            } else {         // a 0 b c
+                f1 = f2;
+                f2 = f3;
+            }
+            f3 = 0;
+        } else {             // f1 !== 0 && f0 !== 0
+            if (f2 === 0) {  // a b 0 c
+                if (f3 === 0)
+                    moved = false;
+                f2 = f3;
+                f3 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f1 === 0) {          // a 0 0 0
+        to.da = 0;
+        to.ca = 0;
+        to.ba = 0;
+        to.aa = f0;
+        continue;
+    }
+    if (f2 === 0) {
+        to.da = 0;
+        to.ca = 0;
+        if (f1 === f0) {     // a a 0 0
+            updated = true;
+            to.ba = 0;
+            to.aa = f0 + 1;
+        } else {             // a b 0 0
+            to.ba = f1;
+            to.aa = f0;
+        }
+        continue;
+    }
+    if (f1 === f0) {
+        to.da = 0;
+        to.aa = f0 + 1;
+        if (f3 === f2) {     // a a b b
+            updated = true;
+            to.ca = 0;
+            to.ba = f2 + 1;
+        } else {             // a a b c
+            to.ca = f3;
+            to.ba = f2;
+        }
+    } else {
+        to.aa = f0;
+        if (f2 === f1) {     // a b b c
+            updated = true;
+            to.da = 0;
+            to.ca = f3;
+            to.ba = f1 + 1;
+        } else {
+            to.ba = f1;
+            if (f2 === f3) { // a b c c
+                updated = true;
+                to.da = 0;
+                to.ca = f2+1;
+            } else {         // a b c d
+                to.da = f3;
+                to.ca = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.ab, f1 = from.bb, f2 = from.cb, f3 = from.db;
+    if (f0 === 0) {
+        if (f1 === 0) {
+            if (f2 === 0) {  // 0 0 0 a
+                if (f3 === 0)
+                    moved = false;
+                f0 = f3;
+                f1 = 0;
+            } else {         // 0 0 a b
+                f0 = f2;
+                f1 = f3;
+            }
+            f2 = 0;
+        } else {             // f1 !== 0 && f0 === 0
+            if (f2 === 0) {  // 0 a 0 b
+                f0 = f1;
+                f1 = f3;
+            } else {         // 0 a b c
+                f0 = f1;
+                f1 = f2;
+                f2 = f3;
+            }
+        }
+        f3 = 0;
+    } else {                 // f0 !== 0
+        if (f1 === 0) {
+            if (f2 === 0) {  // a 0 0 b
+                if (f3 === 0)
+                    moved = false;
+                f1 = f3;
+            } else {         // a 0 b c
+                f1 = f2;
+                f2 = f3;
+            }
+            f3 = 0;
+        } else {             // f1 !== 0 && f0 !== 0
+            if (f2 === 0) {  // a b 0 c
+                if (f3 === 0)
+                    moved = false;
+                f2 = f3;
+                f3 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f1 === 0) {          // a 0 0 0
+        to.db = 0;
+        to.cb = 0;
+        to.bb = 0;
+        to.ab = f0;
+        continue;
+    }
+    if (f2 === 0) {
+        to.db = 0;
+        to.cb = 0;
+        if (f1 === f0) {     // a a 0 0
+            updated = true;
+            to.bb = 0;
+            to.ab = f0 + 1;
+        } else {             // a b 0 0
+            to.bb = f1;
+            to.ab = f0;
+        }
+        continue;
+    }
+    if (f1 === f0) {
+        to.db = 0;
+        to.ab = f0 + 1;
+        if (f3 === f2) {     // a a b b
+            updated = true;
+            to.cb = 0;
+            to.bb = f2 + 1;
+        } else {             // a a b c
+            to.cb = f3;
+            to.bb = f2;
+        }
+    } else {
+        to.ab = f0;
+        if (f2 === f1) {     // a b b c
+            updated = true;
+            to.db = 0;
+            to.cb = f3;
+            to.bb = f1 + 1;
+        } else {
+            to.bb = f1;
+            if (f2 === f3) { // a b c c
+                updated = true;
+                to.db = 0;
+                to.cb = f2+1;
+            } else {         // a b c d
+                to.db = f3;
+                to.cb = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.ac, f1 = from.bc, f2 = from.cc, f3 = from.dc;
+    if (f0 === 0) {
+        if (f1 === 0) {
+            if (f2 === 0) {  // 0 0 0 a
+                if (f3 === 0)
+                    moved = false;
+                f0 = f3;
+                f1 = 0;
+            } else {         // 0 0 a b
+                f0 = f2;
+                f1 = f3;
+            }
+            f2 = 0;
+        } else {             // f1 !== 0 && f0 === 0
+            if (f2 === 0) {  // 0 a 0 b
+                f0 = f1;
+                f1 = f3;
+            } else {         // 0 a b c
+                f0 = f1;
+                f1 = f2;
+                f2 = f3;
+            }
+        }
+        f3 = 0;
+    } else {                 // f0 !== 0
+        if (f1 === 0) {
+            if (f2 === 0) {  // a 0 0 b
+                if (f3 === 0)
+                    moved = false;
+                f1 = f3;
+            } else {         // a 0 b c
+                f1 = f2;
+                f2 = f3;
+            }
+            f3 = 0;
+        } else {             // f1 !== 0 && f0 !== 0
+            if (f2 === 0) {  // a b 0 c
+                if (f3 === 0)
+                    moved = false;
+                f2 = f3;
+                f3 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f1 === 0) {          // a 0 0 0
+        to.dc = 0;
+        to.cc = 0;
+        to.bc = 0;
+        to.ac = f0;
+        continue;
+    }
+    if (f2 === 0) {
+        to.dc = 0;
+        to.cc = 0;
+        if (f1 === f0) {     // a a 0 0
+            updated = true;
+            to.bc = 0;
+            to.ac = f0 + 1;
+        } else {             // a b 0 0
+            to.bc = f1;
+            to.ac = f0;
+        }
+        continue;
+    }
+    if (f1 === f0) {
+        to.dc = 0;
+        to.ac = f0 + 1;
+        if (f3 === f2) {     // a a b b
+            updated = true;
+            to.cc = 0;
+            to.bc = f2 + 1;
+        } else {             // a a b c
+            to.cc = f3;
+            to.bc = f2;
+        }
+    } else {
+        to.ac = f0;
+        if (f2 === f1) {     // a b b c
+            updated = true;
+            to.dc = 0;
+            to.cc = f3;
+            to.bc = f1 + 1;
+        } else {
+            to.bc = f1;
+            if (f2 === f3) { // a b c c
+                updated = true;
+                to.dc = 0;
+                to.cc = f2+1;
+            } else {         // a b c d
+                to.dc = f3;
+                to.cc = f2;
+            }
+        }
+    }
+    var moved = true;
+    var f0 = from.ad, f1 = from.bd, f2 = from.cd, f3 = from.dd;
+    if (f0 === 0) {
+        if (f1 === 0) {
+            if (f2 === 0) {  // 0 0 0 a
+                if (f3 === 0)
+                    moved = false;
+                f0 = f3;
+                f1 = 0;
+            } else {         // 0 0 a b
+                f0 = f2;
+                f1 = f3;
+            }
+            f2 = 0;
+        } else {             // f1 !== 0 && f0 === 0
+            if (f2 === 0) {  // 0 a 0 b
+                f0 = f1;
+                f1 = f3;
+            } else {         // 0 a b c
+                f0 = f1;
+                f1 = f2;
+                f2 = f3;
+            }
+        }
+        f3 = 0;
+    } else {                 // f0 !== 0
+        if (f1 === 0) {
+            if (f2 === 0) {  // a 0 0 b
+                if (f3 === 0)
+                    moved = false;
+                f1 = f3;
+            } else {         // a 0 b c
+                f1 = f2;
+                f2 = f3;
+            }
+            f3 = 0;
+        } else {             // f1 !== 0 && f0 !== 0
+            if (f2 === 0) {  // a b 0 c
+                if (f3 === 0)
+                    moved = false;
+                f2 = f3;
+                f3 = 0;
+            } else {         // else: a b c d
+                moved = false;
+            }
+        }
+    }
+    updated = updated || moved;
+    if (f1 === 0) {          // a 0 0 0
+        to.dd = 0;
+        to.cd = 0;
+        to.bd = 0;
+        to.ad = f0;
+        continue;
+    }
+    if (f2 === 0) {
+        to.dd = 0;
+        to.cd = 0;
+        if (f1 === f0) {     // a a 0 0
+            updated = true;
+            to.bd = 0;
+            to.ad = f0 + 1;
+        } else {             // a b 0 0
+            to.bd = f1;
+            to.ad = f0;
+        }
+        continue;
+    }
+    if (f1 === f0) {
+        to.dd = 0;
+        to.ad = f0 + 1;
+        if (f3 === f2) {     // a a b b
+            updated = true;
+            to.cd = 0;
+            to.bd = f2 + 1;
+        } else {             // a a b c
+            to.cd = f3;
+            to.bd = f2;
+        }
+    } else {
+        to.ad = f0;
+        if (f2 === f1) {     // a b b c
+            updated = true;
+            to.dd = 0;
+            to.cd = f3;
+            to.bd = f1 + 1;
+        } else {
+            to.bd = f1;
+            if (f2 === f3) { // a b c c
+                updated = true;
+                to.dd = 0;
+                to.cd = f2+1;
+            } else {         // a b c d
+                to.dd = f3;
+                to.cd = f2;
+            }
+        }
+    }
+    return updated;
+}