76 lines
2.4 KiB
TypeScript
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;
|
|
} |