summaryrefslogtreecommitdiff
path: root/interactor/board.js
diff options
context:
space:
mode:
Diffstat (limited to 'interactor/board.js')
-rw-r--r--interactor/board.js160
1 files changed, 160 insertions, 0 deletions
diff --git a/interactor/board.js b/interactor/board.js
new file mode 100644
index 0000000..35ba93a
--- /dev/null
+++ b/interactor/board.js
@@ -0,0 +1,160 @@
+function colourValue(value) {
+ return value < 4;
+}
+
+function parsePosition(str) {
+ if (str.length != 2) return null;
+ var a = str.toUpperCase().charCodeAt(0), b = str.charCodeAt(1);
+ if (a < 65 || a > 65+25) return null;
+ if (b < 48 || b > 48+9) return null;
+ return N * (N - (b - 48)) + a - 65;
+}
+
+function parseMove(str) {
+ if (str.length != 5) return null;
+ if (str[2] != "-" && str[2] != " ") return null;
+
+ var from, to;
+ from = parsePosition(str.substr(0, 2));
+ if (from != null) {
+ to = parsePosition(str.substr(3, 2));
+ if (to != null) {
+ return {from: from, to: to};
+ }
+ }
+
+ return null;
+}
+
+function stringifyPosition(pos) {
+ return String.fromCharCode(65 + pos % N) + String.fromCharCode(48 + N - ~~(pos / N));
+}
+
+function stringifyMove(mv) {
+ return stringifyPosition(mv.from) + '-' + stringifyPosition(mv.to);
+}
+
+function stringifyMoveExt(mv, captures) {
+ var s = stringifyMove(mv);
+ if (captures.length > 0) {
+ for (var i = 0; i < captures.length; i++) {
+ s += (i == 0 ? "x" : "/") + stringifyPosition(captures[i]);
+ }
+ }
+ return s;
+}
+
+
+function stoneFlankedH(pos, by) {
+ if (by & (WHITE|KING)) by = WHITE|KING;
+ return ((board[pos-1] & by) || (pos-1 == BOARDMID && board[BOARDMID] == EMPTY)) &&
+ ((board[pos+1] & by) || (pos+1 == BOARDMID && board[BOARDMID] == EMPTY));
+}
+
+function stoneFlankedV(pos, by) {
+ if (by & (WHITE|KING)) by = WHITE|KING;
+ return ((board[pos-N] & by) || (pos-N == BOARDMID && board[BOARDMID] == EMPTY)) &&
+ ((board[pos+N] & by) || (pos+N == BOARDMID && board[BOARDMID] == EMPTY));
+}
+
+function kingEncircled(pos) {
+ if (pos == BOARDMID) {
+ return board[pos-1] == BLACK && board[pos+1] == BLACK &&
+ board[pos-N] == BLACK && board[pos+N] == BLACK;
+ } else if (pos == BOARDMID-1) {
+ return board[pos-1] == BLACK && board[pos-N] == BLACK && board[pos+N] == BLACK;
+ } else if (pos == BOARDMID+1) {
+ return board[pos+1] == BLACK && board[pos-N] == BLACK && board[pos+N] == BLACK;
+ } else if (pos == BOARDMID-N) {
+ return board[pos-1] == BLACK && board[pos+1] == BLACK && board[pos-N] == BLACK;
+ } else if (pos == BOARDMID+N) {
+ return board[pos-1] == BLACK && board[pos+1] == BLACK && board[pos+N] == BLACK;
+ } else {
+ var x = pos % N, y = ~~(pos / N);
+ return (x > 0 && x < N-1 && board[pos-1] == BLACK && board[pos+1] == BLACK) ||
+ (y > 0 && y < N-1 && board[pos-N] == BLACK && board[pos+N] == BLACK);
+ }
+}
+
+function applyMove(mv) {
+ board[mv.to] = board[mv.from];
+ board[mv.from] = EMPTY;
+ var i = mv.to;
+ var x = i % N, y = ~~(i / N);
+
+ var captures = [];
+
+ if (x > 1 && board[i-1] != EMPTY && colourValue(board[i-1]) != colourValue(board[i])) {
+ if (board[i-1] == KING ? kingEncircled(i-1) : stoneFlankedH(i-1, board[i])) {
+ board[i-1] = EMPTY;
+ captures.push(i-1);
+ }
+ }
+
+ if (y > 1 && board[i-N] != EMPTY && colourValue(board[i-N]) != colourValue(board[i])) {
+ if (board[i-N] == KING ? kingEncircled(i-N) : stoneFlankedV(i-N, board[i])) {
+ board[i-N] = EMPTY;
+ captures.push(i-N);
+ }
+ }
+
+ if (x < N-2 && board[i+1] != EMPTY && colourValue(board[i+1]) != colourValue(board[i])) {
+ if (board[i+1] == KING ? kingEncircled(i+1) : stoneFlankedH(i+1, board[i])) {
+ board[i+1] = EMPTY;
+ captures.push(i+1);
+ }
+ }
+
+ if (y < N-2 && board[i+N] != EMPTY && colourValue(board[i+N]) != colourValue(board[i])) {
+ if (board[i+N] == KING ? kingEncircled(i+N) : stoneFlankedV(i+N, board[i])) {
+ board[i+N] = EMPTY;
+ captures.push(i+N);
+ }
+ }
+
+ return captures;
+}
+
+function checkWin() {
+ for (var x = 0; x < N; x++) if (board[x] == KING) return 1;
+ for (var y = 0; y < N; y++) if (board[N * y] == KING) return 1;
+ for (var x = 0; x < N; x++) if (board[N * (N-1) + x] == KING) return 1;
+ for (var y = 0; y < N; y++) if (board[N * y + N-1] == KING) return 1;
+
+ for (var i = 0; i < N * N; i++) {
+ if (board[i] == KING) return 0;
+ }
+
+ return -1;
+}
+
+function isValid(mv) {
+ if (mv.from < 0 || mv.from >= N * N || mv.to < 0 || mv.to >= N * N) return false;
+ if (mv.from == mv.to) return false;
+ if (board[mv.from] == EMPTY || board[mv.to] != EMPTY) return false;
+
+ if (mv.to == BOARDMID) return false;
+
+ var x1 = mv.from % N, y1 = ~~(mv.from / N);
+ var x2 = mv.to % N, y2 = ~~(mv.to / N);
+ if (x1 != x2 && y1 != y2) return false;
+
+ if (x1 == x2) {
+ var delta = y2 < y1 ? -1 : 1;
+ for (var y = y1 + delta; y != y2; y += delta) {
+ if (board[N * y + x1] != EMPTY) return false;
+ }
+ } else {
+ var delta = x2 < x1 ? -1 : 1;
+ for (var x = x1 + delta; x != x2; x += delta) {
+ if (board[N * y1 + x] != EMPTY) return false;
+ }
+ }
+
+ return true;
+}
+
+function isValidForPlayer(mv, player) {
+ var mask = player == 1 ? WHITE|KING : BLACK;
+ return isValid(mv) && (board[mv.from] & mask) != 0;
+}