import {IGameContext} from "@/core/game"; import {RegicideState} from "@/samples/regicide/state"; import {buildEnemyDeck, buildTavernDeck, createAllCards, getPlayerHandRegionId} from "@/samples/regicide/utils"; import {INITIAL_HAND_SIZE} from "@/samples/regicide/constants"; import {Enemy, PlayerType, RegicideCard} from "@/samples/regicide/types"; export type RegicideGame = IGameContext; /** * 初始化游戏设置 * @param game 游戏上下文 * @param playerCount 玩家数量(1-4) * @param seed 随机种子(可选) */ export async function setupGame(game: RegicideGame, playerCount: number, seed?: number) { if (playerCount < 1 || playerCount > 4) { throw new Error('玩家数量必须为 1-4 人'); } if (seed) { // RNG seeding handled by game context } // 创建所有卡牌 const allCards = createAllCards(); // 构建敌人牌堆(J/Q/K) const enemyDeck = buildEnemyDeck(game._rng); // 构建酒馆牌堆(A-10) const tavernDeck = buildTavernDeck(game._rng); // 初始化游戏状态 await game.produceAsync(state => { state.cards = allCards; state.playerCount = playerCount; state.currentPlayerIndex = 0; state.enemyDeck = enemyDeck; // 设置酒馆牌堆区域 for (const card of tavernDeck) { card.regionId = 'tavernDeck'; state.regions.tavernDeck.childIds.push(card.id); } // 设置敌人牌堆区域(只存储ID,敌人是独立对象) state.regions.enemyDeck.childIds = enemyDeck.map(e => e.id); // 给每个玩家发牌 const players: PlayerType[] = ['player1', 'player2', 'player3', 'player4']; for (let i = 0; i < playerCount; i++) { const player = players[i]; const regionId = getPlayerHandRegionId(player); for (let j = 0; j < INITIAL_HAND_SIZE; j++) { if (tavernDeck.length === 0) break; const card = tavernDeck.shift()!; card.regionId = regionId; state.playerHands[player].push(card.id); const region = state.regions[regionId as keyof typeof state.regions]; region.childIds.push(card.id); } } // 翻开第一个敌人 if (enemyDeck.length > 0) { const firstEnemy = enemyDeck.shift()!; state.currentEnemy = firstEnemy; } }); } /** * 启动游戏主循环 */ export async function start(game: RegicideGame) { const state = game.value; // 检查游戏是否已设置 if (!state.currentEnemy) { throw new Error('请先调用 setupGame 初始化游戏'); } const players: PlayerType[] = ['player1', 'player2', 'player3', 'player4']; // 主游戏循环 while (state.phase === 'playing') { const currentPlayerIndex = state.currentPlayerIndex; const currentPlayer = players[currentPlayerIndex]; // 检查当前玩家是否有手牌 const currentHand = state.playerHands[currentPlayer]; if (currentHand.length === 0) { // 玩家没有手牌,跳过回合 await game.produceAsync(state => { state.currentPlayerIndex = (state.currentPlayerIndex + 1) % state.playerCount; }); continue; } // 等待玩家输入(出牌或让过) // 这里需要外部通过 prompt 系统获取输入 // 实际使用时由 UI 或测试代码提供输入 // 循环会在外部调用 play/pass 命令后继续 // 当 phase 变为 'victory' 或 'defeat' 时退出 break; } return game.value; } /** * 处理完整的玩家回合 */ export async function playTurn(game: RegicideGame, player: PlayerType, action: 'play' | 'pass', cardId?: string, secondCardId?: string) { const state = game.value; if (state.phase !== 'playing') { return {success: false, error: '游戏已结束'}; } if (!state.currentEnemy) { return {success: false, error: '没有活跃的敌人'}; } let playResult: any; // 执行玩家动作 if (action === 'play' && cardId) { // 检查是否是A配合另一张牌 const card = state.cards[cardId]; if (card.rank === 'A' && secondCardId) { playResult = await game.run(`play-with-a ${player} ${cardId} ${secondCardId}`); } else { playResult = await game.run(`play ${player} ${cardId}`); } } else { // 让过 playResult = await game.run(`pass ${player}`); } if (!playResult.success) { return playResult; } // 检查敌人是否被击败 const checkResult = await game.run<{defeated: boolean; currentEnemy?: any; nextEnemy?: any; defeatedEnemy?: any; enemiesRemaining?: number}>('check-enemy'); if (!checkResult.success) { return checkResult; } // 如果敌人未被击败,处理反击 if (!checkResult.result.defeated) { // 反击逻辑需要玩家选择弃牌,这里返回状态让外部处理 return { success: true, result: { playResult: playResult.result, enemyDefeated: false, needsDiscard: true, enemyAttack: state.currentEnemy.value, playerHand: state.playerHands[player] } }; } // 敌人被击败,检查是否还有更多敌人 if (state.enemyDeck.length === 0 && state.currentEnemy && state.currentEnemy.hp <= 0) { await game.produceAsync(state => { state.phase = 'victory'; state.winner = true; }); return { success: true, result: { playResult: playResult.result, enemyDefeated: true, gameWon: true } }; } // 切换到下一个玩家 await game.run('next-turn'); return { success: true, result: { playResult: playResult.result, enemyDefeated: true, nextEnemy: state.currentEnemy } }; } /** * 处理反击阶段的弃牌 */ export async function handleCounterattack(game: RegicideGame, player: PlayerType, discardCardIds: string[]) { const result = await game.run(`counterattack ${player} ${JSON.stringify(discardCardIds)}`); if (!result.success) { // 弃牌失败(点数和不足),游戏失败 await game.produceAsync(state => { state.phase = 'defeat'; state.winner = false; }); return result; } // 弃牌成功,切换到下一个玩家 await game.run('next-turn'); return result; } /** * 获取当前游戏状态摘要 */ export function getGameStatus(game: RegicideGame) { const state = game.value; return { phase: state.phase, currentPlayer: ['player1', 'player2', 'player3', 'player4'][state.currentPlayerIndex], currentEnemy: state.currentEnemy ? { ...state.currentEnemy, hpPercent: Math.round((state.currentEnemy.hp / state.currentEnemy.maxHp) * 100) } : null, enemiesRemaining: state.enemyDeck.length, tavernDeckCount: state.regions.tavernDeck.childIds.length, discardPileCount: state.regions.discardPile.childIds.length, playerHands: Object.fromEntries( Object.entries(state.playerHands).map(([player, hand]) => [player, hand.length]) ), winner: state.winner }; }