{
  "_comment": "PGS (PlayCraft Gameplay Schema) 参考骨架 - 2048 滑动合并玩法。Agent 以此为起点编写或 fork 玩法规则。",
  "version": "1.0",
  "gameplayType": "2048",
  "entities": {
    "board": {
      "type": "grid",
      "cols": 4,
      "rows": 4,
      "description": "游戏棋盘，4×4 方格，board[row][col]，null 表示空格"
    },
    "tile": {
      "type": "cell-item",
      "fields": {
        "value": "number (2 的幂次，如 2/4/8/.../2048/4096)",
        "merged": "boolean (本次滑动中是否已合并，防止二次合并)"
      },
      "description": "数字方块，值为 2 的幂次；同值相邻方块可合并为两倍值"
    },
    "score": {
      "type": "counter",
      "initial": 0,
      "description": "当前得分，每次合并得分 = 合并后方块值"
    },
    "best_score": {
      "type": "counter",
      "initial": 0,
      "description": "历史最高分，本地持久化"
    }
  },
  "rules": {
    "slide_direction": {
      "description": "玩家向上/下/左/右滑动，所有方块沿该方向移动到最远空格",
      "directions": ["up", "down", "left", "right"],
      "effectiveIfAnyTileMoves": true,
      "noMoveIfBoardUnchanged": true
    },
    "merge_same_value": {
      "description": "滑动过程中，沿移动方向相邻且同值的方块合并为两倍值；每个方块本次滑动最多参与一次合并",
      "mergeOncePerSlide": true,
      "newValueAfterMerge": "tile.value * 2",
      "scoreGain": "newValue"
    },
    "spawn_new_tile": {
      "description": "每次有效滑动后（棋盘有任何变化），在随机空格生成新方块",
      "values": [2, 4],
      "weights": [0.9, 0.1],
      "trigger": "after_effective_slide"
    },
    "game_over_check": {
      "description": "棋盘满且无相邻同值方块（无有效移动）时游戏结束",
      "trigger": "after_spawn",
      "boardFull": "no empty cells",
      "noValidMoves": "no adjacent same-value pairs in any direction"
    }
  },
  "algorithm": {
    "description": "主循环：swipe → slide_and_merge → spawn → win/lose 检测",
    "steps": [
      "1. 玩家输入滑动方向（up/down/left/right）",
      "2. 按滑动方向对每行/列执行滑动和合并：",
      "   a. 提取行/列中非空方块（按移动方向排列）",
      "   b. 相邻同值且均未合并过的方块合并（merged = true），生成新值",
      "   c. 将结果写回行/列，其余位置填 null",
      "3. 检查棋盘是否发生变化（与滑动前对比）",
      "4. 若无变化 → 忽略此次操作，不生成新方块",
      "5. 若有变化 → 在随机空格生成新方块（2: 90%，4: 10%）",
      "6. 检查胜利：任意方块 value >= winValue（2048）",
      "7. 检查失败：棋盘满 AND 无相邻同值方块（无合法滑动）"
    ]
  },
  "winCondition": {
    "type": "tile_value_reached",
    "value": 2048,
    "description": "棋盘上出现值 >= 2048 的方块时胜利（可设置为继续游戏模式）"
  },
  "loseCondition": {
    "type": "no_valid_moves",
    "description": "棋盘已满（无空格）且四个方向均无相邻同值方块（无有效滑动）"
  },
  "testCases": [
    {
      "id": "tc_basic_slide_merge",
      "description": "基础滑动合并：左滑，两个相邻同值方块合并",
      "initialState": {
        "board": [
          [null, null, 2,    2   ],
          [null, null, null, null],
          [null, null, null, null],
          [null, null, null, null]
        ],
        "score": 0
      },
      "actions": [
        { "type": "slide", "direction": "left" }
      ],
      "expectedState": {
        "board": [
          [4,    null, null, null],
          [null, null, null, null],
          [null, null, null, null],
          [null, null, null, null]
        ],
        "scoreGained": 4,
        "newTileSpawned": true
      }
    },
    {
      "id": "tc_slide_no_merge",
      "description": "滑动但无合并：左滑后方块移位但不合并（不同值），且生成新方块",
      "initialState": {
        "board": [
          [null, 2,    4,    null],
          [null, null, null, null],
          [null, null, null, null],
          [null, null, null, null]
        ],
        "score": 0
      },
      "actions": [
        { "type": "slide", "direction": "left" }
      ],
      "expectedState": {
        "board_row0": [2, 4, null, null],
        "scoreGained": 0,
        "newTileSpawned": true
      }
    },
    {
      "id": "tc_merge_once_per_slide",
      "description": "一次滑动中每组只合并一次：左滑 [2,2,2,2] → [4,4,null,null]，不能合并成 [8]",
      "initialState": {
        "board": [
          [2, 2, 2, 2],
          [null, null, null, null],
          [null, null, null, null],
          [null, null, null, null]
        ],
        "score": 0
      },
      "actions": [
        { "type": "slide", "direction": "left" }
      ],
      "expectedState": {
        "board_row0": [4, 4, null, null],
        "scoreGained": 8,
        "newTileSpawned": true
      }
    },
    {
      "id": "tc_game_over_detection",
      "description": "失败检测：棋盘已满且无相邻同值方块，任何方向滑动均无效",
      "initialState": {
        "board": [
          [2,  4,  2,  4 ],
          [4,  2,  4,  2 ],
          [2,  4,  2,  4 ],
          [4,  2,  4,  2 ]
        ],
        "score": 0
      },
      "actions": [
        { "type": "slide", "direction": "left" }
      ],
      "expectedState": {
        "boardUnchanged": true,
        "gameOver": true,
        "win": false
      }
    },
    {
      "id": "tc_win_condition",
      "description": "胜利条件：合并后出现 2048",
      "initialState": {
        "board": [
          [1024, 1024, null, null],
          [null, null, null, null],
          [null, null, null, null],
          [null, null, null, null]
        ],
        "score": 0
      },
      "actions": [
        { "type": "slide", "direction": "left" }
      ],
      "expectedState": {
        "board_row0_col0": 2048,
        "win": true,
        "gameOver": true,
        "scoreGained": 2048
      }
    }
  ]
}
