diff --git a/src/samples/onitama/commands.ts b/src/samples/onitama/commands.ts index 1e71464..69b34cb 100644 --- a/src/samples/onitama/commands.ts +++ b/src/samples/onitama/commands.ts @@ -34,6 +34,22 @@ function playerHasCard(state: OnitamaState, player: PlayerType, cardName: string return cardList.includes(cardName); } +/** + * 获取卡牌的移动候选项,根据玩家视角进行旋转 + * 黑方需要将卡牌旋转180度 + */ +function getCardMoveCandidates(state: OnitamaState, cardName: string, player: PlayerType) { + const card = state.cards[cardName]; + const candidates = card.moveCandidates; + + // 黑方需要将卡牌旋转180度 + if (player === 'black') { + return candidates.map(m => ({ dx: -m.dx, dy: -m.dy })); + } + + return candidates; +} + /** * 检查移动是否合法 */ @@ -42,7 +58,7 @@ function isValidMove(state: OnitamaState, cardName: string, fromX: number, fromY if (!playerHasCard(state, player, cardName)) { return `玩家 ${player} 不拥有卡牌 ${cardName}`; } - + // 检查起始位置是否有玩家的棋子 const fromPawn = getPawnAtPosition(state, fromX, fromY); if (!fromPawn) { @@ -51,34 +67,35 @@ function isValidMove(state: OnitamaState, cardName: string, fromX: number, fromY if (fromPawn.owner !== player) { return `位置 (${fromX}, ${fromY}) 的棋子不属于玩家 ${player}`; } - + // 检查卡牌是否存在 const card = state.cards[cardName]; if (!card) { return `卡牌 ${cardName} 不存在`; } - + // 计算移动偏移量 const dx = toX - fromX; const dy = toY - fromY; - - // 检查移动是否在卡牌的移动候选项中 - const isValid = card.moveCandidates.some(m => m.dx === dx && m.dy === dy); + + // 检查移动是否在卡牌的移动候选项中(黑方需要旋转180度) + const candidates = getCardMoveCandidates(state, cardName, player); + const isValid = candidates.some(m => m.dx === dx && m.dy === dy); if (!isValid) { return `卡牌 ${cardName} 不支持移动 (${dx}, ${dy})`; } - + // 检查目标位置是否在棋盘内 if (!isInBounds(toX, toY)) { return `目标位置 (${toX}, ${toY}) 超出棋盘范围`; } - + // 检查目标位置是否有己方棋子 const toPawn = getPawnAtPosition(state, toX, toY); if (toPawn && toPawn.owner === player) { return `目标位置 (${toX}, ${toY}) 已有己方棋子`; } - + return null; } @@ -236,26 +253,27 @@ const checkWin = registry.register({ */ function getAvailableMoves(state: OnitamaState, player: PlayerType): Array<{card: string, fromX: number, fromY: number, toX: number, toY: number}> { const moves: Array<{card: string, fromX: number, fromY: number, toX: number, toY: number}> = []; - + // 获取玩家的所有卡牌 const cardNames = player === 'red' ? state.redCards : state.blackCards; - + // 获取玩家的所有棋子 const playerPawns = Object.values(state.pawns).filter(p => p.owner === player && p.regionId === 'board'); - + // 对于每张卡牌 for (const cardName of cardNames) { - const card = state.cards[cardName]; - + // 获取旋转后的移动候选项(黑方需要旋转180度) + const candidates = getCardMoveCandidates(state, cardName, player); + // 对于每个棋子 for (const pawn of playerPawns) { const [fromX, fromY] = pawn.position; - + // 对于卡牌的每个移动 - for (const move of card.moveCandidates) { + for (const move of candidates) { const toX = fromX + move.dx; const toY = fromY + move.dy; - + // 检查移动是否合法 if (isInBounds(toX, toY)) { const targetPawn = getPawnAtPosition(state, toX, toY); @@ -267,7 +285,7 @@ function getAvailableMoves(state: OnitamaState, player: PlayerType): Array<{card } } } - + return moves; }