游戏·v1.0.0作者入驻安全验证免授权

doudizhu

在claudecode或其他支持skill的ai工具中斗地主

139次安装
更新于 2026-06-14
by lisiting01
ClaudeCodeCodexCursorOpenCode

将以下命令发送给 AI 助手,AI 将获取安装索引后完成安装:

curl …/skills/doudizhu/download,然后按照返回的 Markdown 文件清单完成 doudizhu 的安装

截图展示

文件

SKILL.md

斗地主 (Dou Dizhu) Skill

Activation

Use this skill when the user:

  • Wants to play 斗地主 / Dou Dizhu / "Fight the Landlord"
  • Asks to start, continue, or explain a 斗地主 game
  • Mentions 叫地主, 出牌, 炸弹, 顺子 in a game context

Overview

斗地主 is a 3-player Chinese card game. One player becomes the landlord (地主) and plays against the other two farmers (农民). First to empty their hand wins.

  • 54 cards: standard 52 + Small Joker (小王) + Big Joker (大王)
  • Card ranking (low→high): 3 4 5 6 7 8 9 10 J Q K A 2 小王 大王
  • Landlord gets 3 extra kitty cards (底牌) after winning the bid

Setup

The skill folder contains engine.py. All game state is stored in game.json.

bash
# Start a new game — prints initial state JSON, redirect to create game.json
python engine.py new > game.json

# With a fixed seed for reproducibility (only use this for testing/debugging — never for real games)
python engine.py new --seed 123 > game.json

**Do NOT use --seed for normal gameplay. Always use the no-seed form so each game deals a unique hand.**

IMPORTANT: Only `new` uses `>` redirection. Never redirect `bid`, `play`, or `pass` output — they save state to the file automatically. Redirecting them will corrupt game.json.

Bidding Phase

Each player bids 0–3 in turn (player 0 → 1 → 2). Highest bidder becomes landlord and receives the kitty. If all bid 0, the game redeals automatically. A bid of 3 immediately wins the landlord role.

bash
# Each bid saves state to game.json automatically — do NOT redirect
python engine.py bid game.json <player> <amount>

After all three players bid, the engine automatically assigns the landlord, adds kitty cards, and switches phase to playing.

Playing Phase

Landlord plays first. Play proceeds clockwise (0→1→2→0…).

bash
# Play cards — saves to game.json automatically, prints JSON to stdout
python engine.py play game.json <player> <card1> [card2 ...]

# Pass
python engine.py pass game.json <player>

# Show full state (internal use — reveals all hands, do NOT display to user)
python engine.py show game.json

# Show what player 0 can see (use this for user-facing display)
python engine.py view game.json 0

# Get playable move hints for a player (returns JSON array)
python engine.py hint game.json <player>

Card string format

| Card | String |

|------|--------|

| Spade 3 | ♠3 |

| Heart King | ♥K |

| Diamond Ace | ♦A |

| Club 2 | ♣2 |

| Small Joker | 小王 |

| Big Joker | 大王 |

Use view game.json 0 to see exact card strings in the human player's hand.

Input normalization

The human player may use shorthand. Resolve shorthand to exact card strings from their hand before calling the engine:

| User input | Meaning | Resolution example |

|------------|---------|-------------------|

| 3 / 出3 | Single card of rank 3 | Pick any 3 in hand, e.g. ♣3 |

| A / 出A | Single Ace | Pick any A in hand, e.g. ♠A |

| 对6 / 双6 | Pair of 6s | Pick two 6s, e.g. ♦6 ♠6 |

| 对k / 对K | Pair of Kings | e.g. ♥K ♣K |

| 5678910j | Straight 5–J | e.g. ♦5 ♥6 ♦7 ♣8 ♥9 ♦10 ♥J |

| pass / 不要 / 不出 | Pass | Call pass command |

When the user's shorthand is ambiguous (e.g. they have two different 3s), pick the lowest-suit card. Always confirm the resolved cards in your narration: "你出 ♦6 ♠6(对6)".

Valid Move Types

| Type | Example | Rule |

|------|---------|------|

| Single | ♠5 | Any one card |

| Pair | ♠5 ♥5 | Two same rank |

| Triple | ♠5 ♥5 ♦5 | Three same rank |

| Triple+1 | ♠5 ♥5 ♦5 ♣3 | Three + any single |

| Triple+pair | ♠5 ♥5 ♦5 ♣3 ♥3 | Three + any pair |

| Straight | ♠3 ♥4 ♦5 ♣6 ♠7 | 5+ consecutive singles (no 2/joker) |

| Straight pairs | ♠3 ♥3 ♦4 ♣4 ♠5 ♥5 | 3+ consecutive pairs |

| Plane | ♠5 ♥5 ♦5 ♣6 ♠6 ♥6 | 2+ consecutive triples |

| Plane+singles | plane + N singles | N = number of triples |

| Plane+pairs | plane + N pairs | N = number of triples |

| Bomb | ♠7 ♥7 ♦7 ♣7 | Four of a kind — beats all except rocket |

| Rocket | 小王 大王 | Both jokers — beats everything |

Beating rules:

  • Must play same move type with higher rank (same length for straights/planes)
  • Bomb beats any non-bomb/non-rocket
  • Rocket beats everything
  • Pass is always allowed unless you own the current trick (last_player == you)
  • If all other players pass, the trick resets and you lead freely

Information Visibility Rules

Never show other players' hands to the human player. The human should only see:

  • Their own hand (full card list)
  • Other players' card counts only
  • The last play on the table
  • Whose turn it is

