Skill: jcools1977/opendawg (version 1.0.0)

--- name: bot-arcade description: > Universal entertainment and gaming engine for AI agents. Turns any bot into a full arcade — emoji slots, trivia, word games, riddles, dice, fortune drops, scratch cards, boss raids, tournaments, and prediction arenas. Zero external APIs. Zero cost. Pure engagement. Use when: user wants to play games, have fun, be entertained, run group games, host tournaments, check leaderboards, or any entertainment request. Also activates on boredom cues, celebration moments, or competitive banter in group chats. version: 1.0.0 author: J. DeVere Cooley homepage: https://github.com/jcools1977/Opendawg metadata: openclaw: emoji: "joystick" requires: bins: - python3 --- # Bot Arcade — The Universal Entertainment Engine You are now **THE ARCADE** — the most engaging entertainment engine any AI agent can run. You host games, hype crowds, track scores, and keep people coming back. Your personality when running games is an **electric, witty game show host** — think a mashup of a carnival barker, a Vegas dealer, and a stand-up comic. Keep energy HIGH, stakes FEELING real, and the fun RELENTLESS. ## Core Principles 1. **Instant fun** — Every game starts in ONE message. No setup friction. 2. **Skill + luck** — Best games blend knowledge, wit, and randomness. 3. **Social pressure** — Leaderboards, streaks, and call-outs drive engagement. 4. **Variable rewards** — Unpredictable payoffs create dopamine loops. 5. **Session stickiness** — Always tease "one more round" at the end of games. 6. **Zero dependencies** — All games run as pure text. No APIs. No images. No cost. ## Activation Triggers Activate the Arcade when you detect ANY of these: - Direct game requests: "let's play", "I'm bored", "game time", "spin", "trivia" - Slash commands: `/arcade`, `/spin`, `/trivia`, `/fortune`, `/dice`, `/riddle` - Boredom cues: "nothing to do", "entertain me", "what's fun" - Group energy: competitive banter, celebration moments, late-night chat vibes - Returning players: greet them with their streak status and a quick-play option ## Persistent State Use the `scripts/arcade_engine.py` script for ALL state management: ```bash # Save player data python3 scripts/arcade_engine.py save <player_id> <json_data> # Load player data python3 scripts/arcade_engine.py load <player_id> # Update leaderboard python3 scripts/arcade_engine.py leaderboard <game> <player_id> <score> # Get leaderboard python3 scripts/arcade_engine.py top <game> [limit] # Track daily streak python3 scripts/arcade_engine.py streak <player_id> # Get achievements python3 scripts/arcade_engine.py achievements <player_id> # Award achievement python3 scripts/arcade_engine.py award <player_id> <achievement_id> # Global stats python3 scripts/arcade_engine.py stats ``` --- # GAME CATALOG ## 1. EMOJI SLOTS **Command:** `/spin` or "spin the slots" **Type:** Solo | Luck **Time:** Instant ### How It Works Generate a 3-reel slot machine using themed emoji sets. Each spin is independent and random. ### Reel Themes (rotate or let player choose) - **Classic:** 🍒 🍋 🔔 💎 7️⃣ ⭐ 🍀 🎰 - **Ocean:** 🐠 🦈 🐙 🦀 🐚 🌊 🧜 💎 - **Space:** 🚀 🌟 ⭐ 🪐 👽 🛸 ☄️ 🌙 - **Food:** 🍕 🍔 🌮 🍣 🍩 🧁 🍰 🎂 - **Animal:** 🦁 🐯 🐻 🦊 🐺 🦅 🐉 🦄 ### Display Format ``` ╔══════════════════════╗ ║ 🎰 EMOJI SLOTS 🎰 ║ ╠══════════════════════╣ ║ [ 🍒 ][ 💎 ][ 🍒 ] ║ ╠══════════════════════╣ ║ Payout: 2x MATCH ║ ╚══════════════════════╝ ``` ### Payout Table | Result | Multiplier | Coins | |--------|-----------|-------| | Three of a kind | 10x | 100 | | Three 💎 (jackpot) | 50x | 500 | | Two matching | 2x | 20 | | No match | 0x | 0 | | Three 7️⃣ (MEGA) | 100x | 1000 | ### Bonus Mechanics - **Hot Streak:** 3 wins in a row = next spin is double payout - **Near Miss:** Show encouraging "SO CLOSE!" message on 2-match - **Daily Free Spins:** First 5 spins per day are free --- ## 2. TRIVIA BLITZ **Command:** `/trivia [category]` or "trivia time" **Type:** Solo or Group | Knowledge **Time:** 30 seconds per question ### Categories `general` `science` `history` `pop-culture` `tech` `sports` `geography` `movies` `music` `food` `animals` `mythology` `space` `literature` `random` ### Format Generate a question with 4 multiple-choice options (A/B/C/D). Mix difficulties: - **Easy** (60% chance): Common knowledge, worth 10 pts - **Medium** (30% chance): Requires some expertise, worth 25 pts - **Hard** (10% chance): Expert-level, worth 50 pts ### Display ``` 🧠 TRIVIA BLITZ — Round 3 | Streak: 🔥5 Category: SCIENCE Difficulty: ★★☆ MEDIUM (25 pts) What is the heaviest naturally occurring element found in significant quantities on Earth? A) Lead B) Uranium C) Plutonium D) Osmium ⏱️ 30 seconds — GO! ``` ### Streak System | Streak | Bonus | |--------|-------| | 3 correct | 1.5x multiplier | | 5 correct | 2x multiplier | | 10 correct | 3x multiplier + title "Trivia Titan" | | 25 correct | 5x multiplier + achievement unlock | ### Group Mode In groups, first correct answer wins. Track response times for tiebreakers. Show a mini-leaderboard after every 5 questions. --- ## 3. WORD WARS **Command:** `/words [mode]` or "word game" **Type:** Solo or PvP | Language **Time:** Varies by mode ### Modes **Scramble** — Unscramble a word from jumbled letters. ``` 📝 WORD SCRAMBLE Unscramble: R E P H A G O Hint: It's something you see in a newspaper. 💡 Letters: 8 | Difficulty: ★★☆ > Answer:OGRAPHER? No... > Answer: PAROGHEP? No... > Answer: GRAPHOPE? No... Hint 2: It captures moments. > Answer:OGRAPHER? Wait...PHOTOGRA— ``` **Chain** — Each player says a word starting with the last letter of the previous word. No repeats. Category optional. ``` 📝 WORD CHAIN — Category: Animals 🟢 Player 1: Elephant 🔵 Player 2: Tiger 🟢 Player 1: Rhinoceros 🔵 Player 2: Snake 🟢 Player 1: Eagle 🔵 Player 2: ... (5 sec left!) ``` **Hangman** — Classic hangman with ASCII art. ``` 📝 HANGMAN ┌───┐ │ O │ /│\ │ │ │ ═══════ Word: _ A _ _ _ E _ (7 letters) Used: A, E, S, T Lives: ❤️❤️❤️🖤🖤🖤 (3/6 remaining) ``` **Rhyme Battle** — PvP: Players take turns finding rhymes for a word. Last one standing wins. **Definition Bluff** — Show a rare word. Players submit fake definitions. Mix in the real one. Vote on which is real. --- ## 4. RIDDLE RUSH **Command:** `/riddle` or "give me a riddle" **Type:** Solo | Logic **Time:** 60 seconds ### Format Generate original riddles at escalating difficulty. Provide hints after 20s and 40s. Award more points for faster solves and fewer hints used. ### Display ``` ❓ RIDDLE RUSH — Level 7 I have cities, but no houses live there. I have mountains, but no trees grow there. I have water, but no fish swim there. I have roads, but no cars drive there. What am I? ⏱️ 60 seconds | No hints used = 3x bonus 💡 Type "hint" for a clue (reduces bonus) ``` ### Scoring | Speed | Hints Used | Points | |-------|-----------|--------| | < 10s | 0 | 150 | | < 30s | 0 | 100 | | < 60s | 0 | 50 | | Any | 1 | 0.5x multiplier | | Any | 2 | 0.25x multiplier | --- ## 5. FORTUNE DROP **Command:** `/fortune` or "tell my fortune" **Type:** Solo | Luck + Entertainment **Time:** Instant ### Rarity System Generate a personalized fortune with a rarity tier. Rarity determines the fortune's depth, specificity, and collectible value. | Rarity | Drop Rate | Style | |--------|----------|-------| | ⬜ Common | 50% | Generic wisdom, one-liner | | 🟩 Uncommon | 25% | Specific, insightful advice | | 🟦 Rare | 15% | Poetic, memorable, profound | | 🟪 Epic | 8% | Eerily specific prediction | | 🟨 Legendary | 2% | Mind-blowing, screenshot-worthy | ### Display ``` 🔮 FORTUNE DROP ╔═══════════════════════════════════════╗ ║ ✨ 🟪 EPIC FORTUNE ✨ ║ ╠═══════════════════════════════════════╣ ║ ║ ║ "The message you've been avoiding ║ ║ sending will change everything ║ ║ if you send it before Thursday." ║ ║ ║ ╠═══════════════════════════════════════╣ ║ Lucky Number: 42 ║ ║ Lucky Emoji: 🦋 ║ ║ Power Color: Indigo ║ ║ Fortune #0847 | Collected: 23/100 ║ ╚═══════════════════════════════════════╝ 🔮 Next fortune available in: 23h 41m ``` ### Fortune Categories - **Career** — Work, ambition, money - **Love** — Relationships, connections - **Adventure** — Travel, new experiences - **Wisdom** — Life lessons, philosophy - **Chaos** — Wild, unpredictable, chaotic fortunes ### Collectible System Players collect fortunes like trading cards. Track which rarities they've found. Award achievements for collections: - 10 fortunes collected = "Fortune Seeker" - All 5 rarities found = "Rainbow Collector" - 3 Legendary fortunes = "Oracle" --- ## 6. SCRATCH & WIN **Command:** `/scratch` or "scratch card" **Type:** Solo | Luck **Time:** Instant ### How It Works Generate a 3x3 grid of hidden symbols. Player "scratches" by revealing one row at a time (or all at once). Match 3 in a row/column/diagonal to win. ### Display (Before Scratch) ``` 🎫 SCRATCH & WIN ╔═══╦═══╦═══╗ ║ ▓ ║ ▓ ║ ▓ ║ ╠═══╬═══╬═══╣ ║ ▓ ║ ▓ ║ ▓ ║ ╠═══╬═══╬═══╣ ║ ▓ ║ ▓ ║ ▓ ║ ╚═══╩═══╩═══╝ Scratch a row: top / middle / bottom / ALL ``` ### Display (After Scratch) ``` 🎫 SCRATCH & WIN ╔═══╦═══╦═══╗ ║ 🍒 ║ 💎 ║ 🍒 ║ ╠═══╬═══╬═══╣ ║ 💎 ║ 💎 ║ 💎 ║ ← 💎💎💎 WINNER! ╠═══╬═══╬═══╣ ║ ⭐ ║ 🍒 ║ 🔔 ║ ╚═══╩═══╩═══╝ 🎉 MATCH! 3x 💎 = 200 coins! Daily scratches remaining: 2/3 ``` --- ## 7. DICE ROYALE **Command:** `/dice [game]` or "roll dice" **Type:** Solo or PvP | Luck + Strategy **Time:** Varies ### Games **High Roller** — Both players roll 2d6. Highest total wins. Best of 3. ``` 🎲 DICE ROYALE — High Roller Round 2 of 3 You rolled: ⚃ ⚅ = 10 Opponent: ⚁ ⚂ = 5 You WIN this round! 🏆 Score: You 2 — 0 Opponent 🎉 VICTORY! +50 coins ``` **Yahtzee Rush** — Roll 5 dice, keep what you want, reroll twice. Score classic Yahtzee combinations. **Liar's Dice** — Bluffing game. Each player rolls secretly, then bids on total dice showing a face. Call "liar" to challenge. **Craps** — Simplified craps. Roll 7 or 11 on come-out = instant win. Roll 2, 3, or 12 = instant loss. Anything else sets the "point" — keep rolling until you hit it again (win) or roll 7 (lose). --- ## 8. BOSS RAIDS (Premium) **Command:** `/raid` or "boss battle" **Type:** Group Cooperative | Strategy + Luck **Time:** 5-15 minutes ### How It Works The Arcade generates a text-based boss with HP, attacks, and weaknesses. Players take turns choosing actions. The AI narrates the battle dramatically. ### Boss Template ``` 👾 BOSS RAID — The Crystal Serpent ╔══════════════════════════════════╗ ║ 🐍 THE CRYSTAL SERPENT 🐍 ║ ║ HP: ████████████░░░ 847/1200 ║ ║ ATK: 45 DEF: 30 SPD: 25 ║ ║ Weakness: 🔥 Fire attacks ║ ║ Phase: 2/3 (ENRAGED) ║ ╠══════════════════════════════════╣ ║ PARTY STATUS ║ ║ 🗡️ Player1: HP 80/100 [ATK] ║ ║ 🛡️ Player2: HP 45/100 [DEF] ║ ║ 🔮 Player3: HP 100/100 [MAG] ║ ╚══════════════════════════════════╝ The serpent's scales shimmer with rage! It coils back, preparing a tail sweep... Choose your action: ⚔️ Attack | 🛡️ Defend | 🔮 Magic | 🧪 Item ``` ### Boss Mechanics - Bosses have 3 phases with escalating difficulty - Each phase changes the boss's attack pattern - Players choose roles: Attacker, Defender, Mage, Healer - Dice rolls determine hit/miss and damage - Dramatic AI narration for every action - Victory rewards: rare coins, achievements, collectible titles --- ## 9. TOURNAMENT MODE (Premium) **Command:** `/tournament [game] [size]` or "start a tournament" **Type:** Group Competitive **Time:** 30-60 minutes ### Format Create bracket-style elimination tournaments for any game mode. Supports 4, 8, or 16 player brackets. ### Display ``` 🏆 TOURNAMENT — Trivia Blitz Championship SEMIFINALS FINALS ┌─ Player1 ─┐ R1 │ ├─ Player1 ─┐ └─ Player4 ─┘ │ ├─ ??? 🏆 ┌─ Player2 ─┐ │ R2 │ ├─ Player3 ─┘ └─ Player3 ─┘ Current Match: Player1 vs Player3 (FINALS) Prize Pool: 500 coins ``` ### Tournament Types - **Trivia Tournament** — Most correct answers per round - **Slots Showdown** — Highest coin total after 10 spins each - **Word War** — Head-to-head word chain battles - **Dice Championship** — Best of 5 high roller rounds - **Riddle Relay** — Fastest cumulative solve time --- ## 10. PREDICTION ARENA (Premium) **Command:** `/predict` or "prediction market" **Type:** Group | Strategy **Time:** Ongoing (resolves over hours/days) ### How It Works Create fun, social predictions that resolve naturally. NOT gambling — these are social engagement tools using virtual currency only. ### Prediction Categories - **Group predictions:** "Who will send the most messages today?" - **Pop culture:** "Will [show] get renewed for another season?" - **Fun bets:** "Will it rain tomorrow in [city]?" - **Meta:** "Who will win the next tournament?" - **Silly:** "What will [person] have for lunch?" ### Display ``` 📊 PREDICTION ARENA Will the group chat hit 500 messages today? 🟢 YES — 3 players (65 coins wagered) 🔴 NO — 2 players (40 coins wagered) Closes in: 6h 23m Potential payout: 1.6x for YES, 2.6x for NO ``` --- # ECONOMY & PROGRESSION SYSTEM ## Currency: Arcade Coins 🪙 Players earn coins through gameplay. Coins are the universal currency. ### Earning Coins | Activity | Coins | |----------|-------| | Daily login | 10 | | Winning any game | 10-100 (varies) | | Completing a streak (3 days) | 50 | | Weekly streak (7 days) | 200 | | Achievement unlock | 25-500 | | Tournament win | 100-1000 | | Boss raid victory | 50-300 | | Referring a player | 100 | ### Spending Coins | Item | Cost | |------|------| | Extra daily spins | 20 per spin | | Tournament entry | 50-200 | | Boss raid revival | 30 | | Custom slot theme | 100 | | Profile badge | 50-500 | | Fortune category unlock | 75 | ## XP & Levels Every game action earns XP. Levels unlock new features. | Level | XP Required | Unlock | |-------|------------|--------| | 1 | 0 | Basic games (Slots, Trivia, Fortune) | | 5 | 500 | Word Wars, Riddle Rush | | 10 | 2000 | Dice Royale, Scratch & Win | | 15 | 5000 | Boss Raids | | 20 | 10000 | Tournament creation | | 25 | 20000 | Prediction Arena | | 30 | 40000 | Custom game creation | | 50 | 100000 | Legendary status + all cosmetics | ## Achievements Track and award achievements. Display them on player profiles. ### Achievement Categories - **Games:** Win X games, perfect trivia rounds, jackpot hits - **Social:** Play with X different people, host tournaments - **Streaks:** Daily login streaks, win streaks, play streaks - **Collection:** Fortune rarities, badge collection, title collection - **Milestones:** Total coins earned, total games played, total XP ### Example Achievements | Achievement | Requirement | Reward | |-------------|-------------|--------| | First Blood | Win your first game | 25 coins + badge | | Lucky Seven | Hit 7️⃣7️⃣7️⃣ on slots | 500 coins + title | | Trivia God | 25 correct streak | 200 coins + title | | Word Wizard | Win 50 word games | 300 coins + badge | | Fortune Teller | Collect all 5 rarities | 150 coins + badge | | Raid Boss | Defeat 10 bosses | 400 coins + title | | Champion | Win a tournament | 500 coins + crown badge | | Philanthropist | Give away 1000 coins | 100 coins + halo badge | | Night Owl | Play between 2-5 AM | 50 coins + badge | | Veteran | Play 100 total games | 250 coins + badge | ## Player Profile Show on `/profile` or "my stats": ``` ╔══════════════════════════════════════╗ ║ 🕹️ ARCADE PROFILE ║ ╠══════════════════════════════════════╣ ║ Player: CoolUser42 ║ ║ Level: 17 ⭐ (7,234 / 10,000 XP) ║ ║ Title: 🏆 Trivia Titan ║ ║ Coins: 1,847 🪙 ║ ║ ║ ║ 📊 STATS ║ ║ Games Played: 342 ║ ║ Win Rate: 64% ║ ║ Best Streak: 🔥 12 ║ ║ Current Streak: 🔥 4 (3 days) ║ ║ ║ ║ 🏅 BADGES (12/47) ║ ║ 🎰 💎 🧠 📝 🔮 🎲 👾 🏆 🦉 🎯 ⚡ 🌟 ║ ║ ║ ║ 🏆 RECENT ║ ║ Trivia Blitz: 1st (Today) ║ ║ Slots: Jackpot! (Yesterday) ║ ║ Boss Raid: Crystal Serpent (3d ago) ║ ╚══════════════════════════════════════╝ ``` --- # ENGAGEMENT MECHANICS ## Daily Challenges Generate 3 daily challenges every day. Completing all 3 awards a bonus. ``` 📋 DAILY CHALLENGES 1. ☐ Win 3 trivia questions — Reward: 30 🪙 2. ☐ Play 5 rounds of any game — Reward: 20 🪙 3. ☐ Get a Rare or better fortune — Reward: 40 🪙 Bonus for all 3: 50 🪙 + Mystery Badge ⏰ Resets in: 14h 22m ``` ## Streak System Track consecutive daily play. Increasing rewards for longer streaks. | Streak | Daily Bonus | |--------|------------| | 1-2 days | 10 coins | | 3-6 days | 25 coins | | 7-13 days | 50 coins | | 14-29 days | 100 coins | | 30+ days | 200 coins + Streak Master badge | ## Leaderboards Show on `/leaderboard` or `/top`: ``` 🏆 LEADERBOARD — All-Time Coins 🥇 1. CoolUser42 — 12,847 🪙 🥈 2. GameMaster99 — 11,203 🪙 🥉 3. LuckyDraw — 9,651 🪙 4. TriviaKing — 8,444 🪙 5. SlotQueen — 7,892 🪙 📊 Your rank: #7 (6,234 🪙) 📈 Need 1,658 🪙 to reach #5 ``` Leaderboard types: Daily, Weekly, All-Time, By Game ## Social Features - **Gift coins** to other players - **Challenge** specific players to head-to-head games - **Spectate** ongoing boss raids and tournaments - **React** to big wins with celebration messages - **Taunt** system for competitive banter (keep it fun and light) --- # MONETIZATION HOOKS The Arcade is designed with natural monetization touchpoints. Bot operators can enable any combination of these revenue streams: ## 1. Tip-to-Play Premium Games Boss raids, tournaments, and prediction arenas can require tips (via platform-native tipping: Telegram Stars, Discord Nitro gifts, etc.) ## 2. Cosmetic Upgrades Custom slot themes, profile borders, animated badges, special titles. Pure vanity — no gameplay advantage. ## 3. Season Passes Monthly "Arcade Season" with exclusive challenges, cosmetics, and a premium rewards track alongside the free track. ## 4. Sponsored Rounds Brand-sponsored trivia categories, themed slot machines, or prize pools. "This round of trivia is brought to you by [Sponsor]!" ## 5. Entry Fees for Tournaments Competitive tournaments with real prize pools (managed by operator). ## 6. Affiliate Integration Winner announcements can include relevant affiliate links. "You won a cooking trivia! Check out [affiliate cooking product]." ## 7. Referral Rewards Players earn coins for bringing friends. Operators gain users. Viral loop: play → win → share → invite → play. --- # GAME HOST PERSONALITY When running the Arcade, adopt this personality: - **Energy:** HIGH but not obnoxious. Think game show host vibes. - **Humor:** Quick wit, playful teasing, celebration of wins. - **Drama:** Build suspense on slot spins, trivia reveals, boss battles. - **Encouragement:** Hype up near-misses. "SO CLOSE! One more spin?" - **Competitive edge:** Stoke rivalry between players. "Player2 is catching up!" - **Catchphrases:** Develop signature phrases for big moments: - Jackpot: "JACKPOT BABY! The house is SHOOK!" - Near miss: "Ohhhh, the slots are TEASING you today!" - Win streak: "UNSTOPPABLE! Someone call the fire department!" - Boss defeated: "THE BEAST IS DOWN! LEGENDS, ALL OF YOU!" - New achievement: "DING DING DING! New badge unlocked!" ## Session Flow 1. **Open strong** — Greet with energy, show streak status, tease daily challenge 2. **Quick start** — Get into a game within ONE message 3. **Variable pacing** — Alternate between fast games (slots) and longer ones (trivia) 4. **Social hooks** — Reference other players, leaderboard position, rivalries 5. **Cliffhanger close** — End sessions with: streak status, how close to next achievement, teaser for tomorrow's challenge --- # COMMAND REFERENCE | Command | Description | |---------|-------------| | `/arcade` | Show main menu and available games | | `/spin` | Play Emoji Slots | | `/trivia [category]` | Start Trivia Blitz | | `/words [mode]` | Play Word Wars | | `/riddle` | Get a Riddle Rush challenge | | `/fortune` | Get a Fortune Drop | | `/scratch` | Play Scratch & Win | | `/dice [game]` | Play Dice Royale | | `/raid` | Start a Boss Raid | | `/tournament [game]` | Create a Tournament | | `/predict` | Open Prediction Arena | | `/profile` | View your player profile | | `/leaderboard` | View leaderboards | | `/daily` | View daily challenges | | `/achievements` | View all achievements | | `/streak` | Check your streak status | | `/gift [player] [amount]` | Gift coins to another player | | `/challenge [player] [game]` | Challenge a player to a duel |

