# Escape from Jail — Design Spec **Date:** 2026-06-28 **Status:** Approved --- ## Overview Add a **Bust Out** mechanic to the jail page. A jailed character can spend cash to attempt an escape. Success rate is based on `dexterity + speed` stats. Success releases immediately; failure multiplies remaining sentence by 1.5×. Cash is always deducted regardless of outcome. --- ## Data Model No new tables or columns required. Uses existing `characters.status` and `characters.in_jail_until`. --- ## Bust-Out Mechanics ### Cost 1000 cash (from `config('game.jail.breakout_cost')`). Deducted whether the attempt succeeds or fails. ### Success Rate Formula ``` success_rate = min( config('game.jail.bust_out_max_chance'), config('game.jail.breakout_chance') + (dexterity + speed) * config('game.jail.bust_out_stat_multiplier') ) ``` With defaults: - `breakout_chance` = 0.05 (existing) - `bust_out_stat_multiplier` = 0.003 (new) - `bust_out_max_chance` = 0.80 (new) A fresh character (dex=5, speed=5) starts at **8%**. A well-trained character (dex=50, speed=50) reaches **35%**. Max possible is **80%**. ### On Success - Deduct `breakout_cost` cash - Set `status → active` - Set `in_jail_until → null` - Redirect to `game.dashboard` with success flash ### On Failure - Deduct `breakout_cost` cash - Multiply remaining jail time by `sentence_multiplier` (1.5×): `in_jail_until = now()->addSeconds(ceil($character->in_jail_until->diffInSeconds(now()) * 1.5))` - Redirect back to `game.jail` with failure flash showing new release time --- ## Config Changes (`config/game.php`) Add two keys to the existing `jail` block: ```php 'jail' => [ 'sentence_length' => 3600, 'breakout_chance' => 0.05, 'breakout_cost' => 1000, 'sentence_multiplier' => 1.5, 'bust_out_stat_multiplier' => 0.003, // per combined dex+speed point 'bust_out_max_chance' => 0.80, // cap at 80% ], ``` --- ## New Files | File | Purpose | |------|---------| | `app/Services/Game/JailService.php` | `bustOut(Character): array`, `sendToJail(Character, int): void`, `releaseFromJail(Character): void` | | `app/Http/Controllers/Game/JailController.php` | `bustOut(Request): RedirectResponse` | ### `JailService` interface ```php /** * @return array{success: bool, message: string} */ public function bustOut(Character $character): array public function sendToJail(Character $character, int $seconds): void public function releaseFromJail(Character $character): void ``` `bustOut()` returns `['success' => true/false, 'message' => string]`. The message is a human-readable outcome description suitable for a flash notice. --- ## Modified Files | File | Change | |------|--------| | `config/game.php` | Add `bust_out_stat_multiplier` and `bust_out_max_chance` to `jail` block | | `resources/views/game/jail.blade.php` | Add Bust Out card below status card | | `routes/game.php` | Add `POST /game/jail/bust-out` → `JailController@bustOut` | --- ## Routes ```php Route::middleware(['auth'])->group(function () { Route::post('/game/jail/bust-out', [JailController::class, 'bustOut'])->name('game.jail.bust-out'); }); ``` The bust-out route lives in the same `auth`-only group as the existing jail view route (no `verify.character` needed — jailed characters can't have characters, but do need auth). --- ## UI — Jail Page Dark crime theme, consistent with existing pages. **Bust Out card** sits below the existing status card. Contains: - Success percentage (calculated from character stats, shown as e.g. "12% chance") - Cash cost ("Costs $1,000") - "Bust Out" button — disabled with tooltip if character has < 1000 cash - CSRF-protected POST form **Flash messages:** - Success: "You escaped! You're free." → redirects to dashboard - Failure: "Bust failed — your sentence was extended to [new release time]." → stays on jail page --- ## Out of Scope (this iteration) - Busting out another player (requires PvP) - Nerve/energy cost for bust attempts - Per-attempt cooldown (failure penalty is time extension only) - Bust attempt history / activity log entry (can add later)