## Implementation Plan: Risk, Defense Systems, and Penalties for Code Farm Raiding ### Objective Extend the existing Code Farm raiding mechanic with purchasable defense items, failure probability, raider fines, insurance payout for defenders, and a pre-raid risk assessment. Maintain backward compatibility with the existing `DefenseTier` system – the new items operate as orthogonal modifiers on top of the tier’s base steal fraction. ### Database Changes (`devplacepy/database/schema.py`) 1. **Add `game_farm_defense_items` table** Columns: `uid` (UUID PK), `farm_uid` (FK → `game_farms.uid`), `item_type` (ENUM: `mines`, `cameras`, `guards`, `insurance`), `purchased_at` (ISO timestamp). Index on `(farm_uid, item_type)`. 2. **Add `game_failed_steals` table** Columns: `uid` (UUID PK), `thief_uid` (FK → users), `owner_uid` (FK → users), `farm_uid` (FK → `game_farms.uid`), `failure_type` (ENUM: `mine`, `camera`, `guard`), `fine_applied` (int, coins), `cooldown_until` (ISO timestamp), `occurred_at` (ISO timestamp). 3. **Add `insurance_payout` column** to `game_steals` table (nullable int). When insurance is active on the owner’s farm, half the stolen coins are credited back and stored here. ### Service Layer Changes (`devplacepy/services/game/` or `devplacepy/services/game.py` – exact location to be determined from project structure) 4. **New service function: `compute_defense_items_effect(farm_uid)`** Returns a dict with: - `failure_chance`: sum of base probabilities – 0.15 per mine item, 0.10 per camera, 0.20 per guard (caps at 0.80). - `catch_chance`: cameras add 0.10 per unit to catch probability (used if not killed by mine/guard). - `auto_catch_prob`: guards add 0.15 per unit (immediate failure if rolled). - `fine_base`: mine=100, camera=50, guard=75. - `has_insurance`: boolean. 5. **Modify `steal()` (core raid logic)** After computing `effective_steal_fraction` from existing tier formula, apply defense item effects: - Roll first for **auto-catch** (guards): if hit, raid fails immediately → record failure in `game_failed_steals` with fine = `fine_base * escalation_multiplier`, deduct from raider’s `coins` (set to 0 if insufficient), apply per-farm cooldown (1 hour). - Roll for **mine** failure: if hit, same failure sequence. - Roll for **camera** catch: if hit, failure with camera fine, else raid proceeds. - If raid proceeds successfully: award steal fraction modified by a **risk bonus multiplier** = `1 + 0.05 * (num_mines + num_cameras + num_guards)`. Cap total steal fraction at 0.50 (50% of crop value). - If owner has insurance, automatically credit owner with 50% of stolen coins (store in `insurance_payout` column). 6. **Escalating penalties** Query `game_failed_steals` for the raider in the last 24 hours. `escalation_multiplier = 1 + (count_failures_last_day - 1) * 0.5` (i.e., second failure 1.5x, third 2x, etc.). After a failure, set a per-farm cooldown `cooldown_until` (current time + 1 hour). The raider cannot attempt that farm again until expiry. 7. **Insurance purchase** Use existing coins. Cost: 500 coins per purchase (one-time, not recurring). Add a new action `game_insurance_purchase` that inserts into `game_farm_defense_items` with type `insurance`. ### API / Action Changes (`devplacepy/services/devii/actions/catalog/game.py`) 8. **New action: `game_defense_item_purchase`** POST, requires auth. Parameters: `farm_uid`, `item_type` (enum). Validates farm ownership, sufficient coins, no duplicate for `insurance` (only one allowed). Inserts row, deducts coins. Returns updated defense profile. 9. **Extended serialization for `game_view_farm`** In addition to `defense_level`, `defense_tier_name`, add: - `defense_items`: list of `{item_type: str, purchased_at: str}` - `raid_risk`: computed `{failure_chance: float, fine_min: int, fine_max: int, has_insurance: bool}` ### Frontend / UX Considerations (non‑code but necessary for completeness) - The raider will see the `raid_risk` data in the farm detail view before clicking `Steal`. - The owner will see a new “Defense Shop” interface to purchase items. - These UI changes are **outside scope** of this backend plan; the plan assumes the frontend can consume the new fields. ### Concurrency and Safety - All coin deductions/transfers must use row-level locking on the user’s coin balance to prevent race conditions (use a `SELECT … FOR UPDATE` pattern in the service layer). - Use a transaction for the entire steal sequence. ### Test Plan (`tests/api/game/mutations.py` and unit tests) **New unit tests** (in `tests/unit/services/game/economy.py` or a new file): - `test_defense_items_failure_probability` – assert correct probability sums. - `test_failed_raid_fine_deduction` – raider coins decrease. - `test_escalating_penalty_multiplier` – second failure has higher fine. - `test_insurance_payout_on_success` – owner receives half. - `test_per_farm_cooldown_after_failure` – block re‑raid within 1 hour. **New integration tests** (in `tests/api/game/mutations.py`): - `test_steal_fails_on_guard_farm` – raid fails when guards present. - `test_steal_succeeds_with_risk_bonus` – higher reward on defended farm. - `test_defense_item_purchase_success` – item inserted, coins deducted. - `test_insurance_purchase_duplicate_rejected` – 400 response. - `test_view_farm_shows_raid_risk` – response includes new fields. **Regression**: existing Playwright e2e tests must still pass. The earlier failures were infrastructure issues (Playwright browser setup); we should ensure our changes do not modify any HTML/UI elements that those tests rely on. If any tests are flaky due to timing, we may need to add a stable wait in tests. However, for this plan we assume we do not touch e2e test code. --- ### Definition of Done - All new database tables, columns, and migrations exist and match the schema described. - The `game_steal` action correctly models failure probability from defense items, applies fines, and records failures. - The `game_steal` action applies a risk bonus to the steal fraction when defense items are present, capped at 50% of crop value. - Escalating penalties increase fines based on the raider’s failure count in the last 24 hours. - A 1-hour per-farm cooldown is enforced after a failed raid. - Owners can purchase insurance via a new `game_insurance_purchase` endpoint, and when a successful raid occurs against an insured farm, the owner automatically receives 50% of stolen coins. - The farm detail endpoint (`game_view_farm`) returns a `raid_risk` object with failure chance, fine range, and insurance status. - All new API actions are authenticated and validate farm ownership where required. - The following tests pass with zero failures: - New unit tests for economy formulas. - New integration tests for steal failure, item purchase, insurance payout. - Full existing test suite: `pip install -e '.[dev]' -q && python -m pytest` (including all Playwright e2e tests). - No regressions in existing steal, defense upgrade, or cooldown behavior. - The implementation does not modify any files outside the target domain (no changes to Playwright test infrastructure).