From e58690c9c6703d61bbcbd7fe318fcccab661c747 Mon Sep 17 00:00:00 2001 From: hypercross Date: Sat, 4 Apr 2026 22:11:02 +0800 Subject: [PATCH] fix: impl --- src/samples/boop/commands.ts | 26 ++++++++++++++++---------- src/samples/boop/utils.ts | 20 ++++++++++++++++---- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/samples/boop/commands.ts b/src/samples/boop/commands.ts index 853305c..df87090 100644 --- a/src/samples/boop/commands.ts +++ b/src/samples/boop/commands.ts @@ -32,12 +32,15 @@ async function place(game: BoopGame, row: number, col: number, player: PlayerTyp throw new Error(`No ${type} available in ${player}'s supply`); } + const partId = part.id; + game.produce(state => { // 将棋子从supply移动到棋盘 + const part = state.pieces[partId]; moveToRegion(part, state.regions[player], state.regions.board, [row, col]); }); - return { row, col, player, type, partId: part.id }; + return { row, col, player, type, partId }; } const placeCommand = registry.register( 'place ', place); @@ -52,12 +55,13 @@ async function boop(game: BoopGame, row: number, col: number, type: PieceType) { for (const [dr, dc] of getNeighborPositions()) { const nr = row + dr; const nc = col + dc; - + if (!isInBounds(nr, nc)) continue; - - const part = findPartAtPosition(game, nr, nc); + + // 从 state 中查找,而不是 game + const part = findPartAtPosition(state, nr, nc); if (!part) continue; - + // 小猫不能推动猫 if (type === 'kitten' && part.type === 'cat') continue; @@ -70,7 +74,7 @@ async function boop(game: BoopGame, row: number, col: number, type: PieceType) { // 棋子被推出棋盘,返回玩家supply booped.push(part.id); moveToRegion(part, state.regions.board, state.regions[part.player]); - } else if (!isCellOccupied(game, newRow, newCol)) { + } else if (!isCellOccupied(state, newRow, newCol)) { // 新位置为空,移动过去 booped.push(part.id); moveToRegion(part, state.regions.board, state.regions.board, [newRow, newCol]); @@ -122,21 +126,23 @@ async function checkGraduates(game: BoopGame){ } const player = whites >= WIN_LENGTH ? 'white' : blacks >= WIN_LENGTH ? 'black' : null; if(!player) continue; - + for(const [row, col] of line){ const part = findPartAtPosition(game, row, col); part && toUpgrade.add(part.id); } } - + game.produce(state => { + // 预先收集所有可用的猫(在盒子里的) for(const partId of toUpgrade){ const part = state.pieces[partId]; const [row, col] = part.position; const player = part.player; moveToRegion(part, state.regions.board, null); - - const newPart = findPartInRegion(game, '', 'cat'); + + // 使用下一个可用的猫 + const newPart = findPartInRegion(state, '', 'kitten', player); moveToRegion(newPart || part, null, state.regions[player], [row, col]); } }); diff --git a/src/samples/boop/utils.ts b/src/samples/boop/utils.ts index d784b6c..e101f42 100644 --- a/src/samples/boop/utils.ts +++ b/src/samples/boop/utils.ts @@ -1,4 +1,13 @@ -import {BOARD_SIZE, BoopGame, BoopPart, BoopState, PieceType, WIN_LENGTH} from "@/samples/boop/data"; +import { + BOARD_SIZE, + BoopGame, + BoopPart, + BoopState, + PieceType, + PlayerType, + RegionType, + WIN_LENGTH +} from "@/samples/boop/data"; const DIRS = [ [0, 1], @@ -41,14 +50,17 @@ export function* getNeighborPositions(x: number = 0, y: number = 0){ yield [x + dx, y + dy] as PT; } -export function findPartInRegion(ctx: BoopGame | BoopState, regionId: keyof BoopGame['value']['regions'], type: PieceType): BoopPart | null { +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 => part.type === type && !part.regionId) || null; + return Object.values(state.pieces).find(part => match(regionId, part, type, player)) || null; } - const id = state.regions[regionId].childIds.find(id => state.pieces[id].type === type); + 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);