/** * bubble_shooter.aigameplay — reducer 接口模板 * * Agent 生成实际 reducer 时,必须导出以下函数。 * 此文件是接口约束模板,不是可执行代码。 * * ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ * ⚠️ 重要:渲染层(GameScene)不应直接调用 dispatch() * * dispatch() 是一体化接口,内部完成发射 + 吸附 + 消除 + 掉落后只返回最终状态, * 中间过程(弹道轨迹、消除簇坐标、孤立泡泡掉落路径)全部丢失。 * * 渲染层需要分步动画(泡泡飞行 → 吸附 → 消除爆炸 → 孤立掉落), * 因此必须使用下方的「分步函数」逐步驱动,每步之间插入 Tween / 粒子动画。 * * dispatch() 的用途:无头测试、AI 模拟、快速跳过动画等场景。 * ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */ // ─── 配置类型 ───────────────────────────────────────────────────────────────── export type BubbleColor = number; // 0 ~ colorCount-1 export type BubbleShooterConfig = { /** 棋盘列数,默认 9 */ cols: number; /** 棋盘初始行数,默认 8 */ initialRows: number; /** 泡泡颜色总数,默认 6 */ colorCount: number; /** 触发消除的最小连通数,默认 3 */ minClusterSize: number; /** 是否允许墙壁反弹,默认 true */ wallBounceEnabled: boolean; /** 最大反弹次数,默认 3 */ maxBounces: number; /** 每发射多少次后推进一排,默认 5 */ advanceRowAfterShots: number; /** 失败行(泡泡到达此行时失败),默认 = initialRows + 2 */ loseRow: number; /** 每消除一颗泡泡的得分,默认 100 */ scorePerPop: number; /** 每掉落一颗孤立泡泡的得分,默认 200 */ scorePerDrop: number; }; // ─── 动作类型 ───────────────────────────────────────────────────────────────── export type BubbleShooterAction = | { type: 'shoot'; angle: number } // angle: 度数,0=向右,90=向上,180=向左 | { type: 'reset' }; // ─── 状态类型 ───────────────────────────────────────────────────────────────── export type GridPosition = { row: number; col: number; }; /** 棋盘:board[row][col],null 表示空格 */ export type BubbleBoard = (BubbleColor | null)[][]; export type CannonState = { currentColor: BubbleColor; nextColor: BubbleColor; position: { x: number; y: number }; }; export type BubbleShooterState = { board: BubbleBoard; cannon: CannonState; score: number; /** 已发射次数 */ moves: number; gameOver: boolean; win: boolean; loseReason?: 'bubbles_reach_cannon_line'; }; // ─── 分步操作返回类型 ───────────────────────────────────────────────────────── /** 弹道轨迹点(含反弹折射点) */ export type TrajectoryPoint = { x: number; y: number; /** 是否为墙壁反弹点 */ isBounce: boolean; }; /** 弹道计算结果 */ export type TrajectoryResult = { /** 轨迹关键点列表(起点 → 反弹点1 → ... → 落点) */ points: TrajectoryPoint[]; /** 最终落点网格坐标(吸附前的世界坐标) */ landingPosition: { x: number; y: number }; }; /** 消除簇信息 */ export type ClusterInfo = { /** 连通的同色格子坐标列表 */ cells: GridPosition[]; /** 颜色 */ color: BubbleColor; }; /** popCluster 结果 */ export type PopResult = { newState: BubbleShooterState; /** 被消除的格子列表 */ popped: GridPosition[]; /** 本次消除得分 */ scoreGained: number; }; /** dropOrphans 结果 */ export type DropResult = { finalState: BubbleShooterState; /** 掉落的孤立格子列表 */ dropped: GridPosition[]; /** 本次掉落得分 */ scoreGained: number; }; // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 必须导出的函数 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ─── 初始化 ────────────────────────────────────────────────────────────────── /** * init:根据配置初始化游戏状态,随机生成初始泡泡排列 */ export declare function init(config: BubbleShooterConfig): BubbleShooterState; // ─── 一体化接口(测试/AI 模拟用) ─────────────────────────────────────────── /** * dispatch:接收动作,返回新状态(纯函数,不得修改原 state) * - shoot:发射泡泡,自动执行吸附/消除/掉落/推进一步(一步到位) * - reset:重置到初始状态 * * ⚠️ 仅用于无头测试和 AI 模拟。渲染层请使用下方分步函数。 */ export declare function dispatch(state: BubbleShooterState, action: BubbleShooterAction): BubbleShooterState; /** * getState:返回当前状态快照 */ export declare function getState(state: BubbleShooterState): BubbleShooterState; // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 分步函数(渲染层/场景层必须使用这些函数驱动动画) // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ /** * calculateTrajectory:根据瞄准角度计算泡泡弹道轨迹 * 返回包含反弹折射点的轨迹关键点列表及最终落点世界坐标 * * 场景层根据 TrajectoryResult.points 绘制弹道预览线, * 并驱动泡泡精灵沿轨迹飞行动画 */ export declare function calculateTrajectory( state: BubbleShooterState, angle: number, ): TrajectoryResult; /** * snapToGrid:将世界坐标映射到最近的空网格格子 * 返回目标格子的行列坐标 * * 场景层在泡泡飞行动画结束后调用,确定最终落点 */ export declare function snapToGrid( state: BubbleShooterState, position: { x: number; y: number }, ): GridPosition; /** * findCluster:从指定格子出发,BFS 查找同色连通区域 * 返回包含起始格子的完整连通簇信息 * * 场景层在泡泡落定后调用,size >= minClusterSize 则触发消除 */ export declare function findCluster( board: BubbleBoard, col: number, row: number, ): ClusterInfo; /** * popCluster:消除指定簇,更新棋盘和得分 * 返回消除结果(含更新后的状态和被消除格子列表) * * 场景层根据 PopResult.popped 播放各泡泡爆炸/缩小消失动画 */ export declare function popCluster( state: BubbleShooterState, cluster: ClusterInfo, ): PopResult; /** * findOrphans:从顶部行出发做 BFS,返回所有不可达(孤立)泡泡的坐标列表 * 孤立泡泡 = 无法通过连通路径到达第 0 行的泡泡 * * 场景层在 popCluster 后调用,对孤立泡泡播放悬空抖动 → 掉落动画 */ export declare function findOrphans(board: BubbleBoard): GridPosition[]; /** * dropOrphans:从棋盘移除孤立泡泡,更新得分 * 返回掉落结果(含更新后的状态和掉落格子列表) * * 场景层根据 DropResult.dropped 播放泡泡掉落消失动画 */ export declare function dropOrphans( state: BubbleShooterState, orphans: GridPosition[], ): DropResult; /** * calculateScore:根据消除数量和掉落数量计算得分 * score = popped * scorePerPop + dropped * scorePerDrop */ export declare function calculateScore( popped: number, dropped: number, config: Pick, ): number;