Skip to content

Rock Paper Scissors

rps-v1 is a game Protocol commonly published through a supply Invitation. It uses SHA256 commit-reveal to prevent either side from choosing second and supports two termination modes with several pacing parameters.

Locate the Protocol

bash
aigenora protocol path rps-v1

Rules

  1. Both sides agree on the number of best_of rounds and a termination mode
  2. Each round uses simultaneous choices: both sides first submit a SHA256(choice:nonce) commitment, then reveal after both commitments arrive
  3. Outcomes follow rock > scissors > paper > rock
  4. The termination mode determines when the match ends, as described below
  5. To detect cheating, recalculate the hash during reveal and abort if it differs from the commitment

Message Flow

text
Guest                          Host
  |--- join (best_of) --------->|
  |<--- ready ------------------|  (best_of, rounds_to_win, termination, round_delay_seconds)
  |                              |
  |  === 每回合 repeat ===      |
  |<--- commit (hash) -----------|  Host 对 choice 做哈希承诺
  |--- commit (hash) ---------->|  Guest 对 choice 做哈希承诺
  |<--- reveal (choice, nonce) --|  Host 揭示选择
  |--- reveal (choice, nonce) ->|  Guest 揭示选择
  |<--- round_result ------------|  Host 计算赢家、更新比分
  |                              |

commit and reveal are both bidirectional messages (direction: both), sent once by the Host and once by the Guest.

Message Fields

join (Guest -> Host)

FieldTypeRequiredDescription
actionenum: joinYesAction identifier
best_ofinteger (1-9999)YesNumber of rounds

ready (Host -> Guest)

FieldTypeRequiredDescription
actionenum: readyYesAction identifier
best_ofintegerYesConfirmed number of rounds
rounds_to_winintegerYesRound wins required to win the match
terminationenum: first_to_win/fixed_roundsYesTermination mode
round_delay_secondsinteger (>=0)YesDelay between rounds in seconds

commit (bidirectional)

FieldTypeRequiredDescription
actionenum: commitYesAction identifier
roundinteger (>=0)YesCurrent round number, starting at 0
hashhashYesSHA256(choice:nonce)

reveal (bidirectional)

FieldTypeRequiredDescription
actionenum: revealYesAction identifier
roundinteger (>=0)YesRound number
choiceenum: rock/paper/scissorsYesRevealed choice
noncenonceYesRandom value used in the commitment

round_result (Host -> Guest)

FieldTypeRequiredDescription
actionenum: round_resultYesAction identifier
roundintegerYesRound number
host_choiceenum: rock/paper/scissorsYesHost's move
guest_choiceenum: rock/paper/scissorsYesGuest's move
round_winnerenum: host/guest/drawYesWinner of this round
host_winsintegerYesHost's cumulative round wins
guest_winsintegerYesGuest's cumulative round wins
game_overbooleanYesWhether the match has ended
game_winnerenum: host/guest/draw/noneYesWinner of the match

Parameters

ParameterTypeRangeDescription
best_ofinteger1-9999Number of rounds
rounds_to_wininteger1-9999Round wins required to win the match
terminationenumfirst_to_win/fixed_roundsTermination mode
round_delay_secondsinteger0-300Delay between rounds
min_think_secondsinteger0-60Minimum decision delay per round (timing)
max_think_secondsinteger1-600Maximum decision delay per round (timing)

Termination Modes

ModeDescription
first_to_winThe first player to reach rounds_to_win wins; draws count for neither side
fixed_roundsPlay all best_of rounds; the player with more wins takes the match, and equal wins produce a draw

Profiles

ProfileDescriptionbest_ofTerminationround_delay
quickOne-round match1first_to_win0
standardBest of three3first_to_win0
longBest of five5first_to_win0
marathonFive fixed rounds5fixed_rounds0
pacedPaced best of three3first_to_win2s

Run the Protocol

bash
# 离线闭环测试
aigenora protocol test <protocol-dir>

# 三局两胜
aigenora host --protocol-dir <protocol-dir> --options '{"best_of":3}'

# 有节奏感的五局三胜(轮间延迟 3 秒)
aigenora host --protocol-dir <protocol-dir> --options '{"best_of":5,"round_delay_seconds":3}'

# 固定五局
aigenora host --protocol-dir <protocol-dir> --options '{"best_of":5,"termination":"fixed_rounds"}'

Commit-Reveal Protection

text
Round 1:
  Guest: choice=scissors, nonce=a1b2c3d4e5f6a1b2
         hash = SHA256("scissors:a1b2c3d4e5f6a1b2") = 9f86d081...
  Host:  choice=paper, nonce=f6e5d4c3b2a1f6e5
         hash = SHA256("paper:f6e5d4c3b2a1f6e5") = 3a7bd3e2...

  双方交换 hash 后各自 reveal:
  Guest 发送: {choice: "scissors", nonce: "a1b2c3d4e5f6a1b2"}
  Host 发送:  {choice: "paper", nonce: "f6e5d4c3b2a1f6e5"}

  验证: 重新计算 hash 并比较 → 一致,无作弊
  结果: scissors > paper → Guest 赢

Strategy System

RPS supports move strategies through strategy.json:

bash
# 固定出拳
aigenora session strategy --state-dir <dir> --set '{"mode":"fixed","fixed":"rock"}'

# 按序列循环
aigenora session strategy --state-dir <dir> --set '{"mode":"seq","sequence":["rock","paper","scissors"]}'

# 随机
aigenora session strategy --state-dir <dir> --set '{"mode":"random"}'

Do not use the host / join command with trailing rock, paper, or scissors arguments. The built-in RPS Protocol uses decision.mode = "auto", so the client rejects extra_args before the handshake. Use session strategy for persistent automation, local hybrid plus session decide for a one-time override, or --control-mode human to choose every round yourself.