Use python engine.py view game.json 0 to display the board — it hides other players' hands automatically.

Use python engine.py show game.json only internally (to read state for AI decisions). Never paste its output directly to the user.

At game start, show only the human's hand and card counts:

你的手牌(17张): ♣3 ♦5 ♥6 ...
玩家1(农民): 17张
玩家2(农民): 17张
底牌: 暂时隐藏

After landlord is determined, reveal the kitty and show updated counts:

底牌揭示: ♠4 ♠10 ♣4 → 归入玩家1手中
玩家1(地主): 20张

Agent Workflow

1. Setup

bash
python engine.py new > game.json

Show the human their hand and card counts for other players. Do NOT show other players' hands.

2. Bidding loop

For each player in order (0 → 1 → 2):

  • If player 0 (human): ask "你要叫几分?(0=不叫, 1/2/3)"
  • If AI player: decide bid based on hand strength (read hand via show internally), then call bid
  • Call python engine.py bid game.json <player> <amount>
  • Check the returned JSON: if phase == "playing", bidding is done

After bidding, announce the landlord and reveal the kitty cards. Show updated card counts.

3. Turn loop

Execute exactly one `play` or `pass` command per response. After each command, show the updated board and stop.

For each turn:

If `current_player == 0` (human's turn):

1. Run python engine.py hint game.json 0

2. If hint returns `["PASS"]` or is empty: the human has no legal moves. Automatically call python engine.py pass game.json 0 and narrate: "你没有能压过的牌,自动不要。" Do NOT ask the user.

3. If hint has actual moves: display the board using view game.json 0, show what needs to be beaten, and ask the user what to play.

4. Accept user input, resolve shorthand to card strings, call play or pass.

5. If the engine returns _error, narrate the error and ask again with a valid move.

If `current_player` is an AI player:

1. Run python engine.py hint game.json <player> to get legal moves.

2. Apply AI strategy (see below) to pick one move.

3. Call exactly one play or pass command.

4. Narrate what the AI did: "玩家1(地主)出 ♥Q(单牌)"

5. Run python engine.py view game.json 0 and show the updated board.

6. Stop here. Do not proceed to the next turn in the same response. Every AI turn — including consecutive AI passes — must be shown individually so the user can follow the sequence.

After each turn, check the returned JSON:

  • If _error is present: the move was rejected. Re-read state with show, try a valid move.
  • If phase == "finished": announce the winner and which team won.

4. Showing the board

After every play (human or AI), display using view game.json 0:

  • Who played what (move type and cards)
  • Each player's remaining card count (no hand contents for AI players)
  • The human player's current hand
  • What the next player needs to beat, or "自由出牌" if the trick reset

5. Error recovery

If _error appears in the returned JSON:

  • Do NOT save the bad state (the engine already saved the pre-error state)
  • Re-read current state with python engine.py show game.json
  • Try a different valid move from the hint list

Hand display format

When showing the human player's hand, group cards by rank and mark pairs/triples/quads to aid readability:

你的手牌(17张):
  单张:♣3 ♦5 ♥9 ♠A
  对子:♥6♦6 ♣8♦8 ♦10♥10 ♣Q♠Q ♥K♣K
  特殊:♠6(三个6: ♥6 ♦6 ♠6)

Use the hint command output to identify combos. At minimum, show pairs and triples clearly distinguished from singles. This makes it easier for the player to plan moves.

AI Strategy

Landlord strategy

  • Free lead: If hand ≤ 5 cards, play combos to clear quickly. Otherwise play the lowest single or pair to probe.
  • Responding: Beat with the lowest valid move. Use a bomb only if a farmer has ≤ 3 cards remaining (urgent threat). Save the rocket for last resort.
  • General: Prioritize clearing cards quickly. Prefer combos (straights, planes) over singles when leading.

Farmer strategy

  • If teammate is `last_player` (owns the current trick): Always pass — let the teammate win the trick and lead next.
  • If landlord is `last_player`: Beat with the lowest valid move. Use a bomb if the landlord has ≤ 3 cards.
  • Free lead: Play the lowest single or pair to probe. If hand ≤ 5 cards, play combos to clear.
  • Cooperation: Never beat a teammate's move unless you can win the trick outright (i.e., no one can beat you).

After each AI decision, briefly explain the reasoning in one sentence: "玩家2选择不要,让队友继续控牌。"

State JSON Fields

json
{
  "phase": "bidding | playing | finished",
  "current_player": 0,
  "landlord": 1,
  "hands": [["♠3","♥4",...], [...], [...]],
  "kitty": ["♠A","♥2","大王"],
  "bids": [1, 2, 0],
  "last_move": {"mt":"pair","key":5,"length":1,"cards":["♠5","♥5"]},
  "last_player": 1,
  "pass_count": 0,
  "winner": -1,
  "history": [...]
}

winner is -1 until the game ends. _error key appears on invalid actions (not saved to file). _event key carries informational messages.

Constraints

  • Engine requires Python 3.8+ (stdlib only, no external dependencies).
  • State file is plain JSON — safe to inspect, copy, or reset.
  • The engine does not implement AI opponents; the agent decides all AI moves.
  • Straight/plane moves exclude rank 2 and jokers (standard rules).
  • Bidding tie: if two players bid the same highest amount, the later bidder (higher player index) wins.
  • bid, play, pass commands save state to the file AND print JSON to stdout. Never redirect their output to game.json.