{
  "_comment": "PGS (PlayCraft Gameplay Schema) 参考骨架 - Klondike 纸牌接龙。Agent 以此为起点编写或 fork 玩法规则。",
  "version": "1.0",
  "gameplayType": "solitaire",
  "entities": {
    "card": {
      "type": "card-item",
      "description": "扑克牌，52张标准牌",
      "fields": {
        "suit":    { "type": "enum",    "values": ["S", "H", "D", "C"], "description": "花色：S=黑桃，H=红心，D=方块，C=梅花" },
        "value":   { "type": "integer", "range": [1, 13], "description": "牌值：1=A，11=J，12=Q，13=K" },
        "face_up": { "type": "boolean", "default": false, "description": "是否翻面（正面朝上）" },
        "color":   { "type": "enum",    "values": ["red", "black"], "description": "红色=H/D，黑色=S/C" }
      }
    },
    "tableau": {
      "type": "card-columns",
      "description": "7列牌堆（主游戏区）",
      "columns": 7,
      "initialSetup": "第 i 列（1-indexed）有 i 张牌，最上面1张 face_up，其余 face_down"
    },
    "stock": {
      "type": "card-pile",
      "description": "备用牌堆（未翻开的剩余牌），点击翻牌到 waste",
      "face_up": false
    },
    "waste": {
      "type": "card-pile",
      "description": "翻开的废牌堆，顶牌可用",
      "face_up": true
    },
    "foundations": {
      "type": "card-piles",
      "description": "4个花色目标堆，目标是将所有牌按 A→K 移入",
      "count": 4,
      "suits": ["S", "H", "D", "C"],
      "startValue": 1,
      "endValue": 13
    }
  },
  "rules": {
    "move_to_tableau": {
      "description": "将牌（或牌组）移到另一列牌堆顶部",
      "conditions": [
        "目标列顶牌 face_up（或目标列为空）",
        "移动牌颜色与目标列顶牌颜色不同（红↔黑）",
        "移动牌的值 = 目标列顶牌值 - 1",
        "空列只接受 K（value == 13）"
      ],
      "group_move": "可以将一组连续的有效叠放牌（由顶部的某张 face_up 牌开始向下）一起移动"
    },
    "move_to_foundation": {
      "description": "将牌移到对应花色的目标堆",
      "conditions": [
        "目标堆花色 == 移动牌花色",
        "目标堆为空时只接受 A（value == 1）",
        "移动牌值 = 目标堆当前顶牌值 + 1"
      ],
      "note": "一次只能移动1张牌到目标堆"
    },
    "flip_tableau_top": {
      "description": "移走某列顶牌后，若新的顶牌 face_down，则自动翻开",
      "trigger": "after_move_from_tableau",
      "effect": "new_top_card.face_up = true"
    },
    "draw_from_stock": {
      "description": "从备用牌堆翻 1 张牌到 waste 堆（face_up）",
      "trigger": "player_click_stock",
      "drawCount": 1
    },
    "recycle_stock": {
      "description": "备用牌堆为空时，点击将 waste 堆整个翻回作为新的备用堆",
      "trigger": "player_click_empty_stock",
      "recycleLimit": -1,
      "effect": "stock = reverse(waste); waste = []"
    },
    "auto_complete": {
      "description": "所有牌都 face_up 时，可以自动将可移动的牌逐一放入目标堆",
      "trigger": "all_cards_face_up",
      "effect": "auto_move_to_foundations_until_win"
    }
  },
  "algorithm": {
    "description": "主循环：player selects card → validate move → execute move → flip top → check win",
    "steps": [
      "1. 玩家选择一张或一组牌（从 tableau/waste）",
      "2. 玩家选择目标位置（tableau 列 / foundation 堆）",
      "3. 验证移动合法性（颜色交替降序 / 同花色升序）",
      "4. 执行移牌：从源位置移除，添加到目标位置",
      "5. 若源为 tableau 且新顶牌 face_down → 翻开",
      "6. 若为翻牌操作：stock 顶牌移到 waste（face_up）",
      "7. 检测胜利：4个 foundation 堆都满（各13张，A→K）",
      "8. 若所有牌都 face_up → 触发 auto_complete 提示"
    ]
  },
  "winCondition": {
    "type": "all_in_foundations",
    "description": "4个花色目标堆各有13张牌（A到K），共52张"
  },
  "loseCondition": {
    "type": "no_valid_moves",
    "description": "（可选检测）无任何合法移动且 stock 为空且 waste 仅剩无法移动的牌"
  },
  "testCases": [
    {
      "id": "tc_move_to_tableau",
      "description": "合法移牌：红色5放到黑色6上",
      "initialState": {
        "tableau": {
          "col_0": [
            { "suit": "H", "value": 5, "face_up": true, "color": "red" }
          ],
          "col_1": [
            { "suit": "S", "value": 7, "face_up": false },
            { "suit": "C", "value": 6, "face_up": true, "color": "black" }
          ]
        },
        "foundations": { "S": [], "H": [], "D": [], "C": [] },
        "stock": [],
        "waste": []
      },
      "actions": [
        { "type": "move_cards", "from": { "zone": "tableau", "col": 0 }, "to": { "zone": "tableau", "col": 1 }, "count": 1 }
      ],
      "expectedState": {
        "tableau.col_0": [],
        "tableau.col_1_top": { "suit": "H", "value": 5, "face_up": true }
      }
    },
    {
      "id": "tc_move_to_foundation",
      "description": "移牌到目标堆：A先进，再放2",
      "initialState": {
        "tableau": {
          "col_0": [
            { "suit": "S", "value": 2, "face_up": true, "color": "black" }
          ]
        },
        "foundations": { "S": [{ "suit": "S", "value": 1, "face_up": true }], "H": [], "D": [], "C": [] },
        "stock": [],
        "waste": []
      },
      "actions": [
        { "type": "move_cards", "from": { "zone": "tableau", "col": 0 }, "to": { "zone": "foundation", "suit": "S" }, "count": 1 }
      ],
      "expectedState": {
        "foundations.S": [
          { "suit": "S", "value": 1 },
          { "suit": "S", "value": 2 }
        ],
        "tableau.col_0": []
      }
    },
    {
      "id": "tc_draw_from_stock",
      "description": "从备用堆翻牌到 waste",
      "initialState": {
        "tableau": { "col_0": [], "col_1": [], "col_2": [], "col_3": [], "col_4": [], "col_5": [], "col_6": [] },
        "foundations": { "S": [], "H": [], "D": [], "C": [] },
        "stock": [
          { "suit": "D", "value": 9, "face_up": false },
          { "suit": "H", "value": 3, "face_up": false }
        ],
        "waste": []
      },
      "actions": [
        { "type": "draw_from_stock" }
      ],
      "expectedState": {
        "stock_count": 1,
        "waste_top": { "suit": "H", "value": 3, "face_up": true }
      }
    },
    {
      "id": "tc_flip_after_move",
      "description": "移走顶牌后，下方 face_down 牌自动翻开",
      "initialState": {
        "tableau": {
          "col_0": [
            { "suit": "C", "value": 8, "face_up": false },
            { "suit": "H", "value": 5, "face_up": true, "color": "red" }
          ],
          "col_1": [
            { "suit": "S", "value": 6, "face_up": true, "color": "black" }
          ]
        },
        "foundations": { "S": [], "H": [], "D": [], "C": [] },
        "stock": [],
        "waste": []
      },
      "actions": [
        { "type": "move_cards", "from": { "zone": "tableau", "col": 0 }, "to": { "zone": "tableau", "col": 1 }, "count": 1 }
      ],
      "expectedState": {
        "tableau.col_0_top": { "suit": "C", "value": 8, "face_up": true },
        "lastFlipped": true
      }
    }
  ]
}
