✓ Verified 💻 Development ✓ Enhanced Data

Snake Rodeo

Autoplay daemon for the Trifle Snake Rodeo game.

Rating
4.9 (280 reviews)
Downloads
42,443 downloads
Version
1.0.0

Overview

Autoplay daemon for the Trifle Snake Rodeo game.

Complete Documentation

View Source →

Snake Rodeo Skill

Play the Trifle Snake Rodeo automatically with a persistent daemon and modular strategy system. Built on the snake-rodeo-agents library.

How It Works

The game is a multiplayer snake on a grid (hex or cartesian). Teams bid on directions each round — the highest bidder's direction wins. All bids go into a prize pool that the winning team splits. The daemon watches the game via SSE, picks optimal directions using a strategy, and submits votes automatically.

Prerequisites

  • Authenticated via trifle-auth skill
  • Node.js 18+
  • Ball balance (earned from games, auth bonuses, etc.)

Daemon Commands

bash
# Start/stop
node snake.mjs start [--detach] [--strategy NAME]
node snake.mjs stop
node snake.mjs status
node snake.mjs attach [-f]

# Pause/resume voting (daemon keeps running)
node snake.mjs pause
node snake.mjs resume

# Configuration
node snake.mjs config [key] [value]
node snake.mjs strategies
node snake.mjs server [live|staging]
node snake.mjs telegram [chat_id|off]

# Manual play
node snake.mjs state
node snake.mjs vote <direction> <team> [amount]
node snake.mjs strategy    # Analyze current game
node snake.mjs balance

Strategies

Five built-in strategies are available. Each extends BaseStrategy from snake-rodeo-agents.

StrategyAliasDescription
expected-valueev, defaultBFS pathfinding, dead-end avoidance, game-theoretic team selection, probabilistic defection in multi-agent scenarios. Balanced.
aggressiveaggBacks leading teams, counter-bids aggressively.
underdogundBacks small pools for bigger payouts.
conservativeconMinimum bids, prioritizes safety.
randomrandRandom valid moves.
Switch strategy:

bash
node snake.mjs config strategy aggressive
# or
node snake.mjs start --strategy aggressive

Creating Custom Strategies

Extend BaseStrategy from snake-rodeo-agents:

javascript
import { BaseStrategy } from 'snake-rodeo-agents';

export class MyStrategy extends BaseStrategy {
  constructor(options = {}) {
    super('my-strategy', 'My custom strategy', options);
  }

  computeVote(parsed, balance, state) {
    // parsed: ParsedGameState — hex grid, teams, scores, valid directions
    // balance: number — current ball balance
    // state: AgentState — round tracking, team assignment, vote history

    // Return a vote:
    return { direction: 'ne', team: 'A', amount: 1, reason: 'chasing fruit' };

    // Or skip:
    return { skip: true, reason: 'too risky' };
  }

  // Optional: counter-bid when outbid
  shouldCounterBid(parsed, balance, state, ourVote) {
    return null; // or return a new VoteAction
  }
}

Key types for strategy development:

  • ParsedGameState — Parsed game with head, teams[], validDirections[], gridRadius, prizePool, minBid, fruitsToWin
  • AgentState{ currentTeam, roundSpend, roundVoteCount, lastRound, gamesPlayed, votesPlaced, wins }
  • VoteAction{ direction, team, amount, reason }

snake-rodeo-agents Library

The core logic lives in snake-rodeo-agents, a standalone TypeScript library. This skill wraps it with daemon management, config persistence, and OpenClaw integration.

API Client

javascript
import { SnakeClient, createAndAuthenticate, parseGameState, getStrategy } from 'snake-rodeo-agents';

// Auth (creates a throwaway wallet, no real ETH needed)
const { token, privateKey, address } = await createAndAuthenticate('https://bot.trifle.life');

// Create client
const client = new SnakeClient('https://bot.trifle.life', token);

// Play
const rawState = await client.getGameState();
const parsed = parseGameState(rawState);
const strategy = getStrategy('expected-value');
const vote = strategy.computeVote(parsed, balance, agentState);

if (vote && !vote.skip) {
  await client.submitVote(vote.direction, vote.team, vote.amount);
}

SnakeClient methods:

MethodDescription
getGameState()Current game state (snake, fruits, scores, votes)
getBalance()Current ball balance
submitVote(dir, team, amount)Submit a direction vote
getRodeos()List active rodeo games
getUserStatus()User profile and stats

Wallet Authentication

SIWE (Sign In With Ethereum) auth with throwaway wallets:

javascript
import { createAndAuthenticate, reauthenticate, checkToken } from 'snake-rodeo-agents';

// New wallet
const { token, privateKey, address } = await createAndAuthenticate(serverUrl);

// Reuse saved wallet
const { token } = await reauthenticate(serverUrl, savedPrivateKey);

// Check token validity
const user = await checkToken(serverUrl, token);

Game State Utilities

The library provides hex grid utilities for strategy development:

javascript
import { parseGameState, hexDistance, bfsDistance, floodFillSize, getValidDirections } from 'snake-rodeo-agents';

