added more documentation
This commit is contained in:
@@ -61,7 +61,6 @@ ShaiBot/
|
||||
│ └── poker/
|
||||
├── utils/
|
||||
├── index.js
|
||||
├── COOKIE_LOGIC.md
|
||||
├── README.md
|
||||
├── package.json
|
||||
└── .env # never commit
|
||||
@@ -504,7 +503,7 @@ Preserve this metadata because achievements/social relationship tracking depend
|
||||
|
||||
Normal player-to-player stealing is separate from Vault Heist.
|
||||
|
||||
The current steal model is documented in `COOKIE_LOGIC.md`.
|
||||
The current steal model is documented in `docs/ECONOMY.md`.
|
||||
|
||||
Key current balance values:
|
||||
|
||||
@@ -2046,7 +2045,7 @@ Before modifying code:
|
||||
|
||||
1. Read this file.
|
||||
2. Read `README.md`.
|
||||
3. If touching Cookies/steal logic, read `COOKIE_LOGIC.md`.
|
||||
3. If touching Cookie balances, transfers, stealing, cooldowns, settlement, or economy idempotency, read docs/ECONOMY.md.
|
||||
4. Read every utility directly involved.
|
||||
5. Read its command/button consumers.
|
||||
6. Search for imports/exports of functions being changed.
|
||||
@@ -2097,19 +2096,24 @@ Use these docs together:
|
||||
|
||||
```text
|
||||
README.md
|
||||
Broad feature/product overview and contribution conventions.
|
||||
|
||||
COOKIE_LOGIC.md
|
||||
Detailed /cookies steal/robbery rules and collection contracts.
|
||||
Human-facing project overview, features, setup, and documentation index.
|
||||
|
||||
AGENTS.md
|
||||
Cross-repository AI-agent architectural/safety guide.
|
||||
Repository-wide architecture, invariants, and safety rules for AI agents.
|
||||
|
||||
Poker-specific agent guide (if present)
|
||||
Deep Poker state/economy/rules/recovery contract.
|
||||
docs/ARCHITECTURE.md
|
||||
Runtime, handlers, persistence, concurrency, and recovery.
|
||||
|
||||
Phase/rollout notes (if retained)
|
||||
Historical implementation context; current code still wins.
|
||||
docs/ECONOMY.md
|
||||
Complete Cookie economy manual, including PvP stealing mechanics,
|
||||
formulas, heat, exposure budgets, transfers, settlement, and idempotency.
|
||||
|
||||
docs/GAMES.md
|
||||
Crumb Saucer, Poker, Crumble Strike, and game mechanics.
|
||||
|
||||
docs/PROGRESSION.md
|
||||
Profiles, achievements, badges, activity, social progression,
|
||||
reconciliation, and maintenance.
|
||||
```
|
||||
|
||||
If an older phase note disagrees with current implementation, do not regress current code to match the note.
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
# Cookie Economy Command
|
||||
|
||||
`cookies.js` implements the `/cookies` command and its five subcommands: `collect`, `steal`, `check`, `give`, and `leaderboard`.
|
||||
|
||||
## Commands
|
||||
|
||||
- `/cookies collect` delegates collection logic to `collectCookies()`, then displays the amount collected, updated vault, and next collection time.
|
||||
- `/cookies check [target]` shows a user's current Cookie balance. Without a target it checks the invoking user.
|
||||
- `/cookies give <target> <amount>` transfers Cookies to another non-bot user and records sender/recipient profile statistics.
|
||||
- `/cookies leaderboard` reads `items_cookies`, sorts by balance, excludes the bot, and displays the ten richest users.
|
||||
- `/cookies steal <target>` runs the PvP robbery system described below.
|
||||
|
||||
## Steal balance
|
||||
|
||||
| Setting | Value |
|
||||
|---|---:|
|
||||
| Cooldown | 15 minutes |
|
||||
| Base/equal-wealth success chance | 55% |
|
||||
| Success range | 30%–80% |
|
||||
| Wealth scaling | 12.5 percentage points per 10x balance difference |
|
||||
| Heat per recent attempt | 7.5 percentage points |
|
||||
| Heat lifetime | 1 hour, linear decay |
|
||||
| Victim hourly loss budget | 15% of balance when the window starts |
|
||||
| Per-robbery hard cap | 25,000 Cookies |
|
||||
| Base loot tiers | 1–3%, 3–5%, 5–8%, 8–10% |
|
||||
| Loot multiplier | 0.75x–1.25x based on final robbery difficulty |
|
||||
| Base failure penalty | 2%–10% of thief balance |
|
||||
| Failure multiplier | 0.75x–1.50x based on final success chance |
|
||||
|
||||
### Wealth chance curve
|
||||
|
||||
Before heat is applied, relative wealth determines the success chance. Absolute economy size does not matter.
|
||||
|
||||
| Attacker compared with target | Base chance |
|
||||
|---|---:|
|
||||
| 100x poorer | 80% |
|
||||
| 10x poorer | 67.5% |
|
||||
| Equal | 55% |
|
||||
| 10x richer | 42.5% |
|
||||
| 100x richer | 30% |
|
||||
|
||||
### Heat protection (`stats_profile`)
|
||||
|
||||
Each valid robbery attempt adds an entry without modifying existing achievement/profile fields:
|
||||
|
||||
```js
|
||||
stealProtection: {
|
||||
attempts: [
|
||||
{
|
||||
userId: "attacker-id",
|
||||
timestamp: Date
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
All attackers contribute to the same victim heat. Each attempt starts at a 7.5-point success penalty and fades linearly to zero over one hour. Expired entries are removed whenever the victim is targeted again. The current attempt is appended atomically while MongoDB returns the immediately previous profile state, so simultaneous attacks see newly-created heat while an attempt never penalizes itself.
|
||||
|
||||
### Hourly victim-loss budget (`items_cookies`)
|
||||
|
||||
Each Cookie record may contain:
|
||||
|
||||
```js
|
||||
stealable: {
|
||||
amount: 15000,
|
||||
windowStartedAt: Date
|
||||
}
|
||||
```
|
||||
|
||||
When no active window exists, the first valid robbery attempt after the attacker's cooldown check initializes the allowance to 15% of the victim's current balance. That first attempt is treated as breaching the Vault and adds a short `🔓 Vault Breached!` flavor message to the robbery embed. Attempts rejected by the attacker's cooldown do not open a new victim window.
|
||||
|
||||
The exposed amount is shown in steal result embeds as **Vault Exposed**. The window lasts a fixed hour; successful robberies decrement `amount` without moving `windowStartedAt`. Failed robberies leave the exposed budget unchanged. When the hour expires, the next valid attempt recalculates the allowance from the victim's then-current balance and opens a new exposure window.
|
||||
|
||||
A successful robbery reserves its amount from this budget with an atomic MongoDB update before calling `transferCookies()`. This prevents concurrent robberies from spending the same allowance. If the Cookie transfer fails, the reservation is refunded.
|
||||
|
||||
When the allowance reaches zero, the Vault is no longer exposed. Further steal attempts are rejected without consuming the attacker's steal cooldown until the fixed window expires and can be breached again.
|
||||
|
||||
### Loot and penalties
|
||||
|
||||
The original weighted loot tiers remain:
|
||||
|
||||
- 50% of successful steals roll 1–3%.
|
||||
- 30% roll 3–5%.
|
||||
- 15% roll 5–8%.
|
||||
- 5% roll 8–10%.
|
||||
|
||||
Those ranges are multiplied by a difficulty factor: easy/high-chance robberies pay less, while difficult/low-chance robberies can pay more. The final amount is also capped by the victim balance, the remaining hourly stealable budget, and the 25,000-Cookie per-hit cap.
|
||||
|
||||
Failure penalties work in the opposite direction. Easy/high-chance robberies carry a larger penalty when they fail; difficult robberies carry a smaller one. The resulting range moves from roughly 1.5–7.5% at a 30% success chance to 3–15% at an 80% success chance.
|
||||
|
||||
## Collections and utilities
|
||||
|
||||
The file expects `getCollections()` to expose:
|
||||
|
||||
- `items_cookies` as `cookies`, `itemsCookies`, or `items_cookies`.
|
||||
- `stats_profile` as `statsProfile`, `statsProfiles`, or `stats_profile`.
|
||||
- Alternatively, `getCollections()` may expose a `db`/`database` handle from which those raw MongoDB collection names can be opened.
|
||||
|
||||
Existing shared utilities remain responsible for Cookie balances, transfers, cooldown claims, random helpers, profile event tracking, and collection logic.
|
||||
@@ -1,611 +1,280 @@
|
||||
# ShaiBot
|
||||
|
||||
A modular **Discord.js** bot built around a shared Cookie economy,
|
||||
interactive Crumb Saucer games, player profiles, achievements, global
|
||||
badges, cooperative boss battles, raid planning, and community
|
||||
interactions.
|
||||
ShaiBot is a modular Discord community bot built around a persistent
|
||||
**Cookie economy**, interactive games, player progression, and
|
||||
multiplayer activities.
|
||||
|
||||
> **Status:** Active development. Features, achievements, and game
|
||||
> balance may change.
|
||||
The bot's main entertainment hub is the **Crumb Saucer**, where players
|
||||
can collect and wager Cookies, play casino-style games, attempt Vault
|
||||
Heists, recover through Bankruptcy, and sit down at a multiplayer Texas
|
||||
Hold'em table.
|
||||
|
||||
## Features
|
||||
ShaiBot also includes persistent player profiles, achievements,
|
||||
guild-unique badges, cooperative encounters, raid planning, and lighter
|
||||
community features.
|
||||
|
||||
### 🍪 Cookie Economy
|
||||
> **Status:** Active development and stabilization. The major economy,
|
||||
> profile, achievement, and Poker overhaul is live; current work is
|
||||
> focused primarily on testing, balancing, and polish.
|
||||
|
||||
Cookies are ShaiBot's shared virtual currency. The economy supports
|
||||
persistent balances, atomic balance checks, transfers, Mongo-backed
|
||||
cooldowns, and a shared bot/house vault.
|
||||
## Highlights
|
||||
|
||||
The bot itself acts as the general Cookie vault: gambling losses and
|
||||
penalties can feed the vault, while wins, heists, collection rewards,
|
||||
and other systems can pay Cookies back out.
|
||||
- 🍪 Persistent Cookie economy
|
||||
- 🎰 Crumb Saucer game hub
|
||||
- 🎰 Slots, Blackjack, Roulette, Vault Heist, and Bankruptcy
|
||||
- ♠️ Persistent 2--6 player Texas Hold'em
|
||||
- 🏴 Player-to-player Cookie stealing
|
||||
- 👤 Lifetime player profiles and statistics
|
||||
- 🏆 Personal achievements
|
||||
- 🎖️ Guild-unique global badges
|
||||
- 🔁 All-In and Run It Back progression
|
||||
- ⚔️ Cooperative Crumble Strike encounters
|
||||
- 📅 Raid planning and community utilities
|
||||
- 💾 Mongo-backed persistence and recovery
|
||||
|
||||
Cookie collection is shared between `/cookies collect` and the **Crumb
|
||||
Saucer Cookie Bakery**, using the same cooldown and reward logic.
|
||||
## The Crumb Saucer
|
||||
|
||||
### 👤 Player Profiles
|
||||
The **Crumb Saucer** is the main home for ShaiBot's Cookie-powered
|
||||
games.
|
||||
|
||||
ShaiBot includes persistent player profiles that bring together Cookie
|
||||
and game activity.
|
||||
### 🍪 Cookie Bakery
|
||||
|
||||
Profiles can expose:
|
||||
Collect Cookies using the same shared collection system as
|
||||
`/cookies collect`.
|
||||
|
||||
- Cookie economy statistics
|
||||
### 🎰 Slots
|
||||
|
||||
Spin for symbol combinations, jackpots, All-In wagers, and Run It Back
|
||||
streaks.
|
||||
|
||||
### 🃏 Blackjack
|
||||
|
||||
Includes Hit, Stand, Double, natural Blackjack, pushes, All-In, and Run
|
||||
It Back.
|
||||
|
||||
### 🎡 Roulette
|
||||
|
||||
A compact European Roulette game using numbers `0–36`, with Red, Black,
|
||||
Odd, Even, and Zero bets.
|
||||
|
||||
### 🏦 Vault Heist
|
||||
|
||||
Attempt to steal from ShaiBot's house vault using different risk/reward
|
||||
approaches.
|
||||
|
||||
### 🆘 Bankruptcy
|
||||
|
||||
A recovery mechanic for players who need a fresh start, with profile
|
||||
progression for rebuilding afterward.
|
||||
|
||||
### ♠️ Shai Poker
|
||||
|
||||
A persistent multiplayer Texas Hold'em game for **2--6 players**.
|
||||
|
||||
Current defaults:
|
||||
|
||||
``` text
|
||||
Buy-in: 1,000 Cookies
|
||||
Blinds: 10 / 20
|
||||
Turn timer: 90 seconds
|
||||
Pot model: single pot
|
||||
```
|
||||
|
||||
Poker supports private hole cards, public community cards,
|
||||
Fold/Check/Call/Bet/Raise/All-In, automatic timeout folding, restart
|
||||
recovery, host cancellation, safe buy-in/cash-out settlement, Poker
|
||||
statistics, achievements, and guild-first badges.
|
||||
|
||||
Side pots, tournaments, bots, rake, and player-facing equity assistance
|
||||
are intentionally outside the current V1 design.
|
||||
|
||||
## Player Profiles
|
||||
|
||||
Profiles provide the permanent history behind ShaiBot's progression
|
||||
systems.
|
||||
|
||||
They track things such as:
|
||||
|
||||
- Game wins and losses
|
||||
- Per-game statistics
|
||||
- Lifetime gains and losses
|
||||
- Stealing and giving activity
|
||||
- Cookie gains and losses
|
||||
- Giving and stealing
|
||||
- Daily activity and streaks
|
||||
- Social progression
|
||||
- Run It Back streaks
|
||||
- Poker history and hand accomplishments
|
||||
- Achievements
|
||||
- Global badges
|
||||
- Collection progress
|
||||
|
||||
Profile menus are public so other members can view them, while
|
||||
interactive controls are intended to remain restricted to the session
|
||||
owner. Errors, cooldown/debug-style feedback, and unauthorized
|
||||
interaction messages may be ephemeral.
|
||||
Completed multiplayer game documents do not need to become permanent
|
||||
history when the meaningful result already belongs in the profile
|
||||
system.
|
||||
|
||||
### 🏆 Achievements
|
||||
## Achievements & Global Badges
|
||||
|
||||
Achievements are repeatable across the community: every eligible player
|
||||
can earn their own copy.
|
||||
**Achievements** are personal progression. Any eligible player can earn
|
||||
them.
|
||||
|
||||
Achievement tracking can use persistent profile statistics as well as
|
||||
explicit game events. Current and planned categories include:
|
||||
**Global badges** are guild-unique distinctions, usually awarded to the
|
||||
first player in a guild to accomplish something notable.
|
||||
|
||||
- Cookie collection and economy milestones
|
||||
- Giving and stealing milestones
|
||||
- Game wins and losses
|
||||
- Game-specific loss milestones
|
||||
- All-In accomplishments
|
||||
- Run It Back streaks
|
||||
- Cross-game special challenges
|
||||
- Collector achievements for earning a portion or all available
|
||||
achievements
|
||||
Progression spans the Cookie economy, stealing, Crumb Saucer games,
|
||||
activity, social interactions, Poker, and special cross-game challenges.
|
||||
|
||||
Game-specific achievements use names such as:
|
||||
## Cookie Stealing
|
||||
|
||||
``` text
|
||||
The House Always Wins: Blackjack
|
||||
```
|
||||
Player-to-player stealing is separate from Vault Heist.
|
||||
|
||||
where sharing a generalized achievement concept between games makes
|
||||
sense.
|
||||
The current system accounts for wealth differences, recent pressure on
|
||||
the victim, percentage-based loot, hard caps, and an hourly exposure
|
||||
budget.
|
||||
|
||||
### 🎖️ Global Badges
|
||||
Detailed balancing and mechanics are documented in
|
||||
[`COOKIE_LOGIC.md`](COOKIE_LOGIC.md).
|
||||
|
||||
Global badges are guild-wide collectibles that can have a single owner.
|
||||
They are intended for special "first player to..." accomplishments and
|
||||
other unique distinctions.
|
||||
## ⚔️ Crumble Strike
|
||||
|
||||
Examples include:
|
||||
Crumble Strike is ShaiBot's cooperative boss-battle system.
|
||||
|
||||
- First-time game accomplishments
|
||||
- Slots triplet combinations
|
||||
- All-In / Run It Back feats
|
||||
- Special or hidden manually awarded badges
|
||||
- Achievement collection milestones
|
||||
Players recruit a party, choose combat roles, commit Cookies, and work
|
||||
together using actions such as Strike, Defend, Heal, Revive, and Limit
|
||||
Break.
|
||||
|
||||
Badges may be hidden until discovered. Some special badges are
|
||||
intentionally managed manually in MongoDB rather than automatically
|
||||
awarded by gameplay.
|
||||
Encounters use persistent state because they can span many players and
|
||||
interactions.
|
||||
|
||||
### 🎰 The Crumb Saucer
|
||||
## 📅 Raid Planner & Community Features
|
||||
|
||||
The **Crumb Saucer** is ShaiBot's Cookie-powered entertainment hub.
|
||||
ShaiBot also includes raid-planning tools and smaller social/community
|
||||
commands alongside its economy and progression systems.
|
||||
|
||||
#### Cookie Bakery
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Players can collect a fresh batch of Cookies from the Saucer.
|
||||
|
||||
The Bakery and `/cookies collect` use the same shared collection
|
||||
utility, meaning they share:
|
||||
|
||||
- The same Mongo-backed cooldown
|
||||
- The same reward range
|
||||
- The same balance mutation
|
||||
- The same profile/stat tracking
|
||||
|
||||
The current default collection range is **1--1000 Cookies**.
|
||||
|
||||
#### Slots
|
||||
|
||||
- Multiple Cookie wagers
|
||||
- Embed-based reel presentation
|
||||
- Different symbol payouts
|
||||
- Triplet combinations
|
||||
- Jackpot support
|
||||
- Run It Back support
|
||||
- Shared Cookie vault
|
||||
- Game-specific achievements and first-time global badges
|
||||
|
||||
Slots triplets can participate in unique global badge progression,
|
||||
including Lemon, Cherry, Cookie, Star, and Diamond combinations.
|
||||
|
||||
#### Blackjack
|
||||
|
||||
- Hit, Stand, and Double
|
||||
- Dealer stands on 17
|
||||
- Natural Blackjack pays 3:2
|
||||
- Push returns the wager
|
||||
- All-In support
|
||||
- Run It Back support
|
||||
- Persistent active hands
|
||||
- Per-player session ownership
|
||||
- Safe simultaneous sessions
|
||||
- Profile, achievement, and badge integration
|
||||
|
||||
All-In state should be derived from the committed wager and the player's
|
||||
vault at the time the wager is made rather than solely from which button
|
||||
was pressed.
|
||||
|
||||
Run It Back preserves immutable metadata from the previous hand. This
|
||||
allows historical challenges to remain valid even if another player
|
||||
changes the user's Cookie balance between rounds.
|
||||
|
||||
For example, an All-In that pushes can be followed by Run It Back and
|
||||
still qualify for an All-In → Run It Back challenge even if Cookies were
|
||||
gifted to the player in between.
|
||||
|
||||
Blackjack resolution is designed to guard against rapid repeated
|
||||
interactions so a hand cannot be resolved and paid multiple times.
|
||||
|
||||
#### Roulette
|
||||
|
||||
A compact European Roulette implementation using **0--36**.
|
||||
|
||||
Available bets include:
|
||||
|
||||
- 🔴 Red
|
||||
- ⚫ Black
|
||||
- Odd
|
||||
- Even
|
||||
- 🟢 Zero
|
||||
|
||||
Roulette uses repeated edits of the same embed for a
|
||||
rate-limit-conscious pseudo-animation. Zero loses on Red, Black, Odd,
|
||||
and Even.
|
||||
|
||||
Roulette supports All-In and Run It Back tracking for profile
|
||||
achievements and special accomplishments.
|
||||
|
||||
#### Vault Heist
|
||||
|
||||
Players can attempt to steal directly from ShaiBot's Cookie vault using
|
||||
different risk/reward approaches such as **Sneak**, **Hack**, and
|
||||
**Smash**.
|
||||
|
||||
Heist actions share a per-player cooldown so changing approach does not
|
||||
bypass it.
|
||||
|
||||
Heist rewards and fines use percentage-based mechanics with hard caps so
|
||||
the system remains meaningful for wealthy players without allowing
|
||||
extreme balances to produce unreasonable penalties.
|
||||
|
||||
### 🔁 Run It Back
|
||||
|
||||
Supported Crumb Saucer games can track consecutive use of **Run It
|
||||
Back**.
|
||||
|
||||
The streak represents the player's choice to immediately replay through
|
||||
the Run It Back action; wins, losses, pushes, jackpots, or other
|
||||
outcomes do not inherently break the streak.
|
||||
|
||||
Current achievement concepts include using Run It Back five consecutive
|
||||
times in supported games:
|
||||
|
||||
``` text
|
||||
One More Spin: Slots
|
||||
One More Bet: Roulette
|
||||
One More Hand: Blackjack
|
||||
```
|
||||
|
||||
A normal/new wager breaks that game's Run It Back chain.
|
||||
|
||||
### ♾️ I Can Do This All Day
|
||||
|
||||
A special cross-game accomplishment tracks the sequence:
|
||||
|
||||
``` text
|
||||
All-In
|
||||
→ round resolves
|
||||
→ Run It Back with the same committed wager
|
||||
```
|
||||
|
||||
The original All-In is determined from immutable wager-time data. The
|
||||
Run It Back relationship is determined from the previous game's stored
|
||||
bet and All-In state rather than relying on the player's live vault
|
||||
remaining unchanged.
|
||||
|
||||
This prevents another player gifting Cookies between rounds from
|
||||
invalidating a legitimate sequence.
|
||||
|
||||
The accomplishment can exist both as a normal achievement available to
|
||||
everyone and as a global first-time badge for the first player to
|
||||
perform it.
|
||||
|
||||
### 🏴 Cookie Stealing
|
||||
|
||||
Normal player-to-player stealing is separate from Vault Heist.
|
||||
|
||||
Steal difficulty can account for attacker and target wealth. Successful
|
||||
steals use randomized percentages with hard caps, while failed attempts
|
||||
can apply a percentage-based penalty.
|
||||
|
||||
Profile tracking records relevant Cookie gains/losses and stealing
|
||||
activity.
|
||||
|
||||
### ⚔️ Crumble Strike
|
||||
|
||||
**Crumble Strike** is a cooperative Cookie-powered boss battle.
|
||||
|
||||
- A player spawns an encounter.
|
||||
- Other players join during recruitment.
|
||||
- The author can start after at least **5 players** have joined.
|
||||
- Players can join an active encounter later.
|
||||
- Encounters have a limited lifetime.
|
||||
- Failure can result in committed Cookies being lost.
|
||||
|
||||
Combat actions include:
|
||||
|
||||
- **Strike** --- basic damage and Energy generation.
|
||||
- **Defend** --- reduces incoming damage at an Energy cost.
|
||||
- **Heal** --- restores party health at an Energy cost.
|
||||
- **Revive** --- party-wide revival progress. Normal roles add +1 to
|
||||
every downed player; Healers add +2. Three progress revives a
|
||||
player.
|
||||
- **Limit Break** --- consumes the party's global Limit resource for
|
||||
major damage.
|
||||
|
||||
Roles are **DPS**, **Tank**, and **Healer**, with role-specific
|
||||
proficiencies. The general progression theme includes **Sprout →
|
||||
Adventurer → Warrior of Light**.
|
||||
|
||||
### 📅 Raid Planner
|
||||
|
||||
Raid planning uses Discord embeds and reactions. Participation can be
|
||||
counted across reactions without automatically removing user reactions,
|
||||
including a count of unique participants.
|
||||
|
||||
### 👈 Poke
|
||||
|
||||
A lightweight social command can privately poke another guild member
|
||||
through DMs. Repeated pokes are bounded to a rate-limit-friendly
|
||||
maximum.
|
||||
|
||||
## Project Structure
|
||||
|
||||
A typical layout:
|
||||
|
||||
``` text
|
||||
ShaiBot/
|
||||
├── buttons/
|
||||
│ ├── crumbSaucer/
|
||||
│ ├── crumbleStrike/
|
||||
│ └── profile/
|
||||
├── commands/
|
||||
│ └── applications/
|
||||
├── events/
|
||||
├── handlers/
|
||||
├── modals/
|
||||
├── utils/
|
||||
│ ├── cookieEconomy.js
|
||||
│ ├── crumbCollect.js
|
||||
│ ├── crumbSlots.js
|
||||
│ ├── crumbBlackjack.js
|
||||
│ ├── crumbRoulette.js
|
||||
│ ├── cookieHeist.js
|
||||
│ ├── profileSystem.js
|
||||
│ └── crumbleStrike.js
|
||||
├── index.js
|
||||
├── package.json
|
||||
└── .env
|
||||
```
|
||||
|
||||
Interaction modules are loaded into Discord.js collections such as:
|
||||
|
||||
``` js
|
||||
client.commands = new Collection();
|
||||
client.legacyCommands = new Collection();
|
||||
client.aliases = new Collection();
|
||||
client.buttons = new Collection();
|
||||
client.selectMenus = new Collection();
|
||||
client.modals = new Collection();
|
||||
```
|
||||
|
||||
## Shared Utility Architecture
|
||||
|
||||
Game/application files should remain thin wherever practical.
|
||||
|
||||
Shared behavior belongs in `utils/`, particularly:
|
||||
|
||||
- `cookieEconomy.js` --- balances, transfers, cooldowns, and economy
|
||||
primitives
|
||||
- `crumbCollect.js` --- authoritative Cookie collection behavior
|
||||
- `crumbSlots.js` --- Slots state and resolution
|
||||
- `crumbBlackjack.js` --- Blackjack state and resolution
|
||||
- `crumbRoulette.js` --- Roulette state and resolution
|
||||
- `cookieHeist.js` --- Vault Heist behavior
|
||||
- `profileSystem.js` --- profile statistics, achievements, badges,
|
||||
rendering, and audit helpers
|
||||
|
||||
Application commands and button handlers should call these utilities
|
||||
rather than independently reimplementing economy or progression logic.
|
||||
|
||||
This is especially important for features reachable from multiple
|
||||
interfaces. For example:
|
||||
|
||||
``` text
|
||||
/cookies collect
|
||||
│
|
||||
▼
|
||||
crumbCollect.js
|
||||
▲
|
||||
│
|
||||
Crumb Saucer Bakery
|
||||
```
|
||||
|
||||
Both interfaces therefore share one authoritative implementation.
|
||||
# Installation
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node.js
|
||||
- Discord.js
|
||||
- MongoDB
|
||||
- A Discord bot application/token
|
||||
- `dotenv`
|
||||
- Dependencies listed in `package.json`
|
||||
|
||||
Use the Node.js version required by the dependencies in `package.json`.
|
||||
|
||||
## Installation
|
||||
|
||||
Clone the repository:
|
||||
Clone and install:
|
||||
|
||||
``` bash
|
||||
git clone https://git.desq-gaming.de/Shaiwase/ShaiBot.git
|
||||
cd ShaiBot
|
||||
```
|
||||
|
||||
Install dependencies:
|
||||
|
||||
``` bash
|
||||
npm install
|
||||
```
|
||||
|
||||
Create `.env` in the project root:
|
||||
Create `.env` in the repository root:
|
||||
|
||||
``` env
|
||||
D_TOKEN=YOUR_DISCORD_BOT_TOKEN
|
||||
M_URI=YOUR_MONGODB_CONNECTION_STRING
|
||||
M_DB=YOUR_DATABASE_NAME
|
||||
|
||||
# Optional
|
||||
BOT_AUTHOR_ID=YOUR_DISCORD_USER_ID
|
||||
PROFILE_TIMEZONE=Europe/Berlin
|
||||
```
|
||||
|
||||
Start the bot:
|
||||
Never commit `.env`.
|
||||
|
||||
Start normally:
|
||||
|
||||
``` bash
|
||||
node index.js
|
||||
```
|
||||
|
||||
For PM2, a typical command is:
|
||||
Or with PM2:
|
||||
|
||||
``` bash
|
||||
pm2 start index.js --name ShaiBot
|
||||
```
|
||||
|
||||
A typical update cycle is:
|
||||
|
||||
``` bash
|
||||
node --check path/to/changed-file.js
|
||||
pm2 restart ShaiBot
|
||||
pm2 logs ShaiBot --lines 100
|
||||
```
|
||||
|
||||
## MongoDB
|
||||
|
||||
ShaiBot's Cookie economy intentionally does **not** depend on MongoDB
|
||||
transactions, allowing it to work with deployments that do not support
|
||||
replica-set transactions.
|
||||
ShaiBot does not require MongoDB multi-document transactions for its
|
||||
core economy.
|
||||
|
||||
If your deployment does not support retryable writes, include:
|
||||
The bot instead relies on atomic updates, unique indexes, optimistic
|
||||
concurrency, idempotent operations, and recovery logic where
|
||||
appropriate.
|
||||
|
||||
If your Mongo deployment does not support retryable writes, your
|
||||
connection string may require:
|
||||
|
||||
``` text
|
||||
retryWrites=false
|
||||
```
|
||||
|
||||
in the connection string, for example:
|
||||
|
||||
``` env
|
||||
M_URI=mongodb://USER:PASSWORD@HOST:PORT/DATABASE?authSource=admin&retryWrites=false
|
||||
```
|
||||
|
||||
Never commit database credentials.
|
||||
|
||||
Important collections include Cookie balances, cooldowns, persistent
|
||||
game state, profile statistics, achievements, and global badge
|
||||
definitions/ownership.
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Core economy collections include:
|
||||
# Documentation
|
||||
|
||||
``` text
|
||||
items_cookies
|
||||
cooldown_cookies
|
||||
items_games
|
||||
```
|
||||
The central README intentionally stays high-level. Detailed
|
||||
implementation rules live in focused manuals:
|
||||
|
||||
`items_cookies` stores balances, `cooldown_cookies` stores action
|
||||
cooldown timestamps, and `items_games` can store persistent game state.
|
||||
------------------------------------------------------------------------------------
|
||||
Document Purpose
|
||||
------------------------------------------------ -----------------------------------
|
||||
[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) Runtime structure, handlers,
|
||||
utilities, Mongo persistence,
|
||||
concurrency, and recovery
|
||||
|
||||
Profile-related collection names should be treated as part of the
|
||||
profile utility's implementation contract rather than duplicated
|
||||
throughout command/button modules.
|
||||
[`docs/ECONOMY.md`](docs/ECONOMY.md) Cookie balances, transfers,
|
||||
cooldowns, house vault, settlement,
|
||||
and idempotency
|
||||
|
||||
### Recommended Indexes
|
||||
[`docs/PROGRESSION.md`](docs/PROGRESSION.md) Profiles, achievements, badges,
|
||||
activity, social progression, and
|
||||
maintenance
|
||||
|
||||
Run the shared index initializer after MongoDB connects:
|
||||
[`docs/GAMES.md`](docs/GAMES.md) Crumb Saucer games, Poker, Crumble
|
||||
Strike, and important game rules
|
||||
|
||||
``` js
|
||||
const {
|
||||
ensureCookieIndexes
|
||||
} = require("./utils/cookieEconomy");
|
||||
[`COOKIE_LOGIC.md`](COOKIE_LOGIC.md) Detailed PvP Cookie stealing rules
|
||||
and balancing
|
||||
|
||||
await mClient.connect();
|
||||
await ensureCookieIndexes();
|
||||
```
|
||||
[`AGENTS.md`](AGENTS.md) Repository-wide safety and
|
||||
architecture guide for AI coding
|
||||
agents
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
The intended unique keys include:
|
||||
The current repository code remains the final source of truth.
|
||||
|
||||
``` text
|
||||
items_cookies → userId
|
||||
cooldown_cookies → userId + guildId
|
||||
```
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Profile and badge utilities may establish their own required indexes.
|
||||
# Development Principles
|
||||
|
||||
## Discord Intents
|
||||
ShaiBot generally favors:
|
||||
|
||||
The current client uses intents including:
|
||||
- Shared utilities instead of duplicated game/economy logic
|
||||
- Thin Discord command/button wrappers
|
||||
- Persistent authoritative state where recovery matters
|
||||
- Atomic and idempotent economy operations
|
||||
- Centralized profile progression
|
||||
- Public game experiences with private sensitive information
|
||||
- Small explicit solutions over unnecessary abstraction
|
||||
|
||||
``` js
|
||||
GatewayIntentBits.Guilds
|
||||
GatewayIntentBits.GuildMembers
|
||||
GatewayIntentBits.GuildMessages
|
||||
GatewayIntentBits.GuildPresences
|
||||
GatewayIntentBits.GuildMessageReactions
|
||||
GatewayIntentBits.GuildVoiceStates
|
||||
GatewayIntentBits.DirectMessages
|
||||
GatewayIntentBits.MessageContent
|
||||
```
|
||||
|
||||
and partials including:
|
||||
|
||||
``` js
|
||||
Partials.Channel
|
||||
Partials.Message
|
||||
Partials.User
|
||||
Partials.GuildMember
|
||||
Partials.Reaction
|
||||
```
|
||||
|
||||
Enable any required privileged intents in the Discord Developer Portal.
|
||||
|
||||
## Interaction Design
|
||||
|
||||
ShaiBot generally follows these conventions:
|
||||
|
||||
- Normal user-facing messages, achievements, menus, and game output
|
||||
are **public by default**.
|
||||
- Errors, unauthorized interaction feedback, cooldown/debug-style
|
||||
notices, and similar operational messages may be **ephemeral**.
|
||||
- Games use **buttons** for interaction.
|
||||
- Existing messages are edited where practical instead of repeatedly
|
||||
sending new messages.
|
||||
- Game/session ownership is preserved so multiple users can play
|
||||
independently.
|
||||
- Public menus may be visible to everyone without allowing other users
|
||||
to control the owner's session.
|
||||
- Animation-like effects use rate-limit-conscious message edits.
|
||||
- Embed state should not be treated as the only authoritative source
|
||||
for critical economy/game resolution data.
|
||||
|
||||
## Economy Safety
|
||||
|
||||
Economy operations favor atomic MongoDB updates for balance checks and
|
||||
debits.
|
||||
|
||||
Transfers avoid MongoDB transactions for deployment compatibility. If a
|
||||
destination credit fails after a successful debit, the shared economy
|
||||
utility performs a best-effort compensating credit to the source
|
||||
account. Administrators should monitor logs for critical compensation
|
||||
failures.
|
||||
|
||||
When adding games, check that the house vault can cover the maximum
|
||||
possible payout before accepting a wager.
|
||||
|
||||
Game resolution should be protected against rapid repeated interactions.
|
||||
A result must never be paid twice simply because two button interactions
|
||||
reached the server close together.
|
||||
|
||||
Historical game facts such as wager amount, vault-at-wager, All-In
|
||||
state, and replay origin should be persisted when needed rather than
|
||||
reconstructed later from a player's live balance.
|
||||
|
||||
## Adding a Crumb Saucer Game
|
||||
|
||||
Preferred pattern:
|
||||
|
||||
1. Put shared game logic in `utils/`.
|
||||
2. Put individual Discord button handlers in the appropriate `buttons/`
|
||||
directory.
|
||||
3. Reuse `cookieEconomy.js` rather than implementing separate balance
|
||||
logic.
|
||||
4. Reuse `profileSystem.js` for statistics, achievements, and badges.
|
||||
5. Preserve the player/session owner through every screen.
|
||||
6. Check house liquidity before accepting a wager.
|
||||
7. Prefer editing the current embed for animation/state transitions.
|
||||
8. Protect wager resolution against rapid repeated interactions.
|
||||
9. Persist immutable wager metadata required by achievements or replay
|
||||
behavior.
|
||||
10. Keep application/button handlers thin and avoid duplicating shared
|
||||
rules.
|
||||
|
||||
## Achievement and Badge Design
|
||||
|
||||
Achievements and global badges serve different purposes:
|
||||
|
||||
**Achievements** are personal progression. Multiple players can earn the
|
||||
same achievement.
|
||||
|
||||
**Global badges** are unique guild-wide distinctions and may have a
|
||||
single owner.
|
||||
|
||||
When adding progression:
|
||||
|
||||
- Prefer stat-backed achievements for durable numeric milestones.
|
||||
- Use explicit event tracking when the accomplishment depends on a
|
||||
particular sequence or action.
|
||||
- Keep generalized achievement naming consistent between games where
|
||||
appropriate.
|
||||
- Do not make collector completion depend on achievements that cannot
|
||||
actually be obtained.
|
||||
- Use atomic badge claiming so two players cannot both receive a
|
||||
guild-first badge.
|
||||
- Hidden/manual badges do not need gameplay evaluators if they are
|
||||
intentionally awarded directly in MongoDB.
|
||||
|
||||
## Administration and Auditing
|
||||
|
||||
The profile system includes administrative/audit concepts for validating
|
||||
profile progression data and expected badge definitions.
|
||||
|
||||
When changing achievement or badge schemas:
|
||||
|
||||
- Keep existing IDs stable once players may have unlocked them.
|
||||
- Prefer adding new IDs over renaming historical IDs.
|
||||
- Treat legacy/disabled definitions explicitly.
|
||||
- Audit missing or malformed definitions after database changes.
|
||||
- Avoid hardcoding optional manually managed badges as mandatory
|
||||
configuration unless they are intended to exist in every guild.
|
||||
|
||||
## Roadmap / TODO
|
||||
|
||||
ShaiBot is currently focused on testing, balancing, hardening, and
|
||||
expanding progression.
|
||||
|
||||
Near-term work includes:
|
||||
|
||||
- [ ] Continue stress-testing simultaneous gambling interactions
|
||||
- [ ] Continue testing repeated/double button presses
|
||||
- [ ] Test insufficient-balance races
|
||||
- [ ] Test behavior with a nearly empty house vault
|
||||
- [ ] Validate All-In and Run It Back achievement edge cases
|
||||
- [ ] Validate Run It Back streak progression across supported games
|
||||
- [ ] Validate Slots triplet badge claiming
|
||||
- [ ] Continue balancing Vault Heist rewards and fines
|
||||
- [ ] Add Bankruptcy / starter recovery behavior
|
||||
- [ ] Continue centralizing persistent interaction/session ownership
|
||||
- [ ] Consider an economy audit/log collection
|
||||
- [ ] Verify Crumble Strike AoE Revive behavior
|
||||
- [ ] Verify Crumble Strike expiration/failure cleanup survives bot
|
||||
restarts
|
||||
- [ ] Balance Crumble Strike boss HP, damage, healing, Energy, Limit
|
||||
generation, entry costs, and rewards
|
||||
- [ ] Add more Crumble Strike bosses, lore, and encounter variety
|
||||
- [ ] Add more achievements, hidden badges, and Crumb Saucer
|
||||
attractions
|
||||
For stateful changes, always consider duplicate interactions,
|
||||
simultaneous users, insufficient-balance races, and bot restarts during
|
||||
settlement.
|
||||
|
||||
## Security
|
||||
|
||||
A suitable `.gitignore` should include at least:
|
||||
Keep at least the following out of version control:
|
||||
|
||||
``` gitignore
|
||||
node_modules/
|
||||
@@ -613,46 +282,8 @@ node_modules/
|
||||
*.log
|
||||
```
|
||||
|
||||
If a Discord token or MongoDB credential is accidentally committed,
|
||||
rotate it immediately.
|
||||
|
||||
Do not expose administrative secrets or database credentials through
|
||||
embeds, logs intended for public channels, or repository commits.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
ShaiBot Cookies are fictional in-bot currency with no real-world
|
||||
monetary value. Crumb Saucer gambling-style games are entertainment
|
||||
mechanics using that fictional currency.
|
||||
|
||||
Final Fantasy XIV names and concepts referenced by community game
|
||||
features belong to their respective rights holders. ShaiBot is not
|
||||
affiliated with or endorsed by Square Enix.
|
||||
|
||||
## Contributing
|
||||
|
||||
Bug reports, balance suggestions, and contributions are welcome.
|
||||
|
||||
When contributing:
|
||||
|
||||
- Keep commands and button handlers modular.
|
||||
- Reuse shared economy and profile utilities.
|
||||
- Avoid blocking the event loop.
|
||||
- Be mindful of Discord API rate limits.
|
||||
- Validate interaction ownership.
|
||||
- Keep database operations safe under concurrent interactions.
|
||||
- Preserve existing achievement/badge IDs where users may already own
|
||||
them.
|
||||
- Avoid introducing a second implementation of behavior that already
|
||||
has a shared utility.
|
||||
Rotate Discord or MongoDB credentials immediately if they are exposed.
|
||||
|
||||
## License
|
||||
|
||||
Add the license used by the repository here. If the project is open
|
||||
source, include a `LICENSE` file and replace this section with the
|
||||
chosen license.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Made for Discord communities that believe every problem can be improved
|
||||
with a few more Cookies. 🍪
|
||||
See the repository's current license information, if present.
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
# ShaiBot Architecture
|
||||
|
||||
This manual describes ShaiBot's implementation structure at a level
|
||||
useful to maintainers. For exact behavior, the current code remains
|
||||
authoritative.
|
||||
|
||||
## Runtime
|
||||
|
||||
`index.js` initializes the Discord client and MongoDB connection,
|
||||
creates the interaction collections, initializes shared systems/indexes,
|
||||
loads handlers, and logs the bot in.
|
||||
|
||||
Interaction modules are discovered into collections such as:
|
||||
|
||||
``` js
|
||||
client.commands
|
||||
client.legacyCommands
|
||||
client.aliases
|
||||
client.buttons
|
||||
client.selectMenus
|
||||
client.modals
|
||||
```
|
||||
|
||||
Before manually wiring a new component into the central router, check
|
||||
whether the filesystem loader already supports it.
|
||||
|
||||
## Preferred Layering
|
||||
|
||||
ShaiBot favors:
|
||||
|
||||
``` text
|
||||
Discord command / button / select menu
|
||||
↓
|
||||
shared utility
|
||||
↓
|
||||
Mongo / economy / profile
|
||||
```
|
||||
|
||||
Discord wrappers should remain thin. Shared rules belong in `utils/`.
|
||||
|
||||
A feature reachable from multiple interfaces should normally have one
|
||||
authoritative implementation.
|
||||
|
||||
## Important Shared Utilities
|
||||
|
||||
Examples include:
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Utility Responsibility
|
||||
----------------------------------- -----------------------------------
|
||||
`cookieEconomy.js` Cookie balances, transfers,
|
||||
cooldowns, economy primitives
|
||||
|
||||
`crumbCollect.js` Shared Cookie collection
|
||||
|
||||
`crumbSlots.js` Slots
|
||||
|
||||
`crumbBlackjack.js` Blackjack
|
||||
|
||||
`crumbRoulette.js` Roulette
|
||||
|
||||
`cookieHeist.js` Vault Heist
|
||||
|
||||
`bankruptcy.js` Bankruptcy/recovery
|
||||
|
||||
`profileSystem.js` Profiles, achievements, badges,
|
||||
activity
|
||||
|
||||
`profileMaintenance.js` Profile audit/reconciliation
|
||||
|
||||
`interactionSession.js` Shared single-owner interaction
|
||||
sessions
|
||||
|
||||
`permissions.js` Administrator/bot-author checks
|
||||
|
||||
`pokerEngine.js` Pure Hold'em engine
|
||||
|
||||
`crumbPoker.js` Persistent Poker service
|
||||
|
||||
`pokerDiscord.js` Poker Discord rendering/components
|
||||
|
||||
`pokerProfile.js` Poker progression bridge
|
||||
|
||||
`crumbleStrike.js` Cooperative encounter state/combat
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
## MongoDB
|
||||
|
||||
Important collections include:
|
||||
|
||||
``` text
|
||||
items_cookies
|
||||
cooldown_cookies
|
||||
items_games
|
||||
items_special_games
|
||||
stats_profiles
|
||||
items_achievements
|
||||
guild_badges
|
||||
config_achievements
|
||||
```
|
||||
|
||||
Indexes are part of correctness, not only performance.
|
||||
|
||||
ShaiBot intentionally avoids requiring multi-document MongoDB
|
||||
transactions. Depending on the subsystem it instead uses:
|
||||
|
||||
- Atomic filtered updates
|
||||
- Unique indexes
|
||||
- Optimistic version checks
|
||||
- Idempotency markers
|
||||
- Persistent resolution state
|
||||
- Compensating writes
|
||||
|
||||
## Concurrency
|
||||
|
||||
Assume users can double-click, spam controls, act simultaneously, race a
|
||||
timeout, or restart the bot during a transition.
|
||||
|
||||
Stateful systems should answer:
|
||||
|
||||
``` text
|
||||
What is authoritative?
|
||||
Can two interactions both succeed?
|
||||
Can money move twice?
|
||||
What happens if the process stops after the first write?
|
||||
Can the operation safely be retried?
|
||||
```
|
||||
|
||||
Do not rely on process-local flags for correctness that must survive a
|
||||
restart.
|
||||
|
||||
## Discord Interactions
|
||||
|
||||
Button visibility is never authorization.
|
||||
|
||||
For potentially slow stateful interactions, acknowledge Discord early
|
||||
using the response style appropriate to that flow.
|
||||
|
||||
Do not globally defer every interaction from the central router because
|
||||
different modules legitimately use `reply`, `update`, `deferReply`, or
|
||||
`deferUpdate`.
|
||||
|
||||
Critical state should not exist only in an embed/footer.
|
||||
|
||||
## Permissions
|
||||
|
||||
Administrative access is centralized through the shared permission
|
||||
utility.
|
||||
|
||||
Administrative access may include:
|
||||
|
||||
``` text
|
||||
Discord Administrator
|
||||
OR
|
||||
BOT_AUTHOR_ID
|
||||
```
|
||||
|
||||
Do not hard-code administrative Discord IDs.
|
||||
|
||||
## Deployment
|
||||
|
||||
Typical production workflow:
|
||||
|
||||
``` bash
|
||||
node --check path/to/changed-file.js
|
||||
pm2 restart ShaiBot
|
||||
pm2 logs ShaiBot --lines 100
|
||||
```
|
||||
|
||||
Syntax checking is useful, but economy and persistent-state changes
|
||||
still require behavioral testing.
|
||||
|
||||
## Maintainer Checklist
|
||||
|
||||
Before shipping a stateful change:
|
||||
|
||||
- Identify the authoritative state.
|
||||
- Check duplicate-click behavior.
|
||||
- Check simultaneous-user behavior.
|
||||
- Check insufficient-balance behavior.
|
||||
- Check restart/recovery behavior.
|
||||
- Check private/public information boundaries.
|
||||
- Check whether profile tracking can safely fail without corrupting
|
||||
settlement.
|
||||
- Inspect Mongo after a controlled live test.
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
# ShaiBot Cookie Economy
|
||||
|
||||
This manual describes the shared Cookie economy and the rules
|
||||
maintainers should preserve.
|
||||
|
||||
## Source of Truth
|
||||
|
||||
`utils/cookieEconomy.js` is the shared economy utility.
|
||||
|
||||
Game and command modules should not perform independent ad-hoc balance
|
||||
mutations when the shared economy already provides the required
|
||||
operation.
|
||||
|
||||
## Balances
|
||||
|
||||
Cookie balances live in:
|
||||
|
||||
``` text
|
||||
items_cookies
|
||||
```
|
||||
|
||||
Conceptually:
|
||||
|
||||
``` js
|
||||
{
|
||||
userId: "...",
|
||||
cookies: 2500
|
||||
}
|
||||
```
|
||||
|
||||
Negative changes use an atomic balance filter so a player cannot spend
|
||||
more Cookies than are available.
|
||||
|
||||
Expected insufficient-balance failures use:
|
||||
|
||||
``` text
|
||||
INSUFFICIENT_COOKIES
|
||||
```
|
||||
|
||||
Some subsystems carry expected error identifiers in `error.message`,
|
||||
while others may also use `error.code`. User-facing formatters should
|
||||
account for the convention used by that subsystem.
|
||||
|
||||
## Transfers
|
||||
|
||||
Player-to-player transfers do not require MongoDB transactions.
|
||||
|
||||
The safe conceptual sequence is:
|
||||
|
||||
``` text
|
||||
atomic debit source
|
||||
→ credit destination
|
||||
→ compensate source if destination credit fails
|
||||
```
|
||||
|
||||
A critical compensation failure must remain visible in logs.
|
||||
|
||||
## Cooldowns
|
||||
|
||||
Cooldowns live in:
|
||||
|
||||
``` text
|
||||
cooldown_cookies
|
||||
```
|
||||
|
||||
Use the shared cooldown helpers, especially atomic cooldown claiming
|
||||
when double-clicks or simultaneous requests must not both succeed.
|
||||
|
||||
## House Vault
|
||||
|
||||
ShaiBot acts as the general house Cookie vault for supported games.
|
||||
|
||||
Gambling losses and penalties may feed the vault, while wins, heists,
|
||||
and rewards may pay out from it.
|
||||
|
||||
House-funded features should respect their existing liquidity rules.
|
||||
|
||||
## Cookie Collection
|
||||
|
||||
`/cookies collect` and the Crumb Saucer Bakery share
|
||||
`utils/crumbCollect.js`.
|
||||
|
||||
They must share:
|
||||
|
||||
- the same cooldown
|
||||
- the same reward generation
|
||||
- the same balance mutation
|
||||
- the same profile tracking
|
||||
|
||||
Do not create separate collection behavior for the two interfaces.
|
||||
|
||||
## PvP Stealing
|
||||
|
||||
Normal player-to-player stealing is separate from Vault Heist.
|
||||
|
||||
Detailed robbery balancing lives in:
|
||||
|
||||
``` text
|
||||
COOKIE_LOGIC.md
|
||||
```
|
||||
|
||||
The current model includes wealth scaling, victim heat, percentage-based
|
||||
loot, a hard per-hit cap, and an hourly victim exposure budget.
|
||||
|
||||
## Persistent Game Settlement
|
||||
|
||||
For simple house games, settlement should still be protected against
|
||||
repeated resolution.
|
||||
|
||||
For lifecycle-heavy multiplayer games such as Poker, Cookie movement is
|
||||
separated from internal chip movement.
|
||||
|
||||
Poker only crosses the Cookie economy boundary for:
|
||||
|
||||
``` text
|
||||
buy-in
|
||||
cash-out / refund
|
||||
```
|
||||
|
||||
Ordinary Poker betting modifies the table's internal stack state, not
|
||||
`items_cookies`.
|
||||
|
||||
## Idempotent Operations
|
||||
|
||||
Recovery-sensitive economy flows can use operation IDs.
|
||||
|
||||
Poker temporarily stores markers such as:
|
||||
|
||||
``` js
|
||||
appliedCookieOperations: [
|
||||
"poker_buyin:...",
|
||||
"poker_cashout:..."
|
||||
]
|
||||
```
|
||||
|
||||
The purpose is to prevent a retry after a crash from moving money twice.
|
||||
|
||||
Safe lifecycle:
|
||||
|
||||
``` text
|
||||
apply Cookie operation once
|
||||
→ persist authoritative game state
|
||||
→ confirm operation is durably represented
|
||||
→ remove temporary marker
|
||||
```
|
||||
|
||||
Never remove a recovery marker before the surrounding state is safe.
|
||||
|
||||
When the final marker is removed, unset the empty field instead of
|
||||
leaving:
|
||||
|
||||
``` js
|
||||
appliedCookieOperations: []
|
||||
```
|
||||
|
||||
## Economy Invariants
|
||||
|
||||
Every economy change should preserve:
|
||||
|
||||
``` text
|
||||
No Cookie duplication.
|
||||
No unexplained Cookie loss.
|
||||
No duplicate debit.
|
||||
No duplicate payout.
|
||||
No spending below zero.
|
||||
```
|
||||
|
||||
Correctness and recoverability take priority over cosmetic cleanup.
|
||||
+262
@@ -0,0 +1,262 @@
|
||||
# ShaiBot Game Manual
|
||||
|
||||
This document gives maintainers a compact overview of the main game
|
||||
systems. Exact rules remain in the owning utilities.
|
||||
|
||||
# Crumb Saucer
|
||||
|
||||
The Crumb Saucer is ShaiBot's Cookie-powered game hub.
|
||||
|
||||
Shared principle:
|
||||
|
||||
``` text
|
||||
Discord controls
|
||||
→ game utility
|
||||
→ Cookie economy / profile system
|
||||
```
|
||||
|
||||
## Slots
|
||||
|
||||
Core utility:
|
||||
|
||||
``` text
|
||||
utils/crumbSlots.js
|
||||
```
|
||||
|
||||
Features include multiple wagers, symbol payouts, jackpots, All-In
|
||||
tracking, Run It Back, profile statistics, achievements, and guild-first
|
||||
triplet badges.
|
||||
|
||||
Historical replay facts must come from wager-time metadata rather than
|
||||
the player's current Cookie balance.
|
||||
|
||||
## Blackjack
|
||||
|
||||
Core utility:
|
||||
|
||||
``` text
|
||||
utils/crumbBlackjack.js
|
||||
```
|
||||
|
||||
Supports:
|
||||
|
||||
- Hit
|
||||
- Stand
|
||||
- Double
|
||||
- Dealer stands on 17
|
||||
- Natural Blackjack pays 3:2
|
||||
- Push
|
||||
- All-In
|
||||
- Run It Back
|
||||
|
||||
Repeated interactions must never resolve/pay the same hand twice.
|
||||
|
||||
## Roulette
|
||||
|
||||
Core utility:
|
||||
|
||||
``` text
|
||||
utils/crumbRoulette.js
|
||||
```
|
||||
|
||||
European Roulette uses `0–36`.
|
||||
|
||||
Simple bets include Red, Black, Odd, Even, and Zero. Zero loses for
|
||||
Red/Black/Odd/Even.
|
||||
|
||||
Animation uses edits of the same message rather than high-frequency
|
||||
message spam.
|
||||
|
||||
## Vault Heist
|
||||
|
||||
Core utility:
|
||||
|
||||
``` text
|
||||
utils/cookieHeist.js
|
||||
```
|
||||
|
||||
Vault Heist targets ShaiBot's house vault and is separate from PvP
|
||||
stealing.
|
||||
|
||||
Approaches include Sneak, Hack, and Smash and share the same Heist
|
||||
cooldown.
|
||||
|
||||
## Bankruptcy
|
||||
|
||||
Core utility:
|
||||
|
||||
``` text
|
||||
utils/bankruptcy.js
|
||||
```
|
||||
|
||||
Bankruptcy provides a recovery path and tracks post-Bankruptcy
|
||||
rebuilding in profiles.
|
||||
|
||||
Recovery progress should reflect actual balance after Bankruptcy, not
|
||||
merely lifetime Cookie gains.
|
||||
|
||||
## Run It Back
|
||||
|
||||
Supported games can track consecutive replay through the explicit Run It
|
||||
Back action.
|
||||
|
||||
A normal/new wager breaks the chain.
|
||||
|
||||
Win/loss/push does not inherently break it because the streak represents
|
||||
the player's decision to immediately replay.
|
||||
|
||||
Historical All-In and wager state must be preserved at the time the
|
||||
wager occurs.
|
||||
|
||||
# Poker
|
||||
|
||||
Poker is a persistent 2--6 player Texas Hold'em game inside the Crumb
|
||||
Saucer.
|
||||
|
||||
Important files:
|
||||
|
||||
``` text
|
||||
utils/pokerEngine.js
|
||||
utils/crumbPoker.js
|
||||
utils/pokerDiscord.js
|
||||
utils/pokerInteractions.js
|
||||
utils/pokerProfile.js
|
||||
handlers/poker.js
|
||||
buttons/poker/*
|
||||
selectMenus/poker/*
|
||||
```
|
||||
|
||||
Current defaults:
|
||||
|
||||
``` text
|
||||
Buy-in: 1,000 Cookies
|
||||
Blinds: 10 / 20
|
||||
Turn timer: 90 seconds
|
||||
Pot model: single pot
|
||||
```
|
||||
|
||||
Supported actions:
|
||||
|
||||
``` text
|
||||
Fold
|
||||
Check
|
||||
Call
|
||||
Bet
|
||||
Raise
|
||||
All-In
|
||||
```
|
||||
|
||||
## Single-Pot Rule
|
||||
|
||||
Poker intentionally has no side pots.
|
||||
|
||||
At hand start, the maximum amount each participant can commit is limited
|
||||
by the smallest participating starting stack.
|
||||
|
||||
Chips above that cap remain protected for a later hand.
|
||||
|
||||
## Persistence
|
||||
|
||||
MongoDB is authoritative for live/recoverable tables.
|
||||
|
||||
Poker uses temporary state in:
|
||||
|
||||
``` text
|
||||
items_special_games
|
||||
```
|
||||
|
||||
and optimistic versioning for authoritative updates.
|
||||
|
||||
Fully settled games are cleaned up rather than kept permanently as raw
|
||||
history.
|
||||
|
||||
## Economy
|
||||
|
||||
Cookies move only at buy-in and cash-out/refund boundaries.
|
||||
|
||||
Betting moves internal table chips.
|
||||
|
||||
Recovery-sensitive economy operations are idempotent.
|
||||
|
||||
## Privacy
|
||||
|
||||
Hole cards are private.
|
||||
|
||||
The private Cards view may show the requesting player's cards, community
|
||||
cards, turn status, and remaining turn time.
|
||||
|
||||
It must never expose opponent cards.
|
||||
|
||||
A player-facing equity/win-percentage calculator is intentionally
|
||||
excluded from V1 for fairness.
|
||||
|
||||
## Turn / Lobby Behavior
|
||||
|
||||
Active turns have a 90-second deadline.
|
||||
|
||||
Timeout folding uses the same authoritative Fold transition as a normal
|
||||
player action.
|
||||
|
||||
Lobby expiry is disabled while a hand is active and refreshed when a
|
||||
hand ends.
|
||||
|
||||
The internal between-hand state may be called `NEXT_HAND`, but the
|
||||
user-facing UI presents **HAND COMPLETE**.
|
||||
|
||||
## Cancellation / Cleanup
|
||||
|
||||
Host cancellation is allowed outside an active hand.
|
||||
|
||||
Cancellation safely settles players before deleting the table state.
|
||||
|
||||
Confirmation controls should disappear after Confirm or Keep so stale
|
||||
buttons cannot remain usable.
|
||||
|
||||
# Crumble Strike
|
||||
|
||||
Core utility:
|
||||
|
||||
``` text
|
||||
utils/crumbleStrike.js
|
||||
```
|
||||
|
||||
Crumble Strike is a persistent cooperative boss battle.
|
||||
|
||||
Typical flow:
|
||||
|
||||
1. Spawn encounter.
|
||||
2. Recruit players.
|
||||
3. Start once requirements are met.
|
||||
4. Fight within the encounter lifetime.
|
||||
5. Settle success/failure and committed Cookies.
|
||||
|
||||
Combat includes:
|
||||
|
||||
``` text
|
||||
Strike
|
||||
Defend
|
||||
Heal
|
||||
Revive
|
||||
Limit Break
|
||||
```
|
||||
|
||||
Roles include:
|
||||
|
||||
``` text
|
||||
DPS
|
||||
Tank
|
||||
Healer
|
||||
```
|
||||
|
||||
Crumble Strike has more lifecycle complexity than ordinary Saucer games.
|
||||
Do not copy its persistence model into simpler games unless the new
|
||||
feature genuinely requires it.
|
||||
|
||||
# Raid Planner
|
||||
|
||||
Raid planning uses Discord embeds and reactions.
|
||||
|
||||
Participation can count unique users across reactions without forcibly
|
||||
removing reactions.
|
||||
|
||||
Be mindful of Discord partials when changing reaction behavior.
|
||||
@@ -0,0 +1,200 @@
|
||||
# ShaiBot Profiles, Achievements & Badges
|
||||
|
||||
ShaiBot's profile system is the permanent progression layer behind the
|
||||
economy and games.
|
||||
|
||||
## Central Profile System
|
||||
|
||||
`utils/profileSystem.js` owns the main profile/progression behavior.
|
||||
|
||||
Important collections:
|
||||
|
||||
``` text
|
||||
stats_profiles
|
||||
items_achievements
|
||||
guild_badges
|
||||
config_achievements
|
||||
```
|
||||
|
||||
Game modules should integrate with this system instead of creating
|
||||
separate progression databases.
|
||||
|
||||
## Profiles
|
||||
|
||||
Profiles can track:
|
||||
|
||||
- Overall game totals
|
||||
- Per-game statistics
|
||||
- Cookie gains and losses
|
||||
- Giving and stealing
|
||||
- Daily activity
|
||||
- Win/loss streaks
|
||||
- Weekday/time-of-day activity
|
||||
- Social relationships
|
||||
- Run It Back progression
|
||||
- Poker history
|
||||
- Achievement progress
|
||||
- Badge ownership
|
||||
|
||||
Profiles are intended to preserve meaningful long-term history.
|
||||
|
||||
## Profile Events
|
||||
|
||||
Prefer extending established event metadata rather than inventing
|
||||
parallel event systems.
|
||||
|
||||
Common concepts include:
|
||||
|
||||
``` text
|
||||
game_start
|
||||
game_result
|
||||
cookie_gain
|
||||
cookies_given
|
||||
steal_success
|
||||
stolen_from_me
|
||||
```
|
||||
|
||||
New wager metadata should prefer:
|
||||
|
||||
``` text
|
||||
wager
|
||||
```
|
||||
|
||||
Compatibility reads for older `bet`/`previousBet` fields may remain
|
||||
intentionally.
|
||||
|
||||
## Activity
|
||||
|
||||
Profile activity uses a configured timezone.
|
||||
|
||||
Default:
|
||||
|
||||
``` text
|
||||
Europe/Berlin
|
||||
```
|
||||
|
||||
Activity supports daily streaks, weekly participation, weekday counts,
|
||||
and broad time buckets.
|
||||
|
||||
Avoid making ordinary progression depend on excessively narrow
|
||||
late-night windows.
|
||||
|
||||
## Social Progression
|
||||
|
||||
Profiles can store unique relationship sets for gifting and stealing.
|
||||
|
||||
Use set-style updates for unique users rather than appending duplicates.
|
||||
|
||||
Current social progression is intentionally scaled for a relatively
|
||||
small community.
|
||||
|
||||
## Achievements
|
||||
|
||||
Achievements are personal: multiple players can earn the same
|
||||
achievement.
|
||||
|
||||
Supported models include:
|
||||
|
||||
### Stat-backed
|
||||
|
||||
Best for durable lifetime milestones and reconciliation.
|
||||
|
||||
### Composite
|
||||
|
||||
Combines multiple durable conditions.
|
||||
|
||||
### Event-only
|
||||
|
||||
Used when the accomplishment depends on exact event context that cannot
|
||||
reliably be reconstructed later.
|
||||
|
||||
### Hidden
|
||||
|
||||
Used for secret/special challenges.
|
||||
|
||||
Event-only achievements should not be treated as historically
|
||||
backfillable when the necessary event was never stored.
|
||||
|
||||
## Achievement Notifications
|
||||
|
||||
Unlock notification is centralized.
|
||||
|
||||
Individual games should not create competing achievement announcement
|
||||
systems.
|
||||
|
||||
## Global Badges
|
||||
|
||||
Global badges are guild-unique distinctions.
|
||||
|
||||
The common pattern is an atomic claim against an unowned badge:
|
||||
|
||||
``` text
|
||||
guildId
|
||||
badgeId
|
||||
ownerId: null
|
||||
```
|
||||
|
||||
then setting the winner.
|
||||
|
||||
This prevents simultaneous candidates from both owning the same
|
||||
guild-first badge.
|
||||
|
||||
Achievements and badges are intentionally different:
|
||||
|
||||
``` text
|
||||
Achievement → personal; many owners
|
||||
Global badge → guild-unique; one owner
|
||||
```
|
||||
|
||||
## ID Stability
|
||||
|
||||
Once achievement or badge IDs may exist in MongoDB, treat them as
|
||||
persistent database identifiers.
|
||||
|
||||
Prefer retiring an old definition over renaming/deleting an ID that
|
||||
players may already own.
|
||||
|
||||
## Reconciliation & Audit
|
||||
|
||||
Administrative tooling includes:
|
||||
|
||||
``` text
|
||||
/profileadmin audit
|
||||
/profileadmin reconcile dry-run:true
|
||||
```
|
||||
|
||||
Reconciliation can backfill durable/stat-backed accomplishments.
|
||||
|
||||
Event-only achievements may be skipped because historical event context
|
||||
cannot be invented safely.
|
||||
|
||||
When changing progression schemas:
|
||||
|
||||
- use idempotent migrations
|
||||
- preserve existing values
|
||||
- preserve historical IDs
|
||||
- dry-run reconciliation first
|
||||
- do not fabricate data that was never tracked
|
||||
|
||||
## Poker History
|
||||
|
||||
Poker stores permanent statistics in the profile system rather than
|
||||
retaining completed raw table documents.
|
||||
|
||||
Examples include:
|
||||
|
||||
- hands played/won/lost
|
||||
- Cookies won/lost
|
||||
- largest pot
|
||||
- All-Ins
|
||||
- showdowns
|
||||
- action counts
|
||||
- streaks
|
||||
- hand-rank counters
|
||||
- pocket Aces wins
|
||||
- 7-2 wins
|
||||
- fold wins
|
||||
- full-table wins
|
||||
|
||||
Poker profile tracking occurs after authoritative game state succeeds. A
|
||||
profile failure must never corrupt a valid pot/economy settlement.
|
||||
Reference in New Issue
Block a user