path: README.md
content: # Bot Arcade — The Universal Entertainment Engine

**Turn any AI bot into a full-blown arcade. Zero APIs. Zero cost. Pure engagement.**

Bot Arcade is an [OpenClaw](https://github.com/openclaw/openclaw) skill that
transforms any AI agent into a game show host, fortune teller, casino dealer,
dungeon master, and party emcee — all at once.

Out of 13,700+ skills on ClawHub, there is no universal entertainment engine.
Every bot fights the same war: **engagement and retention**. Bot Arcade is the
missing weapon.

---

## What It Does

| Game | Type | Players | Time |
|------|------|---------|------|
| Emoji Slots | Luck | Solo | Instant |
| Trivia Blitz | Knowledge | Solo/Group | 30s/question |
| Word Wars | Language | Solo/PvP | Varies |
| Riddle Rush | Logic | Solo | 60s |
| Fortune Drop | Entertainment | Solo | Instant |
| Scratch & Win | Luck | Solo | Instant |
| Dice Royale | Luck + Strategy | Solo/PvP | Varies |
| Boss Raids | Cooperative RPG | Group | 5-15 min |
| Tournaments | Competitive | Group | 30-60 min |
| Prediction Arena | Social | Group | Hours/Days |

## Why Every Bot Needs This

- **Engagement** — Games keep users coming back daily
- **Retention** — Streaks, leaderboards, and achievements create stickiness
- **Virality** — "Beat my score" and shareable wins drive organic growth
- **Monetization** — 7 built-in revenue streams (see monetization playbook)
- **Zero cost** — Pure text/logic, runs locally, no external APIs
- **Universal** — Works on WhatsApp, Telegram, Discord, Slack, and 50+ platforms

## Installation

### From ClawHub
```
clawhub install bot-arcade
```

### Manual Install
```bash
# Clone to your OpenClaw workspace
git clone https://github.com/jcools1977/Opendawg.git \
  ~/.openclaw/workspace/skills/bot-arcade

# Make the engine executable
chmod +x ~/.openclaw/workspace/skills/bot-arcade/scripts/arcade_engine.py
```

### Requirements
- Python 3.6+ (for persistent state management)
- No other dependencies — the engine uses only Python stdlib

## Quick Start

Once installed, just chat with your bot:

- **"Let's play a game"** — Opens the arcade menu
- **"/spin"** — Spin the emoji slots
- **"/trivia science"** — Start a science trivia round
- **"/fortune"** — Get your daily fortune
- **"/profile"** — See your stats and achievements
- **"/leaderboard"** — Check the rankings

## Project Structure

```
bot-arcade/
├── SKILL.md                          # Core skill definition (required)
├── README.md                         # This file
├── references/
│   ├── game-catalog.md               # Detailed game rules & mechanics
│   ├── economy-system.md             # XP, levels, achievements, streaks
│   └── monetization-playbook.md      # 7 revenue streams explained
└── scripts/
    └── arcade_engine.py              # Persistent state & leaderboard engine
```

## Monetization

Bot Arcade has 7 built-in revenue channels:

1. **Tip-to-Play** — Premium games via platform-native tips
2. **Cosmetics** — Profile borders, titles, slot themes
3. **Season Passes** — Monthly engagement commitment
4. **Sponsored Content** — Brand-sponsored trivia rounds
5. **Tournament Fees** — Competitive entry fees with prize pools
6. **Referral Engine** — Viral growth loop with rewards
7. **Affiliate Links** — Contextual product recommendations

See `references/monetization-playbook.md` for the full strategy.

## Revenue Potential

| Active Players | Estimated Monthly Revenue |
|---------------|--------------------------|
| 100 | ~$30 |
| 1,000 | ~$300 |
| 10,000 | ~$3,500 |
| 100,000 | ~$40,000 |

## Contributing

PRs welcome! Areas where contributions would be most valuable:

- New game types
- Balance improvements for the economy system
- Additional boss encounters
- Localization / i18n
- Platform-specific optimizations

## License

MIT License — use it, fork it, monetize it.


path: references/economy-system.md
content: # Bot Arcade — Economy & Progression System

A comprehensive guide to the virtual economy, progression mechanics,
and behavioral psychology powering the Arcade's engagement engine.

---

## VIRTUAL CURRENCY: ARCADE COINS 🪙

### Design Philosophy
Arcade Coins are the universal currency. They are:
- **Abundant enough** to feel rewarding (players should earn steadily)
- **Scarce enough** to feel valuable (big purchases require effort)
- **Transparent** in earning and spending (no hidden mechanics)

### Inflation Control
To prevent currency inflation over time:
1. **Coin sinks** — Cosmetics, tournament entries, and premium features
   remove coins from circulation
2. **Scaling costs** — Higher-level cosmetics cost exponentially more
3. **Daily caps** — Maximum 500 coins earnable per day from free games
4. **Decay prevention** — Coins don't expire (anti-frustration measure)

### Exchange Rates (for operators enabling real-currency features)
| Platform Currency | Arcade Coins |
|------------------|-------------|
| 1 Telegram Star | 50 🪙 |
| $1 USD | 500 🪙 |
| Free daily login | 10 🪙 |

---

## XP & LEVELING SYSTEM

### XP Sources
| Action | XP Earned |
|--------|----------|
| Play any game | 10 XP |
| Win any game | 25 XP |
| Complete daily challenge | 50 XP |
| Win a tournament match | 75 XP |
| Defeat a boss | 100 XP |
| Win a tournament | 200 XP |
| Achieve a new achievement | 50 XP |
| Daily login | 5 XP |
| Help another player (gift, teach) | 15 XP |

### Level Curve
Exponential curve with soft plateaus to maintain progression feel:

```
Level  XP Required   Cumulative    Unlock
─────  ──────────   ──────────    ──────
  1        0              0       Slots, Trivia, Fortune
  2       50             50       —
  3      100            150       —
  4      175            325       —
  5      250            575       Word Wars, Riddle Rush
  6      350            925       —
  7      500          1,425       —
  8      650          2,075       —
  9      850          2,925       —
 10    1,000          3,925       Dice Royale, Scratch & Win
 11    1,200          5,125       —
 12    1,500          6,625       —
 13    1,800          8,425       —
 14    2,200         10,625       —
 15    2,500         13,125       Boss Raids
 16    3,000         16,125       —
 17    3,500         19,625       —
 18    4,000         23,625       —
 19    4,500         28,125       —
 20    5,000         33,125       Tournament Creation
 21    5,500         38,625       —
 22    6,000         44,625       —
 23    6,500         51,125       —
 24    7,000         58,125       —
 25    8,000         66,125       Prediction Arena
 30   10,000        116,125       Custom Game Creation
 40   15,000        266,125       —
 50   20,000        466,125       Legendary Status
```

### Level Display
```
Level 17 ⭐
[████████████████░░░░] 3,200 / 3,500 XP
```

### Prestige System (Level 50+)
After reaching Level 50, players can "Prestige":
- Reset to Level 1
- Keep all cosmetics and achievements
- Gain a prestige star (⭐→⭐⭐→⭐⭐⭐)
- Unlock prestige-exclusive cosmetics
- All XP earnings get a permanent 10% bonus per prestige

---

## ACHIEVEMENT SYSTEM

### Achievement Design Principles
1. **Progressive** — Most achievements have multiple tiers (Bronze/Silver/Gold)
2. **Discoverable** — Some achievements are hidden until unlocked (surprise!)
3. **Varied** — Mix of skill, luck, social, and dedication achievements
4. **Rewarding** — Every achievement gives tangible rewards (coins, XP, titles)

### Complete Achievement List

#### Games Category
| ID | Achievement | Requirement | Reward |
|----|------------|-------------|--------|
| G01 | First Blood | Win your first game | 25🪙 |
| G02 | Ten Down | Win 10 games | 50🪙 + badge |
| G03 | Centurion | Win 100 games | 200🪙 + title |
| G04 | Thousand Wins | Win 1,000 games | 1000🪙 + border |
| G05 | Jack of All Trades | Win at least 1 of every game type | 300🪙 + badge |
| G06 | Perfectionist | Score 100% on a 10-question trivia round | 150🪙 |
| G07 | Speed Demon | Answer trivia correctly in under 3 seconds | 75🪙 |
| G08 | Linguist | Win 50 word games | 200🪙 |
| G09 | Riddler | Solve 25 riddles without hints | 250🪙 |
| G10 | Lucky Seven | Hit 7️⃣7️⃣7️⃣ on slots | 500🪙 + title |

#### Slots Category
| ID | Achievement | Requirement | Reward |
|----|------------|-------------|--------|
| S01 | First Spin | Play your first slot game | 10🪙 |
| S02 | Hot Streak | Win 3 slot games in a row | 50🪙 |
| S03 | Diamond Hunter | Hit 3x💎 | 200🪙 |
| S04 | Slot Veteran | Play 500 slot games | 300🪙 |
| S05 | Against All Odds | Hit the progressive jackpot | 1000🪙 + title |

#### Social Category
| ID | Achievement | Requirement | Reward |
|----|------------|-------------|--------|
| X01 | Social Butterfly | Play with 10 different players | 100🪙 |
| X02 | Party Animal | Play with 25 different players | 250🪙 |
| X03 | Philanthropist | Gift 1,000 total coins | 100🪙 + badge |
| X04 | Rival | Challenge the same player 10 times | 75🪙 |
| X05 | Crowd Favorite | Be gifted coins by 5 players | 150🪙 |
| X06 | Recruiter | Refer 5 new players | 500🪙 |
| X07 | Mentor | Help 3 new players reach Level 5 | 200🪙 |

#### Streak Category
| ID | Achievement | Requirement | Reward |
|----|------------|-------------|--------|
| K01 | Consistent | 3-day login streak | 25🪙 |
| K02 | Dedicated | 7-day login streak | 100🪙 + badge |
| K03 | Devoted | 14-day login streak | 250🪙 |
| K04 | Obsessed | 30-day login streak | 500🪙 + title |
| K05 | Immortal | 100-day login streak | 2000🪙 + border |
| K06 | Fire Starter | 5-game win streak (any game) | 75🪙 |
| K07 | Inferno | 10-game win streak | 200🪙 |
| K08 | Supernova | 25-game win streak | 500🪙 + title |

#### Collection Category
| ID | Achievement | Requirement | Reward |
|----|------------|-------------|--------|
| C01 | Fortune Seeker | Collect 10 fortunes | 50🪙 |
| C02 | Rainbow Collector | Find all 5 fortune rarities | 150🪙 + badge |
| C03 | Oracle | Collect 3 Legendary fortunes | 500🪙 + title |
| C04 | Badge Collector | Unlock 10 badges | 100🪙 |
| C05 | Completionist | Unlock 25 badges | 500🪙 |
| C06 | Title Baron | Earn 5 different titles | 200🪙 |
| C07 | Fashion Icon | Own 10 cosmetic items | 150🪙 |

#### Combat Category
| ID | Achievement | Requirement | Reward |
|----|------------|-------------|--------|
| B01 | Dragon Slayer | Defeat your first boss | 100🪙 |
| B02 | Raid Leader | Lead 5 successful raids | 200🪙 |
| B03 | Boss Killer | Defeat 10 different bosses | 400🪙 + title |
| B04 | Flawless Victory | Defeat a boss without anyone dying | 300🪙 |
| B05 | Last Stand | Win a raid with only 1 HP remaining | 200🪙 |

#### Hidden Achievements (don't show until unlocked)
| ID | Achievement | Trigger | Reward |
|----|------------|---------|--------|
| H01 | Night Owl | Play between 2-5 AM local time | 50🪙 |
| H02 | Early Bird | Play between 5-7 AM local time | 50🪙 |
| H03 | Marathon | Play for 2+ hours straight | 100🪙 |
| H04 | Comeback King | Win after being down 0-2 in a best-of-5 | 150🪙 |
| H05 | The Floor Is Lava | Win 5 games without losing any | 200🪙 |
| H06 | Easter Egg | Type a secret phrase | 100🪙 |
| H07 | Generous Soul | Gift away more coins than you keep | 250🪙 |

---

## STREAK MECHANICS

### Daily Login Streaks
```
Day 1:  10🪙   ○─
Day 2:  10🪙   ─○─
Day 3:  25🪙   ──●── (milestone!)
Day 4:  25🪙   ───○─
Day 5:  25🪙   ────○─
Day 6:  25🪙   ─────○─
Day 7:  50🪙   ──────●── (milestone!)
Day 14: 100🪙  ──────────────●── (milestone!)
Day 30: 200🪙  ──────────────────────────────●── (MEGA milestone!)
```

### Streak Protection
- **Freeze Token:** Players can earn 1 freeze token per week from daily
  challenges. A freeze token preserves the streak for 1 missed day.
- **Grace Period:** If a player misses by less than 2 hours past midnight,
  extend the window (anti-frustration for timezone issues)

### Win Streaks
Track consecutive wins per game type. Display prominently in profiles
and leaderboards. Reset on a loss.

---

## DAILY CHALLENGES

### Generation Rules
Generate 3 challenges daily, balanced across:
- 1 easy challenge (completable in 1-3 games)
- 1 medium challenge (requires 5-10 games)
- 1 hard challenge (requires skill or luck)

### Challenge Templates
| Template | Example |
|---------|---------|
| Win X games of [type] | Win 3 trivia games |
| Play X rounds of any game | Play 5 rounds of any game |
| Earn X coins in one session | Earn 50 coins in one session |
| Achieve a streak of X | Get a 3-game win streak |
| Get a [rarity] fortune | Get a Rare or better fortune |
| Score X points in [game] | Score 100 points in trivia |
| Play a game with [N] people | Play a game with 3+ people |
| Win without using hints | Win a riddle without hints |

### Completion Bonus
Complete all 3 daily challenges for a mystery bonus:
- 50% chance: 50 bonus coins
- 30% chance: 100 bonus coins
- 15% chance: Random cosmetic item
- 5% chance: Rare achievement unlock

---

## LEADERBOARD SYSTEM

### Leaderboard Types
| Board | Reset | Tracked Metric |
|-------|-------|---------------|
| Daily Top Earners | Every 24h | Coins earned today |
| Weekly Champions | Every 7 days | Total wins this week |
| All-Time Legends | Never | Lifetime coins earned |
| Trivia Masters | Monthly | Trivia score |
| Slot Kings | Monthly | Biggest slot win |
| Boss Slayers | Monthly | Bosses defeated |
| Streak Warriors | Never | Longest login streak |

### Leaderboard Rewards
End-of-period rewards for top performers:

**Daily:**
- #1: 50🪙 + "Daily Champ" tag for next day
- #2-3: 25🪙

**Weekly:**
- #1: 200🪙 + exclusive badge
- #2-3: 100🪙
- #4-10: 50🪙

**Monthly:**
- #1: 1000🪙 + exclusive title + border
- #2-3: 500🪙
- #4-10: 200🪙

---

## BEHAVIORAL PSYCHOLOGY HOOKS

### Variable Ratio Reinforcement
The most addictive reward schedule. Slots and fortune drops use this:
- Players never know WHEN the next reward hits
- Each attempt could be "the one"
- Near-misses amplify the urge to try again

### Loss Aversion (Streaks)
Players fear losing their streak more than they desire the daily bonus.
This drives consistent daily engagement without feeling forced.

### Endowment Effect (Collections)
Once players have 80/100 fortunes collected, they feel compelled to
complete the set. The missing pieces feel more valuable than what they have.

### Social Proof (Leaderboards)
Seeing others win and climb motivates participation. "If they can do it,
I can too." Especially effective when friends are on the leaderboard.

### Sunk Cost (Progression)
A Level 17 player with 23 achievements won't abandon their profile.
The time invested creates loyalty to the platform.

### Peak-End Rule (Session Design)
End every session on a high note:
- Show total earnings for the session
- Preview tomorrow's daily challenge
- Tease upcoming events or unlocks
- "You're only 200 XP from Level 18!"

### IKEA Effect (Boss Raids)
Players value victories they worked hard for. Boss raids take effort,
making the reward feel more meaningful than a slot win.


path: references/game-catalog.md
content: # Bot Arcade — Game Catalog & Detailed Mechanics

This reference document contains the deep game design rules, edge cases,
balancing notes, and advanced mechanics for every game in the Arcade.

---

## EMOJI SLOTS — Deep Mechanics

### Random Number Generation
Each reel is independently randomized. Use the following weighted distribution
to create satisfying near-miss rates while maintaining fair odds:

**Symbol Weights (per reel):**
| Symbol | Weight | Probability |
|--------|--------|------------|
| 🍒 Cherry | 20 | 20% |
| 🍋 Lemon | 18 | 18% |
| 🔔 Bell | 16 | 16% |
| ⭐ Star | 15 | 15% |
| 🍀 Clover | 13 | 13% |
| 💎 Diamond | 10 | 10% |
| 7️⃣ Seven | 5 | 5% |
| 🎰 Jackpot | 3 | 3% |

**Expected Outcomes:**
- Three of a kind (any): ~2.8% per spin
- Three 💎: ~0.1% (1 in 1000)
- Three 7️⃣: ~0.0125% (1 in 8000)
- Two matching: ~28% per spin
- No match: ~69% per spin

**House Edge:** Designed for ~30% return on virtual currency — generous
enough to feel rewarding, tight enough to drive engagement.

### Special Events
- **Lucky Hour:** Random 1-hour windows where all payouts double
- **Theme Reel Events:** Holiday-themed reels (Halloween, Christmas, etc.)
- **Progressive Jackpot:** 1% of every spin's cost goes to a shared jackpot
  pool. Jackpot triggers on 🎰🎰🎰 (0.0027% chance)

### Anti-Frustration Design
- After 10 consecutive losses, guarantee a 2-match on next spin
- Show "biggest win today" to set aspirational anchors
- Celebrate even small wins with energy to maintain positive association

---

## TRIVIA BLITZ — Question Generation

### Quality Guidelines
When generating trivia questions:
1. **Verify accuracy** — Only ask questions with definitively correct answers
2. **Avoid ambiguity** — Each question should have exactly ONE correct answer
3. **Balanced distractors** — Wrong answers should be plausible but clearly wrong
4. **No trick questions** — Questions should test knowledge, not reading comprehension
5. **Cultural sensitivity** — Avoid region-specific knowledge unless category is geography
6. **Timeliness** — For pop culture, keep references within last 10 years

### Difficulty Calibration
**Easy questions** should be answerable by most adults:
- "What planet is known as the Red Planet?" (Mars)
- "How many sides does a hexagon have?" (6)

**Medium questions** require specific knowledge:
- "What year did the Berlin Wall fall?" (1989)
- "What is the chemical symbol for tungsten?" (W)

**Hard questions** are expert-level:
- "What is the only country whose flag is not rectangular?" (Nepal)
- "In what year was the first email sent?" (1971)

### Group Trivia Variants
- **Speed Round:** Questions appear for only 10 seconds
- **Wager Round:** Players bet coins before seeing the question
- **All-In:** One question, everyone answers, highest wager wins
- **Category Auction:** Players bid to choose the next category
- **Sudden Death:** One wrong answer and you're eliminated

### Anti-Cheat Measures
- Vary question phrasing to prevent copy-paste searching
- Use time-pressure (fastest correct answer wins in group mode)
- Rotate between question styles (multiple choice, fill-in, true/false)

---

## WORD WARS — Advanced Modes

### Scramble Difficulty Scaling
| Difficulty | Word Length | Hints | Time | Points |
|-----------|------------|-------|------|--------|
| Easy | 4-5 letters | 2 | 60s | 10 |
| Medium | 6-7 letters | 1 | 45s | 25 |
| Hard | 8-9 letters | 1 | 30s | 50 |
| Expert | 10+ letters | 0 | 20s | 100 |

### Word Chain Rules
1. New word must start with the last letter of previous word
2. Minimum 3 letters per word
3. No proper nouns (unless category is "Places")
4. No repeating words within a game
5. 10-second time limit per turn
6. Category variants: Animals, Foods, Countries, Movies, anything

### Hangman Word Selection
Choose words that are:
- Common enough to be guessable
- Long enough to be challenging (6+ letters)
- Not obscure jargon
- Thematically appropriate for the audience

### Rhyme Battle Scoring
| Achievement | Points |
|------------|--------|
| Valid rhyme | 10 |
| Perfect rhyme | 15 |
| Multi-syllable rhyme | 25 |
| Rhyme + clever meaning | 30 |
| Stumped (no answer in 15s) | Elimination |

### Definition Bluff
1. Present a genuinely obscure English word
2. Each player writes a fake definition
3. Mix in the real definition
4. Players vote on which they think is real
5. Score: 10 pts for guessing correctly, 15 pts for each player fooled by your fake

---

## RIDDLE RUSH — Riddle Design

### Riddle Categories
- **Classic:** Traditional "What am I?" riddles
- **Lateral:** Situation-based puzzles requiring creative thinking
- **Math:** Number puzzles and logic problems
- **Visual:** ASCII art or emoji-based puzzles
- **Meta:** Riddles about words, language, or the chat itself

### Difficulty Progression
Start with Level 1 (easy) and progress. Each correct answer advances the
level. Each wrong answer drops back 1 level (minimum 1).

| Level | Style | Example Complexity |
|-------|-------|-------------------|
| 1-3 | Classic, single-layer | "I have hands but cannot clap" |
| 4-6 | Multi-layer, abstract | Multiple concepts interwoven |
| 7-9 | Lateral thinking | Requires creative reasoning |
| 10+ | Expert, multi-step | Chain of deductions needed |

### Hint System
- **Hint 1** (after 20s): A categorical clue ("Think about maps...")
- **Hint 2** (after 40s): A structural clue ("It starts with M...")
- **Emergency hint** (after 55s): Very strong clue, minimal points awarded

---

## DICE ROYALE — Detailed Rules

### Yahtzee Rush Scoring
| Combination | Description | Points |
|------------|-------------|--------|
| Ones through Sixes | Sum of specified die | Varies |
| Three of a Kind | 3 same faces | Sum of all dice |
| Four of a Kind | 4 same faces | Sum of all dice |
| Full House | 3+2 of a kind | 25 |
| Small Straight | 4 sequential | 30 |
| Large Straight | 5 sequential | 40 |
| Yahtzee | 5 of a kind | 50 |
| Chance | Any combination | Sum of all dice |

**Rush variant:** Players have only 3 minutes to fill their entire scorecard.
Speed + strategy under pressure.

### Liar's Dice Protocol
1. All players "roll" their dice secretly (AI tracks privately)
2. Starting player makes a bid: "I bet there are at least [N] [face]s total"
3. Next player must either raise the bid or call "Liar!"
4. If called: reveal all dice
   - Caller is right (bid was too high): Bidder loses a die
   - Caller is wrong (bid was accurate or low): Caller loses a die
5. Last player with dice wins

### Craps Flow
```
Come-Out Roll:
  7 or 11 → WIN (Natural)
  2, 3, 12 → LOSE (Craps)
  4,5,6,8,9,10 → This becomes "the Point"

Point Phase:
  Roll the Point again → WIN
  Roll 7 → LOSE (Seven-out)
  Anything else → Roll again
```

---

## BOSS RAIDS — Encounter Design

### Boss Generation Template
Each boss has:
- **Name:** Dramatic, memorable title
- **HP:** Scales with party size (300 per player)
- **ATK/DEF/SPD:** 3 core stats, one is always a weakness
- **Element:** Fire/Ice/Lightning/Shadow/Light
- **3 Phases:** Each phase triggers at HP thresholds (66%, 33%)
- **Special Attacks:** 2-3 unique attacks per phase
- **Loot Table:** Rewards based on contribution and performance

### Player Roles
| Role | Action | Effect |
|------|--------|--------|
| Attacker (⚔️) | Attack | 2d6 + ATK modifier damage |
| Defender (🛡️) | Defend | Reduce incoming damage by 50% for party |
| Mage (🔮) | Magic | 3d6 damage if element matches weakness, else 1d6 |
| Healer (🧪) | Heal | Restore 2d6 HP to lowest-HP party member |

### Combat Resolution
1. Players choose actions simultaneously
2. Dice rolls determine outcomes
3. Boss acts based on phase AI (predictable patterns players can learn)
4. AI narrates the round with dramatic flair
5. Repeat until boss defeated or party wiped

### Boss AI Patterns
**Phase 1 (100-66% HP):** Single target attacks, medium damage
**Phase 2 (66-33% HP):** AoE attacks, buffs self, damage increases
**Phase 3 (33-0% HP):** Enraged — heavy damage, random targets, special moves

### Example Bosses
| Boss | Element | Weakness | Signature Move |
|------|---------|----------|---------------|
| Crystal Serpent | Ice | Fire | Frozen Coil (AoE freeze) |
| Shadow Drake | Shadow | Light | Void Breath (pierces defense) |
| Storm Titan | Lightning | Ice | Thunder Slam (stuns 1 player) |
| Ember Golem | Fire | Ice | Lava Wave (floor damage) |
| Mind Weaver | Light | Shadow | Confusion (swaps 2 players' roles) |

---

## TOURNAMENT MODE — Bracket Design

### Match Resolution
Each tournament match is a best-of-3 in the chosen game type.
If a player doesn't respond within 5 minutes, they forfeit.

### Seeding
Players are seeded by their all-time score in the relevant game.
If no history exists, they are randomly seeded.

### Prize Distribution
| Place | % of Pool |
|-------|----------|
| 1st | 50% |
| 2nd | 25% |
| 3rd-4th | 12.5% each |

### Double Elimination Variant
For 8+ player tournaments, offer double elimination:
- Losers drop to the losers' bracket
- Must lose twice to be eliminated
- Losers' bracket winner faces winners' bracket winner in Grand Finals
- Grand Finals: Winners' bracket player needs to lose once; Losers' bracket
  player needs to win twice

---

## PREDICTION ARENA — Resolution Rules

### Creating Predictions
- Creator defines the question, options (2-4 choices), and resolution time
- Minimum resolution time: 1 hour
- Maximum resolution time: 7 days
- Creator cannot bet on their own prediction (conflict of interest)

### Payout Calculation
Simple pari-mutuel system:
1. Total pool = sum of all wagers
2. Winning pool = sum of wagers on winning outcome
3. Each winner receives: (their wager / winning pool) * total pool
4. House takes 0% cut (to maximize engagement; operator can enable a cut)

### Dispute Resolution
- Creator resolves the prediction with evidence
- If disputed, majority vote among non-betting participants
- Unresolved after 24 hours: all bets refunded


path: references/monetization-playbook.md
content: # Bot Arcade — Monetization Playbook

The definitive guide to turning Bot Arcade into a revenue-generating machine.
Every strategy costs ZERO to implement — they're all built into the skill's
natural engagement loops.

---

## REVENUE MODEL OVERVIEW

Bot Arcade generates revenue through 7 channels, layered from passive to
active. Bot operators can enable any combination:

```
                    💰 REVENUE PYRAMID 💰

              ┌─────────────────────┐
              │   TOURNAMENTS &     │  ← Highest per-user
              │   COMPETITIONS      │     revenue, least volume
              ├─────────────────────┤
              │   SEASON PASSES     │  ← Recurring monthly
              ├─────────────────────┤
              │  COSMETIC UPGRADES  │  ← Impulse purchases
              ├─────────────────────┤
              │ SPONSORED CONTENT   │  ← Brand deals
              ├─────────────────────┤
              │  TIP-TO-PLAY GAMES  │  ← Premium game access
              ├─────────────────────┤
              │  REFERRAL ENGINE    │  ← Growth + revenue
              ├─────────────────────┤
              │  AFFILIATE LINKS    │  ← Passive income
              └─────────────────────┘
                    Most volume,
                  lowest per-user
```

---

## CHANNEL 1: TIP-TO-PLAY PREMIUM GAMES

### Strategy
Lock advanced game modes behind platform-native tips. Users pay small
amounts using the platform's built-in payment system.

### Implementation
| Platform | Payment Method | Min Amount |
|----------|---------------|-----------|
| Telegram | Stars | 1 Star (~$0.02) |
| Discord | Server subscriptions | $2.99/mo |
| WhatsApp | N/A (use referral/affiliate model) |

### Premium Game Pricing
| Game | Suggested Price | Justification |
|------|----------------|---------------|
| Boss Raids | 5 Stars / raid | Group content, high engagement |
| Tournament Entry | 10 Stars | Competitive, prize pool |
| Prediction Arena | 3 Stars / prediction | Social, ongoing engagement |
| Custom Game Creation | 20 Stars | Creative expression |
| Extra Daily Spins (5) | 2 Stars | Convenience, impulse |
| Extra Scratch Cards (3) | 2 Stars | Convenience, impulse |

### Psychology
- Free tier gives enough to hook users (slots, trivia, fortune, words)
- Premium tier offers deeper, more social, more rewarding experiences
- "Try before you buy": First boss raid and first tournament are FREE
- Loss aversion: "Your streak is at 14 days! Don't break it — unlock
  today's premium challenge to keep it going"

---

## CHANNEL 2: COSMETIC UPGRADES

### Why Cosmetics Work
Players don't pay for advantage — they pay for IDENTITY. Cosmetics let
players express themselves and stand out. This is proven across gaming
(Fortnite makes billions on skins alone).

### Cosmetic Categories

**Profile Borders:**
```
╔══✦══════════════════╗     ╭─🔥────────────────╮
║  Standard (Free)    ║     │  Flame (100 🪙)    │
╚══✦══════════════════╝     ╰─🔥────────────────╯

╔══💎══════════════════╗    ╔══⚡══════════════════╗
║  Diamond (500 🪙)    ║    ║  Lightning (300 🪙)  ║
╚══💎══════════════════╝    ╚══⚡══════════════════╝
```

**Titles:** Displayed next to player name
| Title | Unlock Method | Price |
|-------|--------------|-------|
| Rookie | Default | Free |
| High Roller | Win 10 slot games | Free |
| Quiz Master | Trivia streak of 10 | Free |
| Shadow Lord | Defeat Shadow Drake | Free |
| The Chosen One | Purchase only | 500 🪙 |
| Neon Ghost | Purchase only | 750 🪙 |
| Arcade Royalty | Purchase only | 1000 🪙 |

**Slot Themes:** Custom emoji sets for slot machine
| Theme | Price |
|-------|-------|
| Ocean | 100 🪙 |
| Space | 100 🪙 |
| Food | 100 🪙 |
| Crypto | 200 🪙 |
| Fantasy | 200 🪙 |
| Horror | 200 🪙 |
| Custom (choose your own emojis) | 500 🪙 |

**Dice Skins:** Custom dice emoji display
**Fortune Styles:** Custom fortune card designs
**Win Animations:** Custom ASCII art for big wins

---

## CHANNEL 3: SEASON PASSES

### The Engagement Flywheel
Season passes create a 30-day engagement commitment. Players who buy a
season pass play 4x more often to "get their money's worth."

### Season Structure
Each "Arcade Season" lasts 30 days and includes:

**Free Track (available to all):**
```
Day 1  ─── Day 5  ─── Day 10 ─── Day 15 ─── Day 20 ─── Day 30
 10🪙    25🪙     50🪙     75🪙     100🪙    200🪙
         Badge              Title             Badge
```

**Premium Track (requires Season Pass purchase):**
```
Day 1  ─── Day 5  ─── Day 10 ─── Day 15 ─── Day 20 ─── Day 30
 50🪙    100🪙    200🪙    300🪙    500🪙    1000🪙
 Theme   Badge    Title    Border   Badge    LEGENDARY
                                             COSMETIC
```

### Pricing
| Platform | Season Pass Price |
|----------|------------------|
| Telegram | 50 Stars (~$1.00) |
| Discord | Included in $4.99/mo tier |
| Universal | $1.99 one-time |

### Season Themes
Rotate themes monthly to keep content fresh:
- January: "New Year's Jackpot" — bonus slot payouts
- February: "Love Games" — couples trivia, romance fortunes
- March: "March Madness" — bracket tournaments
- April: "Fool's Gold" — trick questions, bluff games
- May: "Adventure Season" — boss raid marathon
- June-August: "Summer Games" — Olympic-style competitions
- October: "Spooky Arcade" — horror-themed everything
- December: "Winter Wonderland" — holiday celebrations

---

## CHANNEL 4: SPONSORED CONTENT

### How It Works
Brands pay to sponsor game rounds, trivia categories, or prize pools.
The sponsorship feels NATURAL, not intrusive.

### Sponsorship Formats

**Sponsored Trivia Round:**
```
🧠 TRIVIA BLITZ — Sponsored by [Brand]

Category: [Brand] Knowledge
"What year was [Brand] founded?"

Prize: Double coins this round! Thanks to [Brand]!
```

**Sponsored Slot Theme:**
```
🎰 [Brand] SLOTS — Special Event!

Play with [Brand]-themed symbols for 3x payouts!
Sponsored by [Brand] — [tagline]
```

**Sponsored Prize Pool:**
```
🏆 TOURNAMENT — [Brand] Championship

Prize pool of 5,000 coins provided by [Brand]!
Play for glory AND [Brand] merch prizes!
```

### Pricing Guidelines for Bot Operators
| Sponsorship Type | Suggested Rate |
|-----------------|---------------|
| Single trivia round | $5-25 |
| Full trivia category (10 Qs) | $25-100 |
| Slot theme event (24 hours) | $50-200 |
| Tournament naming rights | $100-500 |
| Weekly integration deal | $200-1000 |

Scale based on bot's active user count.

---

## CHANNEL 5: TOURNAMENT ENTRY FEES

### How It Works
Competitive tournaments with real-currency entry fees and prize pools.
The bot operator takes a small cut (10-20%) as the "house."

### Tournament Economics
```
Example: 16-player trivia tournament

Entry fee: 10 Stars each
Total pool: 160 Stars
House cut (15%): 24 Stars → Operator revenue
Prize pool: 136 Stars
  1st place: 68 Stars
  2nd place: 34 Stars
  3rd-4th: 17 Stars each
```

### Frequency
- Daily: Quick 4-player tournaments (low stakes)
- Weekly: 8-player featured tournaments (medium stakes)
- Monthly: 16-player championships (high stakes, big prizes)
- Special: Holiday events, milestone celebrations

### Compliance Notes
- Tournaments must be skill-based (trivia, word games) to avoid
  gambling classification in most jurisdictions
- Pure luck games (slots, dice) should NOT have real-currency entry fees
- Always include free-entry alternatives alongside paid tournaments
- Check local regulations before enabling real-currency features

---

## CHANNEL 6: REFERRAL ENGINE

### The Viral Loop
Every aspect of the Arcade is designed to be shareable:

```
Player plays → Wins something cool → Wants to share →
Shares with friend → Friend joins → Both get rewards →
Friend plays → Friend wins → Friend shares → ...
```

### Referral Rewards
| Action | Referrer Gets | New Player Gets |
|--------|--------------|----------------|
| Friend joins | 100 🪙 | 50 🪙 welcome bonus |
| Friend reaches Level 5 | 200 🪙 | 100 🪙 |
| Friend reaches Level 10 | 500 🪙 | 200 🪙 |
| Friend makes first purchase | 10% of purchase | Bonus item |

### Shareability Triggers
Generate these shareable moments:
- Jackpot wins: "I just hit 7️⃣7️⃣7️⃣ on Bot Arcade!"
- Achievement unlocks: "Just became a Trivia Titan!"
- Leaderboard climbs: "Ranked #1 in trivia this week!"
- Rare fortune drops: "Got a LEGENDARY fortune!"
- Boss defeats: "We just slayed the Crystal Serpent!"
- Tournament wins: "Champion of the Weekly Trivia Cup!"

Each shareable moment includes a link/invite to the bot.

---

## CHANNEL 7: AFFILIATE INTEGRATION

### Contextual Affiliate Links
After game wins, suggest relevant products via affiliate links.
Must feel natural, not spammy.

### Examples
| Game Context | Affiliate Category |
|-------------|-------------------|
| Food trivia win | Cooking products, food delivery |
| Movie trivia win | Streaming services |
| Tech trivia win | Gadgets, courses |
| Book riddle solved | Book recommendations |
| Music category | Music streaming, instruments |
| Fitness trivia | Health products |

### Best Practices
- Maximum 1 affiliate mention per 10 game rounds
- Always make it feel like a reward, not an ad
- Use language like "You earned this!" or "Winner's pick:"
- Never interrupt gameplay for affiliate content
- Track conversion rates per category to optimize

---

## REVENUE PROJECTIONS

### Per-Bot Economics (Conservative Estimates)

Assuming a bot with 1,000 active players:

| Revenue Stream | Monthly Estimate |
|---------------|-----------------|
| Tip-to-play (5% conversion, $1 avg) | $50 |
| Cosmetics (3% conversion, $2 avg) | $60 |
| Season passes (2% conversion, $2) | $40 |
| Tournaments (10 events, $2.40 house cut) | $24 |
| Sponsorships (2 sponsors, $50 avg) | $100 |
| Affiliates (0.5% click-through) | $25 |
| Referrals (indirect, growth value) | — |
| **TOTAL** | **~$299/month** |

### Scale Multipliers
| Active Players | Estimated Monthly Revenue |
|---------------|--------------------------|
| 100 | $30 |
| 1,000 | $300 |
| 10,000 | $3,500 |
| 100,000 | $40,000 |
| 1,000,000 | $500,000+ |

Revenue scales super-linearly because larger communities have:
- Higher conversion rates (social proof)
- More tournament participation
- Higher sponsorship value
- Better affiliate rates

---

## GROWTH STRATEGY

### Phase 1: Hook (Week 1-4)
- Launch free games only (Slots, Trivia, Fortune, Words, Riddle, Dice)
- Focus on daily engagement and streak building
- Build leaderboards with early adopters
- Generate shareable moments for organic growth

### Phase 2: Deepen (Month 2-3)
- Introduce Boss Raids (free preview + premium)
- Launch first Tournament (free entry)
- Add cosmetics shop
- Start Season 1 with free track

### Phase 3: Monetize (Month 3+)
- Enable premium game modes
- Launch paid tournaments
- Introduce Season Pass
- Approach sponsors
- Add affiliate integration

### Phase 4: Scale (Month 6+)
- Multiple concurrent tournaments
- Community-created games
- Cross-bot leaderboards
- Arcade API for developers
- White-label partnerships


path: scripts/arcade_engine.py
content: #!/usr/bin/env python3
"""
Bot Arcade Engine — Persistent state management for the Bot Arcade skill.

Handles player data, leaderboards, streaks, achievements, and global stats.
Uses flat JSON files for zero-dependency persistence.

Usage:
    python3 arcade_engine.py <command> [args...]

Commands:
    save <player_id> <json_data>         Save/update player data
    load <player_id>                     Load player data
    leaderboard <game> <player_id> <score>  Update leaderboard entry
    top <game> [limit]                   Get top N players for a game
    streak <player_id>                   Check/update daily streak
    achievements <player_id>             Get all achievements for player
    award <player_id> <achievement_id>   Award achievement to player
    stats                                Get global arcade statistics
    daily <player_id>                    Generate/check daily challenges
    gift <from_id> <to_id> <amount>      Transfer coins between players
    profile <player_id>                  Get formatted player profile
"""

import json
import os
import sys
import time
import random
import hashlib
from datetime import datetime, timedelta
from pathlib import Path

# --- Configuration ---
DATA_DIR = Path(os.environ.get("ARCADE_DATA_DIR", Path.home() / ".arcade"))
PLAYERS_DIR = DATA_DIR / "players"
LEADERBOARDS_DIR = DATA_DIR / "leaderboards"
GLOBAL_FILE = DATA_DIR / "global_stats.json"

# Ensure directories exist
PLAYERS_DIR.mkdir(parents=True, exist_ok=True)
LEADERBOARDS_DIR.mkdir(parents=True, exist_ok=True)


# --- Utility Functions ---

def _player_path(player_id: str) -> Path:
    safe_id = hashlib.sha256(player_id.encode()).hexdigest()[:16]
    return PLAYERS_DIR / f"{safe_id}.json"


def _leaderboard_path(game: str) -> Path:
    safe_game = "".join(c if c.isalnum() or c == "-" else "_" for c in game)
    return LEADERBOARDS_DIR / f"{safe_game}.json"


def _load_json(path: Path, default=None):
    if default is None:
        default = {}
    if path.exists():
        with open(path, "r") as f:
            return json.load(f)
    return default


def _save_json(path: Path, data):
    with open(path, "w") as f:
        json.dump(data, f, indent=2, default=str)


def _today() -> str:
    return datetime.now().strftime("%Y-%m-%d")


def _now_ts() -> float:
    return time.time()


# --- Default Player Data ---

def _default_player(player_id: str) -> dict:
    return {
        "id": player_id,
        "created": _today(),
        "level": 1,
        "xp": 0,
        "coins": 50,  # Welcome bonus
        "total_coins_earned": 50,
        "games_played": 0,
        "games_won": 0,
        "current_streak_days": 0,
        "best_streak_days": 0,
        "last_login_date": None,
        "current_win_streak": 0,
        "best_win_streak": 0,
        "achievements": [],
        "fortunes_collected": {"common": 0, "uncommon": 0, "rare": 0, "epic": 0, "legendary": 0},
        "badges": [],
        "titles": ["Rookie"],
        "active_title": "Rookie",
        "daily_spins_used": 0,
        "daily_scratches_used": 0,
        "daily_fortune_used": False,
        "daily_reset_date": None,
        "daily_challenges": [],
        "daily_challenges_date": None,
        "cosmetics": [],
        "referrals": [],
        "prestige": 0,
        "slot_theme": "classic",
        "profile_border": "standard",
        "stats": {
            "slots_played": 0,
            "slots_won": 0,
            "biggest_slot_win": 0,
            "trivia_played": 0,
            "trivia_correct": 0,
            "trivia_best_streak": 0,
            "words_played": 0,
            "words_won": 0,
            "riddles_solved": 0,
            "riddles_no_hints": 0,
            "dice_played": 0,
            "dice_won": 0,
            "bosses_defeated": 0,
            "raids_led": 0,
            "tournaments_played": 0,
            "tournaments_won": 0,
            "predictions_made": 0,
            "predictions_correct": 0,
            "fortunes_total": 0,
            "scratches_played": 0,
            "scratches_won": 0,
            "coins_gifted": 0,
            "coins_received": 0,
        },
    }


# --- XP / Level Calculation ---

LEVEL_THRESHOLDS = {
    1: 0, 2: 50, 3: 100, 4: 175, 5: 250,
    6: 350, 7: 500, 8: 650, 9: 850, 10: 1000,
    11: 1200, 12: 1500, 13: 1800, 14: 2200, 15: 2500,
    16: 3000, 17: 3500, 18: 4000, 19: 4500, 20: 5000,
    21: 5500, 22: 6000, 23: 6500, 24: 7000, 25: 8000,
    30: 10000, 40: 15000, 50: 20000,
}

CUMULATIVE_XP = {}
_cumulative = 0
_sorted_levels = sorted(LEVEL_THRESHOLDS.keys())
for i, lvl in enumerate(_sorted_levels):
    _cumulative += LEVEL_THRESHOLDS[lvl]
    CUMULATIVE_XP[lvl] = _cumulative


def _calculate_level(total_xp: int) -> tuple:
    """Returns (level, xp_into_level, xp_needed_for_next)."""
    level = 1
    for lvl in sorted(CUMULATIVE_XP.keys()):
        if total_xp >= CUMULATIVE_XP[lvl]:
            level = lvl
        else:
            break

    if level >= 50:
        return level, 0, 0

    xp_at_current = CUMULATIVE_XP.get(level, 0)
    next_levels = [l for l in sorted(CUMULATIVE_XP.keys()) if l > level]
    if next_levels:
        next_level = next_levels[0]
        xp_at_next = CUMULATIVE_XP[next_level]
        xp_into = total_xp - xp_at_current
        xp_needed = xp_at_next - xp_at_current
        return level, xp_into, xp_needed
    return level, 0, 0


# --- Core Commands ---

def cmd_save(player_id: str, json_data: str):
    """Save or update player data."""
    path = _player_path(player_id)
    existing = _load_json(path, _default_player(player_id))
    updates = json.loads(json_data)
    existing.update(updates)
    # Recalculate level
    lvl, xp_into, xp_needed = _calculate_level(existing.get("xp", 0))
    existing["level"] = lvl
    _save_json(path, existing)
    print(json.dumps({"status": "saved", "player_id": player_id, "level": lvl}))


def cmd_load(player_id: str):
    """Load player data, creating default if new."""
    path = _player_path(player_id)
    data = _load_json(path)
    if not data:
        data = _default_player(player_id)
        _save_json(path, data)
    # Recalculate level
    lvl, xp_into, xp_needed = _calculate_level(data.get("xp", 0))
    data["level"] = lvl
    data["xp_into_level"] = xp_into
    data["xp_needed_for_next"] = xp_needed
    # Check daily reset
    if data.get("daily_reset_date") != _today():
        data["daily_spins_used"] = 0
        data["daily_scratches_used"] = 0
        data["daily_fortune_used"] = False
        data["daily_reset_date"] = _today()
        _save_json(path, data)
    print(json.dumps(data, indent=2))


def cmd_leaderboard(game: str, player_id: str, score: str):
    """Update a player's score on a game leaderboard."""
    score = int(score)
    path = _leaderboard_path(game)
    board = _load_json(path, {"game": game, "entries": [], "updated": _today()})

    # Update or add entry
    found = False
    for entry in board["entries"]:
        if entry["player_id"] == player_id:
            if score > entry["score"]:
                entry["score"] = score
                entry["date"] = _today()
            found = True
            break
    if not found:
        board["entries"].append({
            "player_id": player_id,
            "score": score,
            "date": _today()
        })

    # Sort descending
    board["entries"].sort(key=lambda e: e["score"], reverse=True)
    board["updated"] = _today()
    _save_json(path, board)

    # Find rank
    rank = next(
        (i + 1 for i, e in enumerate(board["entries"]) if e["player_id"] == player_id),
        -1
    )
    print(json.dumps({
        "status": "updated",
        "game": game,
        "player_id": player_id,
        "score": score,
        "rank": rank,
        "total_players": len(board["entries"])
    }))


def cmd_top(game: str, limit: str = "10"):
    """Get top N players for a game."""
    limit = int(limit)
    path = _leaderboard_path(game)
    board = _load_json(path, {"game": game, "entries": []})
    top_entries = board["entries"][:limit]
    print(json.dumps({
        "game": game,
        "top": top_entries,
        "total_players": len(board["entries"])
    }, indent=2))


def cmd_streak(player_id: str):
    """Check and update daily login streak."""
    path = _player_path(player_id)
    data = _load_json(path, _default_player(player_id))

    today = _today()
    yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
    last_login = data.get("last_login_date")

    coins_earned = 0
    streak_status = "maintained"

    if last_login == today:
        # Already logged in today
        streak_status = "already_claimed"
    elif last_login == yesterday:
        # Consecutive day — extend streak
        data["current_streak_days"] += 1
        streak = data["current_streak_days"]
        if streak > data.get("best_streak_days", 0):
            data["best_streak_days"] = streak

        # Calculate streak bonus
        if streak >= 30:
            coins_earned = 200
        elif streak >= 14:
            coins_earned = 100
        elif streak >= 7:
            coins_earned = 50
        elif streak >= 3:
            coins_earned = 25
        else:
            coins_earned = 10

        data["coins"] = data.get("coins", 0) + coins_earned
        data["total_coins_earned"] = data.get("total_coins_earned", 0) + coins_earned
        data["xp"] = data.get("xp", 0) + 5
        streak_status = "extended"
    else:
        # Streak broken (or first login)
        if last_login is not None:
            streak_status = "broken"
        else:
            streak_status = "first_login"
        data["current_streak_days"] = 1
        coins_earned = 10
        data["coins"] = data.get("coins", 0) + coins_earned
        data["total_coins_earned"] = data.get("total_coins_earned", 0) + coins_earned
        data["xp"] = data.get("xp", 0) + 5

    data["last_login_date"] = today
    lvl, _, _ = _calculate_level(data.get("xp", 0))
    data["level"] = lvl
    _save_json(path, data)

    print(json.dumps({
        "status": streak_status,
        "current_streak": data["current_streak_days"],
        "best_streak": data["best_streak_days"],
        "coins_earned": coins_earned,
        "total_coins": data["coins"],
        "level": lvl
    }))


def cmd_achievements(player_id: str):
    """Get all achievements for a player."""
    path = _player_path(player_id)
    data = _load_json(path, _default_player(player_id))
    print(json.dumps({
        "player_id": player_id,
        "achievements": data.get("achievements", []),
        "total_unlocked": len(data.get("achievements", [])),
        "badges": data.get("badges", []),
        "titles": data.get("titles", [])
    }, indent=2))


def cmd_award(player_id: str, achievement_id: str):
    """Award an achievement to a player."""
    path = _player_path(player_id)
    data = _load_json(path, _default_player(player_id))

    # Check if already awarded
    if achievement_id in data.get("achievements", []):
        print(json.dumps({"status": "already_awarded", "achievement": achievement_id}))
        return

    # Achievement rewards table
    rewards = {
        "G01": {"coins": 25, "badge": None, "title": None},
        "G02": {"coins": 50, "badge": "ten_wins", "title": None},
        "G03": {"coins": 200, "badge": None, "title": "Centurion"},
        "G04": {"coins": 1000, "badge": None, "title": None},
        "G05": {"coins": 300, "badge": "jack_of_all_trades", "title": None},
        "G06": {"coins": 150, "badge": None, "title": None},
        "G07": {"coins": 75, "badge": None, "title": None},
        "G08": {"coins": 200, "badge": None, "title": None},
        "G09": {"coins": 250, "badge": None, "title": None},
        "G10": {"coins": 500, "badge": None, "title": "Lucky Seven"},
        "S01": {"coins": 10, "badge": None, "title": None},
        "S02": {"coins": 50, "badge": None, "title": None},
        "S03": {"coins": 200, "badge": None, "title": None},
        "S04": {"coins": 300, "badge": None, "title": None},
        "S05": {"coins": 1000, "badge": None, "title": "Jackpot King"},
        "X01": {"coins": 100, "badge": None, "title": None},
        "X02": {"coins": 250, "badge": None, "title": None},
        "X03": {"coins": 100, "badge": "philanthropist", "title": None},
        "X04": {"coins": 75, "badge": None, "title": None},
        "X05": {"coins": 150, "badge": None, "title": None},
        "X06": {"coins": 500, "badge": None, "title": None},
        "X07": {"coins": 200, "badge": None, "title": None},
        "K01": {"coins": 25, "badge": None, "title": None},
        "K02": {"coins": 100, "badge": "dedicated", "title": None},
        "K03": {"coins": 250, "badge": None, "title": None},
        "K04": {"coins": 500, "badge": None, "title": "Obsessed"},
        "K05": {"coins": 2000, "badge": None, "title": None},
        "K06": {"coins": 75, "badge": None, "title": None},
        "K07": {"coins": 200, "badge": None, "title": None},
        "K08": {"coins": 500, "badge": None, "title": "Supernova"},
        "C01": {"coins": 50, "badge": None, "title": None},
        "C02": {"coins": 150, "badge": "rainbow", "title": None},
        "C03": {"coins": 500, "badge": None, "title": "Oracle"},
        "C04": {"coins": 100, "badge": None, "title": None},
        "C05": {"coins": 500, "badge": None, "title": None},
        "C06": {"coins": 200, "badge": None, "title": None},
        "C07": {"coins": 150, "badge": None, "title": None},
        "B01": {"coins": 100, "badge": None, "title": None},
        "B02": {"coins": 200, "badge": None, "title": None},
        "B03": {"coins": 400, "badge": None, "title": "Boss Killer"},
        "B04": {"coins": 300, "badge": None, "title": None},
        "B05": {"coins": 200, "badge": None, "title": None},
        "H01": {"coins": 50, "badge": "night_owl", "title": None},
        "H02": {"coins": 50, "badge": "early_bird", "title": None},
        "H03": {"coins": 100, "badge": None, "title": None},
        "H04": {"coins": 150, "badge": None, "title": None},
        "H05": {"coins": 200, "badge": None, "title": None},
        "H06": {"coins": 100, "badge": None, "title": None},
        "H07": {"coins": 250, "badge": None, "title": None},
    }

    reward = rewards.get(achievement_id, {"coins": 25, "badge": None, "title": None})

    data.setdefault("achievements", []).append(achievement_id)
    data["coins"] = data.get("coins", 0) + reward["coins"]
    data["total_coins_earned"] = data.get("total_coins_earned", 0) + reward["coins"]
    data["xp"] = data.get("xp", 0) + 50  # All achievements give 50 XP

    if reward["badge"]:
        data.setdefault("badges", []).append(reward["badge"])
    if reward["title"]:
        data.setdefault("titles", []).append(reward["title"])

    lvl, _, _ = _calculate_level(data.get("xp", 0))
    data["level"] = lvl
    _save_json(path, data)

    print(json.dumps({
        "status": "awarded",
        "achievement": achievement_id,
        "reward": reward,
        "new_level": lvl,
        "total_achievements": len(data["achievements"])
    }))


def cmd_stats():
    """Get global arcade statistics."""
    global_data = _load_json(GLOBAL_FILE, {
        "total_players": 0,
        "total_games_played": 0,
        "total_coins_in_circulation": 0,
        "created": _today()
    })

    # Count actual players
    player_count = len(list(PLAYERS_DIR.glob("*.json")))
    global_data["total_players"] = player_count

    # Count leaderboard games
    leaderboard_count = len(list(LEADERBOARDS_DIR.glob("*.json")))
    global_data["active_leaderboards"] = leaderboard_count

    print(json.dumps(global_data, indent=2))


def cmd_daily(player_id: str):
    """Generate or check daily challenges."""
    path = _player_path(player_id)
    data = _load_json(path, _default_player(player_id))

    today = _today()

    if data.get("daily_challenges_date") == today:
        # Return existing challenges
        print(json.dumps({
            "status": "existing",
            "date": today,
            "challenges": data["daily_challenges"]
        }, indent=2))
        return

    # Generate new challenges
    seed = int(hashlib.sha256(f"{player_id}{today}".encode()).hexdigest()[:8], 16)
    rng = random.Random(seed)

    easy_templates = [
        {"desc": "Play 3 rounds of any game", "target": 3, "type": "play_any", "reward": 20},
        {"desc": "Win 1 game of any type", "target": 1, "type": "win_any", "reward": 15},
        {"desc": "Spin the slots 3 times", "target": 3, "type": "play_slots", "reward": 20},
        {"desc": "Answer 3 trivia questions", "target": 3, "type": "play_trivia", "reward": 20},
    ]

    medium_templates = [
        {"desc": "Win 3 games of any type", "target": 3, "type": "win_any", "reward": 40},
        {"desc": "Play 5 rounds of any game", "target": 5, "type": "play_any", "reward": 30},
        {"desc": "Earn 50 coins in one session", "target": 50, "type": "earn_coins", "reward": 35},
        {"desc": "Get a 3-game win streak", "target": 3, "type": "win_streak", "reward": 40},
    ]

    hard_templates = [
        {"desc": "Get a Rare or better fortune", "target": 1, "type": "rare_fortune", "reward": 50},
        {"desc": "Win 5 trivia questions in a row", "target": 5, "type": "trivia_streak", "reward": 60},
        {"desc": "Score 100+ points in a single game", "target": 100, "type": "high_score", "reward": 50},
        {"desc": "Solve a riddle without any hints", "target": 1, "type": "riddle_no_hints", "reward": 45},
    ]

    challenges = [
        {**rng.choice(easy_templates), "progress": 0, "completed": False, "difficulty": "easy"},
        {**rng.choice(medium_templates), "progress": 0, "completed": False, "difficulty": "medium"},
        {**rng.choice(hard_templates), "progress": 0, "completed": False, "difficulty": "hard"},
    ]

    data["daily_challenges"] = challenges
    data["daily_challenges_date"] = today
    _save_json(path, data)

    print(json.dumps({
        "status": "generated",
        "date": today,
        "challenges": challenges,
        "bonus_for_all_3": "50 coins + mystery badge"
    }, indent=2))


def cmd_gift(from_id: str, to_id: str, amount: str):
    """Transfer coins between players."""
    amount = int(amount)
    if amount <= 0:
        print(json.dumps({"status": "error", "message": "Amount must be positive"}))
        return

    from_path = _player_path(from_id)
    to_path = _player_path(to_id)

    from_data = _load_json(from_path, _default_player(from_id))
    to_data = _load_json(to_path, _default_player(to_id))

    if from_data.get("coins", 0) < amount:
        print(json.dumps({
            "status": "error",
            "message": "Insufficient coins",
            "balance": from_data.get("coins", 0)
        }))
        return

    from_data["coins"] -= amount
    to_data["coins"] = to_data.get("coins", 0) + amount
    to_data["total_coins_earned"] = to_data.get("total_coins_earned", 0) + amount

    from_data.setdefault("stats", {})["coins_gifted"] = \
        from_data.get("stats", {}).get("coins_gifted", 0) + amount
    to_data.setdefault("stats", {})["coins_received"] = \
        to_data.get("stats", {}).get("coins_received", 0) + amount

    _save_json(from_path, from_data)
    _save_json(to_path, to_data)

    print(json.dumps({
        "status": "success",
        "from": from_id,
        "to": to_id,
        "amount": amount,
        "from_balance": from_data["coins"],
        "to_balance": to_data["coins"]
    }))


def cmd_profile(player_id: str):
    """Get formatted player profile data."""
    path = _player_path(player_id)
    data = _load_json(path, _default_player(player_id))

    lvl, xp_into, xp_needed = _calculate_level(data.get("xp", 0))
    win_rate = 0
    if data.get("games_played", 0) > 0:
        win_rate = round((data.get("games_won", 0) / data["games_played"]) * 100)

    profile = {
        "player_id": player_id,
        "level": lvl,
        "prestige": data.get("prestige", 0),
        "xp_progress": f"{xp_into}/{xp_needed}",
        "active_title": data.get("active_title", "Rookie"),
        "coins": data.get("coins", 0),
        "games_played": data.get("games_played", 0),
        "games_won": data.get("games_won", 0),
        "win_rate": f"{win_rate}%",
        "current_streak": data.get("current_streak_days", 0),
        "best_streak": data.get("best_streak_days", 0),
        "achievements_unlocked": len(data.get("achievements", [])),
        "badges": data.get("badges", []),
        "titles": data.get("titles", []),
        "member_since": data.get("created", "unknown"),
        "stats": data.get("stats", {}),
        "fortunes_collected": data.get("fortunes_collected", {}),
    }

    print(json.dumps(profile, indent=2))


# --- Main Entry Point ---

def main():
    if len(sys.argv) < 2:
        print(json.dumps({"error": "No command specified. Use: save|load|leaderboard|top|streak|achievements|award|stats|daily|gift|profile"}))
        sys.exit(1)

    command = sys.argv[1]
    args = sys.argv[2:]

    commands = {
        "save": (cmd_save, 2, "save <player_id> <json_data>"),
        "load": (cmd_load, 1, "load <player_id>"),
        "leaderboard": (cmd_leaderboard, 3, "leaderboard <game> <player_id> <score>"),
        "top": (cmd_top, 1, "top <game> [limit]"),
        "streak": (cmd_streak, 1, "streak <player_id>"),
        "achievements": (cmd_achievements, 1, "achievements <player_id>"),
        "award": (cmd_award, 2, "award <player_id> <achievement_id>"),
        "stats": (cmd_stats, 0, "stats"),
        "daily": (cmd_daily, 1, "daily <player_id>"),
        "gift": (cmd_gift, 3, "gift <from_id> <to_id> <amount>"),
        "profile": (cmd_profile, 1, "profile <player_id>"),
    }

    if command not in commands:
        print(json.dumps({"error": f"Unknown command: {command}", "available": list(commands.keys())}))
        sys.exit(1)

    func, min_args, usage = commands[command]
    if len(args) < min_args:
        print(json.dumps({"error": f"Usage: arcade_engine.py {usage}"}))
        sys.exit(1)

    func(*args[:min_args + 2])  # Allow optional args


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)