Asi move-rps-game
Rock-Paper-Scissors PvP game on Aptos with commit-reveal pattern and ACSet-informed design
install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/move-rps-game" ~/.claude/skills/plurigrid-asi-move-rps-game && rm -rf "$T"
manifest:
skills/move-rps-game/SKILL.mdsource content
Move RPS Game Skill
"In the commit-reveal pattern, GF(3) determines victory: (p1 - p2 + 3) % 3"
Overview
Move RPS Game implements a provably fair Rock-Paper-Scissors game on Aptos blockchain using the commit-reveal pattern to prevent cheating.
GF(3) Role
| Aspect | Value |
|---|---|
| Trit | +1 (PLUS) |
| Role | GENERATOR |
| Function | Generates game states via Move contracts |
Architecture
┌─────────────────────────────────────────────────────────────────┐ │ RPS GAME STATE MACHINE │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ WAITING ──join──▶ COMMIT ──both──▶ REVEAL ──both──▶ COMPLETE │ │ │ │ │ │ │ │ cancel timeout timeout winner │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ │ │ [refund] [forfeit] [forfeit] [payout] │ │ │ └─────────────────────────────────────────────────────────────────┘
ACSet Schema
The game state follows a categorical schema:
@present SchRPS(FreeSchema) begin Player::Ob Game::Ob Move::Ob # {Rock=0, Paper=1, Scissors=2} player1::Hom(Game, Player) player2::Hom(Game, Player) commit1::Hom(Game, Hash) commit2::Hom(Game, Hash) reveal1::Hom(Game, Move) reveal2::Hom(Game, Move) winner::Hom(Game, Player) BetType::AttrType bet::Attr(Game, BetType) end
Winner Determination (GF(3))
Move values: Rock=0, Paper=1, Scissors=2 Winner formula: result = (move1 - move2 + 3) % 3 0 = Draw 1 = Player 1 wins 2 = Player 2 wins Cycle: Rock → Scissors → Paper → Rock (0) (2) (1) (0)
Game Flow
1. Create Game
aptos move run \ --function-id 'ADDR::game::create_game' \ --args u64:10000000 # 0.1 APT bet
2. Join Game
aptos move run \ --function-id 'ADDR::game::join_game' \ --args address:GAME_ID
3. Commit Move
# Off-chain: compute hash MOVE=0 # Rock SALT=$(openssl rand -hex 32) HASH=$(echo -n "${MOVE}${SALT}" | sha3sum -a 256) aptos move run \ --function-id 'ADDR::game::commit_move' \ --args address:GAME_ID "vector<u8>:${HASH}"
4. Reveal Move
aptos move run \ --function-id 'ADDR::game::reveal_move' \ --args address:GAME_ID u8:0 "vector<u8>:${SALT}"
Security Model
Commit-Reveal Pattern
Phase 1 (Commit): P1: hash(move₁ || salt₁) → chain P2: hash(move₂ || salt₂) → chain Phase 2 (Reveal): P1: (move₁, salt₁) → chain, verify hash P2: (move₂, salt₂) → chain, verify hash Winner: GF(3) computation on revealed moves
Timeout Protection
| Phase | Timeout | Resolution |
|---|---|---|
| WAITING | None | Player 1 can cancel |
| COMMIT | 5 min | Non-committer forfeits |
| REVEAL | 5 min | Non-revealer forfeits |
Why This Works
- No front-running: Moves hidden until both committed
- No backing out: Commitment is binding
- Provable fairness: Hash verification on-chain
- Timeout protection: Can't grief by not playing
Contract Functions
Entry Functions
| Function | Description |
|---|---|
| Create game with APT bet |
| Join and match bet |
| Submit move commitment |
| Reveal move |
| Claim win on timeout |
| Cancel if no opponent |
View Functions
| Function | Returns |
|---|---|
| (phase, pot, winner) |
| (player1, player2) |
| bool |
| (p1_committed, p2_committed) |
| (p1_revealed, p2_revealed) |
| commitment hash |
Deployment
cd ~/.claude/skills/move-rps-game # Initialize (testnet) aptos init --network testnet # Compile aptos move compile --named-addresses rps_game=default # Test aptos move test --named-addresses rps_game=default # Publish aptos move publish --named-addresses rps_game=default
GF(3) Triads
move-rps-game (+1) ⊗ acsets-relational-thinking (0) ⊗ move-smith-fuzzer (-1) = 0 ✓ move-rps-game (+1) ⊗ aptos-agent (0) ⊗ clj-kondo-3color (-1) = 0 ✓ move-rps-game (+1) ⊗ gay-mcp (0) ⊗ three-match (-1) = 0 ✓
Frontend Integration
import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk"; const config = new AptosConfig({ network: Network.TESTNET }); const aptos = new Aptos(config); // Compute commitment client-side function computeCommitment(move: number, salt: Uint8Array): Uint8Array { const data = new Uint8Array([move, ...salt]); return sha3_256(data); } // Create game await aptos.transaction.build.simple({ sender: player1.accountAddress, data: { function: `${moduleAddress}::game::create_game`, functionArguments: [100_000_000], // 1 APT }, });
Testing Locally
# Start local testnet aptos node run-local-testnet --with-faucet # Fund accounts aptos account fund-with-faucet --account default --amount 100000000 # Run test game aptos move run --function-id 'default::game::create_game' --args u64:10000000
Related Skills
(0) - Blockchain interactionaptos-agent
(0) - Categorical schema designacsets-relational-thinking
(-1) - Contract fuzzingmove-smith-fuzzer
(0) - Quest contract referencekolmogorov-codex-quest
Skill Name: move-rps-game Type: Move Smart Contract / PvP Game Trit: +1 (PLUS - GENERATOR) GF(3): Generates game states, winner via modular arithmetic