Skip to content

Commit

Permalink
wip count
Browse files Browse the repository at this point in the history
  • Loading branch information
h908714124 committed Aug 4, 2024
1 parent f0799bb commit 066cf47
Showing 1 changed file with 170 additions and 0 deletions.
170 changes: 170 additions & 0 deletions src/main/client/src/model/count.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import {
PointQueue,
} from "./PointQueue.js"
import {
PointList,
} from "./PointList.js"
import {
PointSet,
} from "./PointSet.js"
import {
hasStone,
BLACK,
WHITE,
COLORS,
TERRITORY_B,
TERRITORY_W,
TERRITORY,
REMOVED_B,
REMOVED_W,
} from "../util.js"

function findStone(board, xx, yy) {
if (hasStone(board[yy][xx])) {
return board[yy][xx]
}
let dim = board.length
let pointsChecked = new PointSet(dim)
pointsChecked.add(xx, yy)
let pointsToCheck = new PointQueue(dim)
pointsToCheck.offer(xx, yy)
while (!pointsToCheck.isEmpty()) {
let ptId = pointsToCheck.poll()
let y = Math.trunc(ptId / dim)
let x = ptId % dim
if (hasStone(board[y][x])) {
return board[y][x]
}
if (y > 0 && !pointsChecked.has(x, y - 1)) {
pointsChecked.add(x, y - 1)
pointsToCheck.offer(x, y - 1)
}
if (y < dim - 1 && !pointsChecked.has(x, y + 1)) {
pointsChecked.add(x, y + 1)
pointsToCheck.offer(x, y + 1)
}
if (x > 0 && !pointsChecked.has(x - 1, y)) {
pointsChecked.add(x - 1, y)
pointsToCheck.offer(x - 1, y)
}
if (x < dim - 1 && !pointsChecked.has(x + 1, y)) {
pointsChecked.add(x + 1, y)
pointsToCheck.offer(x + 1, y)
}
}
return 0
}

function colorEmptyTerritory(board, acc, xx, yy) {
if (hasStone(board[yy][xx])) {
acc[yy][xx] = board[yy][xx]
return
}
let found = findStone(board, xx, yy)
if (found === 0) { // empty board
for (let row of acc) {
row.fill(0)
}
return
}
let disputed = false
let opponentColor = found ^ COLORS
let dim = board.length
let territory = new PointList(dim)
let pointsToCheck = new PointQueue(dim)
acc[yy][xx] = getTerritoryMarker(found, board[yy][xx])
pointsToCheck.offer(xx, yy)
while (!pointsToCheck.isEmpty()) {
let ptId = pointsToCheck.poll()
let y = Math.trunc(ptId / dim)
let x = ptId % dim
territory.add(x, y)
if (y > 0) {
let c = board[y - 1][x]
disputed |= c === opponentColor
if (isEmpty(c) && acc[y - 1][x] === -1) {
acc[y - 1][x] = getTerritoryMarker(found, c)
pointsToCheck.offer(x, y - 1)
}
}
if (y < dim - 1) {
let c = board[y + 1][x]
disputed |= c === opponentColor
if (isEmpty(c) && acc[y + 1][x] === -1) {
acc[y + 1][x] = getTerritoryMarker(found, c)
pointsToCheck.offer(x, y + 1)
}
}
if (x > 0) {
let c = board[y][x - 1]
disputed |= c === opponentColor
if (isEmpty(c) && acc[y][x - 1] === -1) {
acc[y][x - 1] = getTerritoryMarker(found, c)
pointsToCheck.offer(x - 1, y)
}
}
if (x < dim - 1) {
let c = board[y][x + 1]
disputed |= c === opponentColor
if (isEmpty(c) && acc[y][x + 1] === -1) {
acc[y][x + 1] = getTerritoryMarker(found, c)
pointsToCheck.offer(x + 1, y)
}
}
}
if (disputed) {
territory.forEach((x, y) => acc[y][x] = board[y][x] & ~TERRITORY)
}
}

export function count(board) {
let acc = createAcc(board.length)
for (let y = 0; y < board.length; y++) {
let row = board[y]
for (let x = 0; x < row.length; x++) {
if (acc[y][x] === -1) {
colorEmptyTerritory(board, acc, x, y)
}
}
}
return acc
}

function getTerritoryMarker(found, empty) {
if ((empty & asRemoved(found)) !== 0) {
return found // resurrect
}
return asTerritory(found) | (empty & ~TERRITORY)
}

function asTerritory(color) {
if (color === BLACK) {
return TERRITORY_B
}
if (color === WHITE) {
return TERRITORY_W
}
return color
}

function asRemoved(color) {
if (color === BLACK) {
return REMOVED_B
}
if (color === WHITE) {
return REMOVED_W
}
return color
}

function createAcc(dim) {
let result = Array(dim)
for (let y = 0; y < dim; y++) {
result[y] = new Int32Array(dim).fill(-1)
}
return result
}

function isEmpty(color) {
return (color & COLORS) === 0
}

0 comments on commit 066cf47

Please sign in to comment.