/** * match3_core.aigameplay — reducer 接口模板 * * Agent 生成实际 reducer 时,必须导出以下函数。 * 此文件是接口约束模板,不是可执行代码。 * * ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ * ⚠️ 重要:渲染层(GameScene)不应直接调用 dispatch() * * dispatch() 是一体化接口,内部跑完整个 cascade 循环后只返回最终状态, * 中间过程(哪些格子被消除、哪些格子下落、新补充了什么)全部丢失。 * * 渲染层需要分步动画(消除动画 → 下落动画 → 补充动画 → 检查连消), * 因此必须使用下方的「分步函数」逐步驱动,每步之间插入 Tween 动画。 * * dispatch() 的用途:无头测试、AI 模拟、快速跳过动画等场景。 * ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */ // ─── 配置类型 ───────────────────────────────────────────────────────────────── export type Match3Config = { /** 棋盘列数,默认 8 */ cols: number; /** 棋盘行数,默认 8 */ rows: number; /** 元素颜色/类型数量,默认 6 */ colorCount: number; /** 初始步数 */ initialMoves: number; /** 目标分数(score_goal 模式) */ goalScore?: number; /** 倒计时秒数(time_clear 模式) */ timeLimitSeconds?: number; /** 每格消除基础得分 */ scorePerTile: number; }; // ─── 动作类型 ───────────────────────────────────────────────────────────────── export type Match3Action = | { type: 'swap'; from: [col: number, row: number]; to: [col: number, row: number] } | { type: 'tick'; deltaMs: number } // 倒计时模式下每帧调用 | { type: 'reset' }; // ─── 状态类型 ───────────────────────────────────────────────────────────────── export type TileColor = number; // 0 ~ colorCount-1,null 表示空格 export type Match3State = { /** 棋盘格子,board[col][row] */ board: (TileColor | null)[][]; /** 当前得分 */ score: number; /** 剩余步数 */ movesLeft: number; /** 剩余时间(毫秒,倒计时模式) */ timeLeftMs?: number; /** 游戏是否结束 */ gameOver: boolean; /** 是否胜利 */ win: boolean; /** 上一次 swap 是否因无效而回退 */ lastSwapReverted: boolean; /** 上一次操作触发的连消次数 */ lastCascadeCount: number; }; // ─── 分步操作返回类型 ───────────────────────────────────────────────────────── /** 匹配结果 */ export type MatchResult = { /** 被匹配到的格子坐标列表 */ cells: Array<{ col: number; row: number }>; /** 连续匹配的数量(3/4/5+) */ count: number; }; /** 重力下落:某格子从 fromRow 下落到 toRow */ export type FallMove = { col: number; fromRow: number; toRow: number; }; /** 新补充的棋子 */ export type RefillTile = { col: number; row: number; color: TileColor; }; // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 必须导出的函数 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ─── 初始化 ────────────────────────────────────────────────────────────────── /** * init:根据配置初始化游戏状态,随机填满棋盘(确保初始无三连) */ export declare function init(config: Match3Config): Match3State; // ─── 一体化接口(测试/AI 模拟用) ─────────────────────────────────────────── /** * dispatch:接收动作,返回新状态(纯函数,不得修改原 state) * - swap:交换两格,检测消除、计分、下落、补充、连消(一步到位) * - tick:更新倒计时(time_clear 模式) * - reset:重置到初始状态 * * ⚠️ 仅用于无头测试和 AI 模拟。渲染层请使用下方分步函数。 */ export declare function dispatch(state: Match3State, action: Match3Action): Match3State; /** * getState:返回当前状态快照(通常直接返回 state,供外部读取) */ export declare function getState(state: Match3State): Match3State; // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 分步函数(渲染层/场景层必须使用这些函数驱动动画) // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ /** * trySwap:仅验证交换是否有效,不执行后续 cascade。 * 返回交换后的棋盘副本和第一轮匹配结果。 * * 场景层在 swap 动画播放完毕后调用此函数: * - valid=false → 播放回退动画 * - valid=true → 继续调用 removeMatches → animateElimination → applyGravity → ... */ export declare function trySwap( state: Match3State, from: [col: number, row: number], to: [col: number, row: number], ): { valid: boolean; board: (TileColor | null)[][]; matches: MatchResult[] }; /** * findAllMatches:检测棋盘上所有 ≥3 连匹配 * 场景层在 refill 动画结束后调用,检查是否有连消 */ export declare function findAllMatches( board: (TileColor | null)[][], cols: number, rows: number, ): MatchResult[]; /** * removeMatches:从棋盘移除匹配的格子(置为 null) * 场景层在消除动画播放期间/之后调用,同步逻辑状态 */ export declare function removeMatches( board: (TileColor | null)[][], matches: MatchResult[], ): Set; // 返回被移除的格子 key "col,row" /** * applyGravity:执行重力下落,返回每个移动的格子信息 * 场景层根据 FallMove[] 播放下落 Tween 动画 */ export declare function applyGravity( board: (TileColor | null)[][], cols: number, rows: number, ): FallMove[]; /** * refillBoard:从顶部补充空位,返回新格子信息 * 场景层根据 RefillTile[] 创建新精灵并播放滑入动画 */ export declare function refillBoard( board: (TileColor | null)[][], cols: number, rows: number, colorCount: number, ): RefillTile[]; /** * calculateMatchScore:计算一轮匹配的得分 */ export declare function calculateMatchScore( matches: MatchResult[], config: Match3Config, ): number; /** * hasValidMoves:检查棋盘是否还有可用的合法交换 * 若无可用移动则需要洗牌 */ export declare function hasValidMoves(state: Match3State): boolean;