caro5 / shared /bot /WinMasks.ts
Pedro de Carvalho
Add bot
4d74f52
Raw
History Blame Contribute Delete
2.42 kB
import { isBoardCoordInBounds } from '../board.ts'
export type WinDirection = readonly [number, number]
export interface WinMask {
readonly cellIndices: readonly number[]
readonly beforeIndex: number | null
readonly afterIndex: number | null
readonly direction: WinDirection
readonly words: Uint32Array
}
export interface WinMaskSet {
readonly boardSize: number
readonly cellCount: number
readonly wordCount: number
readonly masks: readonly WinMask[]
readonly byCellIndex: readonly (readonly WinMask[])[]
}
const DIRECTIONS: readonly WinDirection[] = [[1, 0], [0, 1], [1, 1], [1, -1]]
const cache = new Map<number, WinMaskSet>()
export function getWinMasks(boardSize: number): WinMaskSet {
const cached = cache.get(boardSize)
if (cached) return cached
const cellCount = boardSize * boardSize
const wordCount = Math.ceil(cellCount / 32)
const masks: WinMask[] = []
const byCellIndex: WinMask[][] = Array.from({ length: cellCount }, () => [])
for (const direction of DIRECTIONS) {
const [dx, dy] = direction
for (let y = 0; y < boardSize; y++) {
for (let x = 0; x < boardSize; x++) {
const endX = x + dx * 4
const endY = y + dy * 4
if (!isBoardCoordInBounds(endX, endY, boardSize)) continue
const cellIndices: number[] = []
const words = new Uint32Array(wordCount)
for (let i = 0; i < 5; i++) {
const index = toIndex(x + dx * i, y + dy * i, boardSize)
cellIndices.push(index)
words[index >>> 5] |= 1 << (index & 31)
}
const beforeX = x - dx
const beforeY = y - dy
const afterX = x + dx * 5
const afterY = y + dy * 5
const mask: WinMask = {
cellIndices,
beforeIndex: isBoardCoordInBounds(beforeX, beforeY, boardSize)
? toIndex(beforeX, beforeY, boardSize)
: null,
afterIndex: isBoardCoordInBounds(afterX, afterY, boardSize)
? toIndex(afterX, afterY, boardSize)
: null,
direction,
words,
}
masks.push(mask)
for (const index of cellIndices) byCellIndex[index].push(mask)
}
}
}
const result: WinMaskSet = { boardSize, cellCount, wordCount, masks, byCellIndex }
cache.set(boardSize, result)
return result
}
function toIndex(x: number, y: number, boardSize: number): number {
return y * boardSize + x
}