boardgame-core/src/samples/boop/utils.ts

76 lines
2.4 KiB
TypeScript

import {
BOARD_SIZE,
BoopGame,
BoopPart,
BoopState,
PieceType,
PlayerType,
RegionType,
WIN_LENGTH
} from "@/samples/boop/data";
const DIRS = [
[0, 1],
[1, 0],
[1, 1],
[-1, 1]
]
type PT = [number, number];
type Line = PT[];
export function* getLineCandidates(){
for(const [dx, dy] of DIRS){
for(let x = 0; x < BOARD_SIZE; x ++)
for(let y = 0; y < BOARD_SIZE; y ++){
if(!isInBounds(x + dx * (WIN_LENGTH-1), y + dy * (WIN_LENGTH-1))) continue;
const line = [];
for(let i = 0; i < WIN_LENGTH; i ++){
line.push([x + i * dx, y + i * dy]);
}
yield line as Line;
}
}
}
/**
* 检查位置是否在棋盘范围内
*/
export function isInBounds(x: number, y: number): boolean {
return x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE;
}
export function isCellOccupied(game: BoopGame | BoopState, x: number, y: number): boolean {
const id = `${x},${y}`;
return getState(game).regions.board.partMap[id] !== undefined;
}
export function* getNeighborPositions(x: number = 0, y: number = 0){
for(let dx = -1; dx <= 1; dx ++)
for(let dy = -1; dy <= 1; dy ++)
if(dx !== 0 || dy !== 0)
yield [x + dx, y + dy] as PT;
}
export function findPartInRegion(ctx: BoopGame | BoopState, regionId: keyof BoopGame['value']['regions'], type: PieceType, player?: PlayerType): BoopPart | null {
const state = getState(ctx);
if(!regionId){
return Object.values(state.pieces).find(part => match(regionId, part, type, player)) || null;
}
const id = state.regions[regionId].childIds.find(id => match(regionId, state.pieces[id], type, player));
return id ? state.pieces[id] || null : null;
}
function match(regionId: RegionType, part: BoopPart, type: PieceType, player?: PlayerType){
return regionId === part.regionId && part.type === type && (!player || part.player === player);
}
export function findPartAtPosition(ctx: BoopGame | BoopState, row: number, col: number): BoopPart | null {
const state = getState(ctx);
const id = state.regions.board.partMap[`${row},${col}`];
return id ? state.pieces[id] || null : null;
}
function getState(ctx: BoopGame | BoopState): BoopState {
if('value' in ctx){
return ctx.value;
}
return ctx;
}