Files
thecrimesynticate/docs/superpowers/specs/2026-06-28-escape-from-jail-design.md
T

138 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)