{
  "_comment": "PGS (PlayCraft Gameplay Schema) 参考骨架 - 飞刀投掷玩法。Agent 以此为起点编写或 fork 玩法规则。",
  "version": "1.0",
  "gameplayType": "knife_hit",
  "entities": {
    "target": {
      "type": "rotating-object",
      "description": "旋转的圆形木桩/水果，飞刀插入其中",
      "fields": {
        "radius":             { "type": "number",  "value": 120, "description": "木桩半径（像素）" },
        "rotation_speed":     { "type": "number",  "description": "当前旋转速度（度/秒），正=顺时针，负=逆时针" },
        "rotation_direction": { "type": "number",  "values": [1, -1], "description": "1=顺时针，-1=逆时针" },
        "current_angle":      { "type": "number",  "range": [0, 360], "description": "当前旋转角度（度）" },
        "inserted_knives":    { "type": "array",   "description": "已插入飞刀的角度列表 number[]" }
      }
    },
    "knives_queue": {
      "type": "counter",
      "description": "当前关卡剩余可投飞刀数量",
      "fields": {
        "remaining_count": { "type": "integer", "description": "剩余飞刀数" },
        "total_count":     { "type": "integer", "description": "本关总飞刀数" }
      }
    },
    "score": {
      "type": "counter",
      "initial": 0,
      "description": "当前得分"
    },
    "apples": {
      "type": "collectibles",
      "description": "木桩上的苹果/水果，可被飞刀收集",
      "fields": {
        "id":              { "type": "integer" },
        "angle":           { "type": "number",  "description": "苹果在木桩上的固定角度（相对于木桩，度）" },
        "angular_radius":  { "type": "number",  "value": 8, "description": "收集判定角度半径（度）" },
        "collected":       { "type": "boolean", "default": false }
      }
    },
    "level": {
      "type": "level-config",
      "description": "关卡配置",
      "fields": {
        "level_number":   { "type": "integer" },
        "knives_required": { "type": "integer", "description": "本关需要成功投出的飞刀数" },
        "rotation_speed": { "type": "number",   "description": "本关旋转速度（度/秒）" },
        "phase_changes":  { "type": "array",    "description": "旋转方向变化阶段 [{at_knife: number, new_direction: 1|-1}]" }
      }
    }
  },
  "rules": {
    "throw_knife": {
      "description": "玩家点击投出飞刀：飞刀以当前木桩旋转角度插入",
      "trigger": "player_tap",
      "effect": [
        "新飞刀插入角度 = target.current_angle",
        "检测碰撞：若与任何已插飞刀角度差 < minSeparationAngle → 游戏结束",
        "检测苹果：若命中苹果角度范围内 → 收集苹果，加苹果分",
        "成功：target.inserted_knives.push(current_angle)；knives_queue.remaining_count--；score += knifeScore"
      ],
      "minSeparationAngle": 15,
      "knifeScore": 10
    },
    "collision_check": {
      "description": "碰撞检测：新飞刀角度与所有已插飞刀的最小角距 < minSeparationAngle",
      "formula": "angularDistance(a, b) = min(|a-b|, 360-|a-b|)",
      "collision_condition": "min(angularDistance(newAngle, knife) for knife in inserted_knives) < minSeparationAngle",
      "result_on_collision": "gameOver = true"
    },
    "apple_collect": {
      "description": "苹果收集：飞刀插入角度与苹果角度的角距 < apple.angular_radius",
      "effect": "apple.collected = true; score += appleBonusScore",
      "appleBonusScore": 50
    },
    "rotation_update": {
      "description": "每帧更新木桩旋转角度",
      "formula": "current_angle = (current_angle + rotation_speed × rotation_direction × dt) mod 360"
    },
    "level_advance": {
      "description": "所有飞刀成功投出（remaining_count == 0）且无碰撞，过关",
      "trigger": "knives_queue.remaining_count == 0"
    }
  },
  "algorithm": {
    "description": "主循环：rotate → player_tap → collision_check → insert → apple_check → level_check",
    "steps": [
      "1. 每帧更新木桩旋转角度：current_angle += rotation_speed × direction × dt",
      "2. 玩家点击：捕获当前木桩角度作为插入角度",
      "3. 碰撞检测：检查新角度与所有已插飞刀的角距，任意 < minSeparationAngle → 游戏结束",
      "4. 苹果检测：检查新角度是否命中任意未收集苹果",
      "5. 插入飞刀：插入成功，remaining_count--，score += knifeScore",
      "6. 检查旋转方向变化：根据 phase_changes 配置切换方向",
      "7. 检查过关：remaining_count == 0 → 显示过关",
      "8. 进入下一关或显示最终结果"
    ]
  },
  "winCondition": {
    "type": "all_knives_thrown",
    "description": "成功投出关卡要求的所有飞刀（remaining_count == 0）且无碰撞"
  },
  "loseCondition": {
    "type": "knife_collision",
    "description": "新投出的飞刀与已插入的飞刀发生碰撞（角距 < minSeparationAngle）"
  },
  "testCases": [
    {
      "id": "tc_successful_throw",
      "description": "成功投刀：新飞刀插入角度与已有飞刀角距 > minSeparationAngle",
      "initialState": {
        "target": {
          "current_angle": 90,
          "rotation_speed": 90,
          "rotation_direction": 1,
          "inserted_knives": [0, 180]
        },
        "knives_queue": { "remaining_count": 5, "total_count": 5 },
        "score": 10,
        "apples": []
      },
      "actions": [
        { "type": "throw_knife" }
      ],
      "expectedState": {
        "target.inserted_knives": [0, 90, 180],
        "knives_queue.remaining_count": 4,
        "score": 20,
        "gameOver": false
      }
    },
    {
      "id": "tc_collision_game_over",
      "description": "碰撞失败：新飞刀角度与已有飞刀角距 < 15度",
      "initialState": {
        "target": {
          "current_angle": 5,
          "rotation_speed": 90,
          "rotation_direction": 1,
          "inserted_knives": [0, 90, 180, 270]
        },
        "knives_queue": { "remaining_count": 3, "total_count": 5 },
        "score": 20,
        "apples": []
      },
      "actions": [
        { "type": "throw_knife" }
      ],
      "expectedState": {
        "gameOver": true,
        "win": false,
        "loseReason": "knife_collision"
      }
    },
    {
      "id": "tc_apple_bonus",
      "description": "收集苹果：飞刀命中苹果位置，获得额外分数",
      "initialState": {
        "target": {
          "current_angle": 135,
          "rotation_speed": 45,
          "rotation_direction": 1,
          "inserted_knives": [0, 180]
        },
        "knives_queue": { "remaining_count": 3, "total_count": 5 },
        "score": 20,
        "apples": [
          { "id": 1, "angle": 135, "angular_radius": 8, "collected": false }
        ]
      },
      "actions": [
        { "type": "throw_knife" }
      ],
      "expectedState": {
        "score": 80,
        "apples[0].collected": true,
        "score_gained": 60
      }
    },
    {
      "id": "tc_level_complete",
      "description": "关卡通过：成功投出最后一刀",
      "initialState": {
        "target": {
          "current_angle": 45,
          "rotation_speed": 90,
          "rotation_direction": 1,
          "inserted_knives": [90, 180, 270]
        },
        "knives_queue": { "remaining_count": 1, "total_count": 4 },
        "score": 30,
        "apples": []
      },
      "actions": [
        { "type": "throw_knife" }
      ],
      "expectedState": {
        "knives_queue.remaining_count": 0,
        "gameOver": true,
        "win": true
      }
    }
  ]
}
