From 233160e17ff451e52621b10d5d00d99e7800c2db Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Sun, 1 Jul 2018 21:12:11 +0200 Subject: Interactor --- interactor/board.js | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 interactor/board.js (limited to 'interactor/board.js') 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; +} -- cgit v1.2.3-54-g00ecf