const parsed = parseGameState(rawState);

// BFS shortest path to a target (respects snake body, grid bounds)
const { distance, firstDir } = bfsDistance(head, target, rawState);

// Flood-fill reachable area (dead-end detection)
const reachable = floodFillSize(head, rawState);

// Hex distance between two positions
const dist = hexDistance(posA, posB);

Tournament Simulator

Run offline tournaments to compare strategies at high speed:

bash
# CLI
npm run simulate -- ev,aggressive --games 100 --seed 42
npm run simulate -- ev,aggressive,conservative --config small --verbose
npm run simulate -- ev,aggressive --json   # machine-readable output

javascript
// Library
import { SimAgent, runTournament, RODEO_CYCLES, getStrategy } from 'snake-rodeo-agents';

const agents = [
  new SimAgent('a', 'ev-agent', getStrategy('ev')),
  new SimAgent('b', 'agg-agent', getStrategy('aggressive')),
];

const results = runTournament(agents, RODEO_CYCLES, 100, { seed: 42 });
console.log(results.agentStats);
// Same seed = identical results for reproducibility

Simulator options:

FlagDescription
-g, --games NGames per config (default: 100)
-c, --config NAMEsmall\medium\large\all (default: all)
-s, --seed NRNG seed for reproducibility
-v, --verbosePrint per-round details
--jsonMachine-readable JSON output

Telegram Logging

Send game events to a Telegram group:

javascript
import { TelegramLogger } from 'snake-rodeo-agents';

const tg = new TelegramLogger({
  botToken: process.env.TELEGRAM_BOT_TOKEN,
  chatId: process.env.TELEGRAM_CHAT_ID,
});

await tg.send('<b>Hello</b> from the snake agent!');

Configure in the daemon:

bash
node snake.mjs telegram <chat_id>   # enable
node snake.mjs telegram off          # disable

Configuration

Settings are stored in ~/.config/snake-rodeo/settings.json (XDG-compliant, isolated from any host agent).

KeyDefaultDescription
strategyexpected-valueActive strategy name
serverlivelive or staging
minBalance5Minimum balance to place votes
telegramChatIdnullTelegram chat ID for logging
telegramBotTokennullTelegram bot token (or set TELEGRAM_BOT_TOKEN env var)

File Locations

PurposePath
Settings~/.config/snake-rodeo/settings.json
Auth token~/.config/snake-rodeo/auth.json or TRIFLE_AUTH_TOKEN env var
Daemon state~/.local/state/snake-rodeo/daemon.state
Daemon PID~/.local/state/snake-rodeo/daemon.pid
Daemon log~/.local/share/snake-rodeo/daemon.log

Authentication

The skill resolves your Trifle auth token in this order:

  • TRIFLE_AUTH_TOKEN environment variable (recommended for automation)
  • ~/.config/snake-rodeo/auth.json{ "token": "your-jwt-here" }
To set up auth, run snake auth login (uses trifle-auth skill) or set the env var directly.

Architecture

text
snake-game/                             # OpenClaw skill wrapper
├── SKILL.md                            # This file
├── snake.mjs                           # CLI entry point
├── clawdhub.json                       # ClawHub registry metadata
├── package.json                        # Dependencies (snake-rodeo-agents)
├── lib/
│   ├── config.mjs                      # Settings/paths
│   ├── api.mjs                         # Token-based API (uses OpenClaw auth)
│   ├── process.mjs                     # Daemon PID management
│   └── telegram.mjs                    # Telegram bridge
├── daemon/
│   └── autoplay.mjs                    # Game loop: SSE → strategy → vote
└── node_modules/
    └── snake-rodeo-agents/             # Core library (TypeScript)
        └── dist/
            ├── lib/game-state.js       # Hex grid, BFS, flood-fill
            ├── lib/strategies/         # Strategy implementations
            ├── lib/client.js           # Standalone API client
            ├── lib/auth.js             # Wallet SIWE auth
            ├── lib/simulator.js        # Offline game simulator
            ├── lib/telegram.js         # Telegram logger
            └── bin/play.js             # Standalone CLI runner

Upgrading

bash
node snake.mjs stop
cd ~/.openclaw/workspace/skills/snake-rodeo
npm install github:trifle-labs/snake-rodeo-agents
node snake.mjs start --detach

Installation

Terminal bash

openclaw install snake-rodeo
    
Copied!

💻Code Examples

node snake.mjs balance

node-snakemjs-balance.txt
## Strategies

Five built-in strategies are available. Each extends `BaseStrategy` from `snake-rodeo-agents`.

| Strategy | Alias | Description |
|----------|-------|-------------|
| `expected-value` | `ev`, `default` | BFS pathfinding, dead-end avoidance, game-theoretic team selection, probabilistic defection in multi-agent scenarios. Balanced. |
| `aggressive` | `agg` | Backs leading teams, counter-bids aggressively. |
| `underdog` | `und` | Backs small pools for bigger payouts. |
| `conservative` | `con` | Minimum bids, prioritizes safety. |
| `random` | `rand` | Random valid moves. |

