Spaces:
Runtime error
Runtime error
| 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 | |
| } | |