Fix #148: Add risk, defense systems, and penalties to Code Farm raiding #149

Open
typosaurus wants to merge 1 commits from typosaurus/ticket-148 into master
Collaborator

Resolves #148.

Plan

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)

  1. 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.
  2. 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).
  3. 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.

  4. 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)

  1. 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.

  2. 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).

Opened automatically by Typosaurus.

Resolves #148. ## Plan ## 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). Opened automatically by Typosaurus.
typosaurus added 1 commit 2026-07-27 22:25:49 +02:00
ticket #148 attempt 1
Some checks failed
DevPlace CI / test (pull_request) Failing after 59m44s
1a1bab1004
Some checks failed
DevPlace CI / test (pull_request) Failing after 59m44s
This pull request can be merged automatically.
You are not authorized to merge this pull request.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin typosaurus/ticket-148:typosaurus/ticket-148
git checkout typosaurus/ticket-148
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: retoor/devplacepy#149
No description provided.