Switch strategy:

node snake.mjs start --strategy aggressive

node-snakemjs-start---strategy-aggressive.txt
### Creating Custom Strategies

Extend `BaseStrategy` from `snake-rodeo-agents`:

}

.txt
Key types for strategy development:

- **`ParsedGameState`** — Parsed game with `head`, `teams[]`, `validDirections[]`, `gridRadius`, `prizePool`, `minBid`, `fruitsToWin`
- **`AgentState`** — `{ currentTeam, roundSpend, roundVoteCount, lastRound, gamesPlayed, votesPlaced, wins }`
- **`VoteAction`** — `{ direction, team, amount, reason }`

## snake-rodeo-agents Library

The core logic lives in [snake-rodeo-agents](https://github.com/trifle-labs/snake-rodeo-agents), a standalone TypeScript library. This skill wraps it with daemon management, config persistence, and OpenClaw integration.

### API Client

}

.txt
**SnakeClient methods:**

| Method | Description |
|--------|-------------|
| `getGameState()` | Current game state (snake, fruits, scores, votes) |
| `getBalance()` | Current ball balance |
| `submitVote(dir, team, amount)` | Submit a direction vote |
| `getRodeos()` | List active rodeo games |
| `getUserStatus()` | User profile and stats |

### Wallet Authentication

SIWE (Sign In With Ethereum) auth with throwaway wallets:

const user = await checkToken(serverUrl, token);

const-user--await-checktokenserverurl-token.txt
### Game State Utilities

The library provides hex grid utilities for strategy development:

const dist = hexDistance(posA, posB);

const-dist--hexdistanceposa-posb.txt
### Tournament Simulator

Run offline tournaments to compare strategies at high speed:

// Same seed = identical results for reproducibility

-same-seed--identical-results-for-reproducibility.txt
**Simulator options:**

| Flag | Description |
|------|-------------|
| `-g, --games N` | Games per config (default: 100) |
| `-c, --config NAME` | `small\|medium\|large\|all` (default: all) |
| `-s, --seed N` | RNG seed for reproducibility |
| `-v, --verbose` | Print per-round details |
| `--json` | Machine-readable JSON output |

### Telegram Logging

Send game events to a Telegram group:

node snake.mjs telegram off # disable

node-snakemjs-telegram-off--disable.txt
## Configuration

Settings are stored in `~/.config/snake-rodeo/settings.json` (XDG-compliant, isolated from any host agent).

| Key | Default | Description |
|-----|---------|-------------|
| `strategy` | `expected-value` | Active strategy name |
| `server` | `live` | `live` or `staging` |
| `minBalance` | `5` | Minimum balance to place votes |
| `telegramChatId` | `null` | Telegram chat ID for logging |
| `telegramBotToken` | `null` | Telegram bot token (or set `TELEGRAM_BOT_TOKEN` env var) |

### File Locations

| Purpose | Path |
|---------|------|
| Settings | `~/.config/snake-rodeo/settings.json` |
| Auth token | `~/.config/snake-rodeo/auth.json` or `TRIFLE_AUTH_TOKEN` env var |
| Daemon state | `~/.local/state/snake-rodeo/daemon.state` |
| Daemon PID | `~/.local/state/snake-rodeo/daemon.pid` |
| Daemon log | `~/.local/share/snake-rodeo/daemon.log` |

### Authentication

The skill resolves your Trifle auth token in this order:

1. `TRIFLE_AUTH_TOKEN` environment variable (recommended for automation)
2. `~/.config/snake-rodeo/auth.json` — `{ "token": "your-jwt-here" }`

To set up auth, run `snake auth login` (uses `trifle-auth` skill) or set the env var directly.

## Architecture
example.sh
# Start/stop
node snake.mjs start [--detach] [--strategy NAME]
node snake.mjs stop
node snake.mjs status
node snake.mjs attach [-f]

# Pause/resume voting (daemon keeps running)
node snake.mjs pause
node snake.mjs resume

# Configuration
node snake.mjs config [key] [value]
node snake.mjs strategies
node snake.mjs server [live|staging]
node snake.mjs telegram [chat_id|off]

# Manual play
node snake.mjs state
node snake.mjs vote <direction> <team> [amount]
node snake.mjs strategy    # Analyze current game
node snake.mjs balance
example.sh
node snake.mjs config strategy aggressive
# or
node snake.mjs start --strategy aggressive

⚙️Configuration Options

Option Type Default Description
strategystringexpected-valueActive strategy name
serverstringlive`live` or `staging`
minBalancestring5Minimum balance to place votes
telegramChatIdstringnullTelegram chat ID for logging
telegramBotTokenstringnullTelegram bot token (or set `TELEGRAM_BOT_TOKEN` env var)

Tags

#devops_and-cloud

Quick Info

Category Development
Model Claude 3.5
Complexity One-Click
Author okwme
Last Updated 3/10/2026
🚀
Optimized for
Claude 3.5
🧠

Ready to Install?

Get started with this skill in seconds

openclaw install snake-rodeo