320 lines
19 KiB
Markdown
320 lines
19 KiB
Markdown
# Donkeys and Droids - Design
|
||
Fantasy promise: you are “programming” a delivery robot in a noisy, glitchy world where logistics (carry, routing, instruction budget) fights entropy (corruption, unreliability, race conditions, weather). The donkey is a great tonal contrast: low-tech capacity as a counterweight to high-tech brittleness.
|
||
|
||
## Metagame and Setup
|
||
- Run parameters
|
||
- `MatchParameters` carries `RobotType`, `Difficulty`, and `Seed` to ensure deterministic runs.
|
||
- Difficulty settings and starting currency
|
||
- Easy
|
||
- Energy: 50
|
||
- MaxCarry: 10
|
||
- HandSize: 9
|
||
- TapeLength: 6
|
||
- Medium
|
||
- Energy: 40
|
||
- MaxCarry: 8
|
||
- HandSize: 8
|
||
- TapeLength: 5
|
||
- Hard
|
||
- Energy: 30
|
||
- MaxCarry: 6
|
||
- HandSize: 7
|
||
- TapeLength: 4
|
||
- Currency fields
|
||
- Energy: spent by most actions and restored by some cards and cells.
|
||
- MaxCarry: total goods capacity.
|
||
- Carry: goods currently held.
|
||
- Delivery: goods already delivered.
|
||
- TapeLength: available instruction slots.
|
||
- HandSize: number of cards that can be held.
|
||
- Preview: intended for future preview capacity; not yet wired in code, but kept in design for Foresight.
|
||
- Robots and starting decks
|
||
- Vintage (selectable)
|
||
- ProgramCount: 5 programs per day.
|
||
- Starting deck: 4 Move, 4 TurnRight, 4 TurnLeft, 4 Interact, 4 NoOp.
|
||
- Analyst (code-defined, not currently pickable)
|
||
- ProgramCount: 5.
|
||
- Starting deck: Vintage deck plus AluminumHat.
|
||
- Stats: HandSize increased by 1.
|
||
- Modifier: first glitch deferral costs 1 energy less.
|
||
- Identity: information, preview, controlled deferrals.
|
||
- Courier (code-defined, not currently pickable)
|
||
- ProgramCount: 5.
|
||
- Stats: MaxCarry +1; TapeLength -1.
|
||
- Deck tweak: +1 Move (and one fewer NoOp than Vintage).
|
||
- Modifier: CourierOverspill converts any delivery delta into +5 Energy once per delivery intent batch.
|
||
- Identity: delivery loops, overspill energy, routing greed.
|
||
- Ranger (code-defined, not currently pickable)
|
||
- ProgramCount: 5.
|
||
- Stats: Energy +2.
|
||
- Starting deck: Vintage deck plus DetoxiumPrime.
|
||
- Modifier: resting on Fertile restores +1 extra Energy.
|
||
- Identity: terrain mastery, resting economy, survival
|
||
- Unlock notions (not enforced in runtime)
|
||
- Finish a full run.
|
||
- Deliver a threshold in one day.
|
||
- Complete a delivery under a low-instruction budget.
|
||
|
||
## Core Loop and Phases
|
||
- High-level phase order
|
||
- Init
|
||
- ExecuteProgram (initial preview occurs here)
|
||
- Scoring
|
||
- DrawGlitch
|
||
- Improve
|
||
- Optional side loops: Gamble or BufferOverflow
|
||
- Return to ExecuteProgram and repeat until termination.
|
||
- Init
|
||
- Seeds the first ExecuteProgram.
|
||
- Immediately jumps to ExecuteProgram.
|
||
- ExecuteProgram
|
||
- Player actions before execution
|
||
- MoveCards: freely reorder cards between hand and tape, respecting HandSize and TapeLength by counting OccupiedSpace (Efficient cards count as 0).
|
||
- Discard: pay 1 Energy per selected hand card; each discarded card is replaced from the top of the deck if available.
|
||
- RunProgram: execute the current tape.
|
||
- RunProgram flow
|
||
- Bookkeeping: ProgramCount decrements; ProgramsExecuted increments.
|
||
- Pre-run shuffle: each RaceCondition card has a 25% chance to swap with its neighbor (next if normal, previous if the card is Corrupt) within the TapeLength window.
|
||
- Modifier stack: intents are processed by Robot modifiers first, then the current Cell, then the Card; modifiers with active debuff sources are skipped.
|
||
- Intent validity: intents require sufficient Energy and no active debuffs unless forced execution is used.
|
||
- Card resolution
|
||
- Persistent cards return to hand after execution; other cards move to discard.
|
||
- ShortTerm modifiers are cleared after each program.
|
||
- Temporary modifiers are cleared when entering Scoring.
|
||
- Termination check after execution
|
||
- If ProgramCount reaches zero, PatchDeck is empty, Energy is zero or below, or all sheds are filled, then:
|
||
- Add 10 Energy.
|
||
- Clear all Temporary modifiers.
|
||
- Set phase to Scoring.
|
||
- Otherwise, draw back up to HandSize and remain in ExecuteProgram for the next program.
|
||
- Scoring
|
||
- NextAssignment command resets shop state by collecting tape, hand, and discard into the deck, shuffling, and preparing a fresh hand on the next day.
|
||
- Phase moves to DrawGlitch; board and robot state persist between days.
|
||
- DrawGlitch
|
||
- Glitch deck is a fixed set, shuffled once, and loops forever without depletion.
|
||
- Accept: apply the current glitch immediately.
|
||
- Defer: advance the cursor and charge Energy equal to (deferCount+1)(deferCount+2)/2; deferCount never resets. After either action, advance to Improve.
|
||
- Improve
|
||
- Shop
|
||
- Five unique patch cards are offered using rarity weights: Common 108, Magic 36, Uncommon 12, Rare 3, Legendary 1.
|
||
- Shop cards never include buffs or debuffs.
|
||
- Buying
|
||
- Pay the card’s ShopCost (or zero if taken from a booster) and add it to the deck.
|
||
- Rerolling
|
||
- Costs rerollCount + 1 Energy.
|
||
- Increments rerollCount and rebuilds the shop with new cards.
|
||
- PreviewProgram
|
||
- Moves to ExecuteProgram and re-enters preview: reshuffles, draws a new hand, and resets ProgramCount to the robot’s value.
|
||
- One-time flags per day: CanGamble and CanBufferOverflow start true and flip to false after use.
|
||
- Gamble (optional branch from Improve)
|
||
- Entry costs 5 Energy and requires CanGamble.
|
||
- Produces a booster of six patch cards.
|
||
- Each booster card independently rolls for modifiers: 25% buff chance scaled down by difficulty, 25% debuff chance scaled up by difficulty.
|
||
- Booster cards are free to take; stopping returns to Improve.
|
||
- Buffer Overflow (optional branch from Improve)
|
||
- Entry costs 10 Energy and requires CanBufferOverflow.
|
||
- Shuffles the deck and draws a new hand.
|
||
- DestroyCard lets the player remove one hand card, then returns to Improve. StopBufferOverflow returns to Improve and puts the drawn hand back into the deck.
|
||
|
||
## Board and World
|
||
- Generation rules
|
||
- Hex board radius = 2 + fDifficulty * 2, where fDifficulty = 0.5 + difficulty/4.
|
||
- An outer ring beyond the playable radius is also generated.
|
||
- The avatar starts at (0,0) facing a random direction.
|
||
- Terrain splats (scaled by difficulty) place Blocked, Dry, Fertile, Mud, and Rocky cells.
|
||
- Corrupt cell modifiers are placed after POIs.
|
||
- Blocked and Corrupt cells are treated as walls for reachability.
|
||
- Points of interest
|
||
- Donkey: sprinkled on 5% of eligible cells; each gets a random facing.
|
||
- Shed: sprinkled on 10% of eligible cells; each holds a delivery request.
|
||
- Crate: sprinkled on 20% of eligible cells; each holds goods.
|
||
- Tower: sprinkled on 5% of eligible cells; each receives permanent Unreliable and gives Unreliable to neighbors.
|
||
- Requests and offers
|
||
- TargetDeliveryAmount equals the sum of shed requests.
|
||
- Default shed request is 10, with per-shed variance.
|
||
- Crate amounts sum to a bonus total that scales down with higher difficulty.
|
||
- Connectivity constraints
|
||
- Placement rejects any change that would break reachability from the avatar when treating Blocked and Corrupt cells as impassable.
|
||
- FindCellIndex currently scans linearly (O(n)); reordering or indexing would enable O(1) lookup (TODO).
|
||
- Terrain effects during play
|
||
- Mud: Move intents incur an additional 1 Energy via a follow-up currency change.
|
||
- Fertile: Rest intents restore an additional 1 Energy.
|
||
- Dry: Rest restores 1 less Energy; Interact costs 1 extra Energy.
|
||
- Rocky: has no runtime effect (only a generation tag).
|
||
- Corrupt, Unreliable, RaceCondition on a cell: entering the cell applies that modifier temporarily to all remaining tape instructions.
|
||
- Towers can be toggled inactive; inactive towers debuff their Unreliable modifiers so they stop applying.
|
||
|
||
## Currency and Metrics
|
||
- Currency handling
|
||
- All changes flow through ModifyCurrency, which prevents negative Energy, MaxCarry, Carry, Delivery, TapeLength, or HandSize.
|
||
- Recruiting or dismissing a donkey changes MaxCarry by 10 (positive when recruited, negative when released).
|
||
- Metrics tracked
|
||
- ProgramsExecuted: number of programs run.
|
||
- InstructionsUsed: one per card executed.
|
||
- PathLength: total movement distance.
|
||
- CellsVisited: set of all visited cells.
|
||
- Overspill: amount delivered beyond shed requests.
|
||
|
||
## Modifiers and Intent Pipeline
|
||
- Processing order per card
|
||
- Robot modifiers.
|
||
- Cell modifiers on the current avatar cell.
|
||
- Card modifiers on the card being executed.
|
||
- Duration types
|
||
- Permanent: persists across the entire run.
|
||
- Temporary: cleared when entering Scoring.
|
||
- ShortTerm: cleared after each program.
|
||
- Corruption effects (when a Corrupt modifier is active and not debuffed)
|
||
- Move: reverses direction.
|
||
- Turn: flips the rotation delta.
|
||
- Rest: original rest is debuffed; a forced backward Move is added.
|
||
- Interact
|
||
- Crate: dumps all carried goods into the crate.
|
||
- Shed: fails and refunds Energy instead of delivering.
|
||
- Tower: toggles the tower active.
|
||
- Donkey: drops a carried donkey onto an empty cell if present.
|
||
- ImmunizeCard with CanCorrupt: removes immunity instead of adding it.
|
||
- ModifyCurrency with CanCorrupt: flips the sign of all deltas.
|
||
- DetoxiumPrime: harms the target cell instead of healing it.
|
||
- References to "next" become references to "previous" when the referencing card is Corrupt.
|
||
- Other modifier behaviors
|
||
- Unreliable: 25% chance to debuff intents, causing them to do nothing.
|
||
- RaceCondition: 25% chance to swap position with a neighbor before execution (next or previous if Corrupt).
|
||
- Effective: 25% chance to duplicate the current intents.
|
||
- Optimized: reduces CardCostIntent by 1.
|
||
- Throttled: increases CardCostIntent by 1.
|
||
- Efficient: OccupiedSpace becomes 0 for hand/tape limits.
|
||
- Persistent: card returns to hand instead of discard after execution.
|
||
- GlobalImmunity: suppresses specified modifiers across entities while active.
|
||
- Gravity: lowers MaxCarry by 2 and increases Move cost by 1 while active; restores on removal.
|
||
- HeatWave: immediately removes 10 Energy when applied; restores 10 on removal.
|
||
- Pest: halves Delivery gains applied via ModifyCurrency.
|
||
- CourierOverspill: adds 5 Energy whenever a Delivery delta is detected.
|
||
- RangerFertileRest: adds 1 Energy when resting on a Fertile cell.
|
||
- Analyst: reduces the Energy cost of the first glitch deferral by 1.
|
||
|
||
## Cards - Patches
|
||
- Common
|
||
- Move: move forward 1 cell if free.
|
||
- TurnRight: rotate 60 degrees clockwise.
|
||
- TurnLeft: rotate 60 degrees counter-clockwise.
|
||
- Interact: interact with the forward cell.
|
||
- NoOp: rest and restore 5 Energy.
|
||
- Magic (temporary buffs to following tape cards; when Corrupt they instead grant temporary immunity to that modifier)
|
||
- Potentiate: adds Effective to following cards.
|
||
- Optimize: adds Optimized to following cards.
|
||
- Streamline: adds Efficient to following cards.
|
||
- Persist: adds Persistent to following cards.
|
||
- Uncommon
|
||
- DetoxiumPrime: heals the forward cell (or harms if Corrupt).
|
||
- FlyingDisk: move forward 1 ignoring blocking and POIs.
|
||
- AluminumHat: grants ShortTerm immunity to Unreliable for following cards.
|
||
- EMField: grants Temporary immunity to Corrupt for following cards.
|
||
- AtomicClock: grants ShortTerm immunity to RaceCondition for following cards.
|
||
- Load Balancer: grants ShortTerm immunity to Throttled for following cards. (design intent; not yet implemented).
|
||
- Rare
|
||
- Remember: permanently increases TapeLength by 1 (Corrupt can invert the delta).
|
||
- Reason: permanently increases HandSize by 1 (Corrupt can invert the delta).
|
||
- Foresight: intended to permanently increase Preview by 1 (Corrupt can invert the delta); design placeholder for future preview mechanics.
|
||
- Legendary
|
||
- Jump: move forward 2 cells, ignoring blocking and POIs.
|
||
- Repeat: re-executes the next card (or previous if Corrupt) with safeguards against loops.
|
||
- Rest: restore 20 Energy.
|
||
- Stabilize: temporarily nullifies all modifiers on the next card (previous if Corrupt).
|
||
- Costs
|
||
- Default play cost for patches is 1 Energy.
|
||
- NoOp, Repeat, Jump, and Rest have a play cost of 0 Energy.
|
||
- Shop costs follow Balancing values per card type.
|
||
|
||
## Cards - Glitches
|
||
- Permanent single-card modifiers applied to a random deck card
|
||
- Bitflip: adds Corrupt permanently.
|
||
- ShortCircuit: adds Unreliable permanently.
|
||
- Slipstream: adds RaceCondition permanently.
|
||
- Latency: adds Throttled permanently.
|
||
- Temporary modifiers applied to all deck cards
|
||
- SolarFlare: adds Corrupt temporarily.
|
||
- LightningStorm: adds Unreliable temporarily.
|
||
- MeteorStorm: adds RaceCondition temporarily.
|
||
- WindStorm: adds Throttled temporarily.
|
||
- Map and robot glitches (Temporary)
|
||
- Rain: converts Rocky to Dry; may convert Grass to Mud.
|
||
- Drought: converts Fertile to Grass; may convert Grass to Dry.
|
||
- Pest: halves Delivery gains.
|
||
- Gravity: lowers MaxCarry by 2 and adds 1 Energy to Move.
|
||
- HeatWave: immediately removes 10 Energy.
|
||
- SandStorm: preview malus is planned but not implemented.
|
||
|
||
## Known Gaps / TODOs
|
||
- Implement Load Balancer patch.
|
||
- Optimize board lookup (FindCellIndex is O(n)); consider indexed storage for O(1).
|
||
- Expose Analyst, Courier and Ranger in selection when ready.
|
||
- Extend modifier hooks so Delivery/Rest effects triggered in Interact/Rest logic also route through ModifyCurrency, aligning courier/ranger/pest behaviors.
|
||
- Implement the Preview mechanic and stat, including other design elements (like e.g., Foresight).
|
||
- For each tape slot, show predicted position/facing/energy/carry changes.
|
||
- Limit the previewable tape length with the Preview stat.
|
||
- “Add 10 Energy when day terminates (including when Energy reaches zero)” can read like a magical bailout unless framed as “enter sleep cycle, recharge.”
|
||
- Diegetic wrappers for each phase
|
||
- ExecuteProgram = “Compile & Run”
|
||
- Scoring = “Telemetry Report”
|
||
- DrawGlitch = “Incoming Anomaly”
|
||
- Improve = “Repair Bay / Patch Installer”
|
||
- Make the stack legible in fiction and UI: For every instruction step, show: robot modifiers → Local modifiers (cell aura/tower) → Instruction modifiers.
|
||
- Presort hand
|
||
- Multiselect drag
|
||
- Clear tape command
|
||
- Glitch deferral mechanic can collapse into a single dominant behavior. If deferCount never resets and cost grows triangularly, optimal play often becomes “defer early only when absolutely necessary, then never defer again,” reducing meaningful choice.
|
||
- Glitch decision becomes richer if it’s a trade, not a tax. Replace infinite defer escalation with one of:
|
||
- Reset automatically after X days.
|
||
- Reset dynamically (drops by N after triggering a core-loop mechanic).
|
||
- Convert to a “heat meter” where deferring increases heat, accepting reduces it.
|
||
- Shop offers without synergy steering. Weighted rarity alone does not guarantee players see “build paths.” Without mild biasing toward current deck/robot, the shop can feel random rather than responsive.
|
||
- Give the player an intentional “build direction” mechanism. Light drafting: choose one of two “contract modifiers” each assignment that biases shop pool and rewards a playstyle.
|
||
- Make assignments meaningfully distinct, e.g. introduce “priority sheds,” timed bonuses, or “fragile goods” constraints.
|
||
- Unlocks should teach, not just gate
|
||
- Unlock robots/cards via challenges that naturally demonstrate the mechanic (low tape budget run unlocks “Efficient” archetype).
|
||
- Punctuate “milestones”
|
||
- Filling a shed, recruiting a donkey, disabling a tower, completing an assignment: each should be a mini-celebration with strong feedback.
|
||
- Variable reward that is still fair: In Gamble boosters: guarantee at least one “clean” high-rarity card or one buffed card so the purchase rarely feels like regret.
|
||
- Combo feedback: When Effective duplicates, when Persist chains value, when Optimize saves energy: show “savings” and “extra actions” as highlighted wins.
|
||
- Permanent negative modifiers need permanent solutions: cleansing, “firmware reset,” or “quarantine a card” systems.
|
||
- Telegraph uncertainty: Show on the tape which slots are unstable and why (tower aura, corrupt cell, race swap risk).
|
||
- Show last program’s path, and a “why did this fail?” postmortem that points to the modifier responsible.
|
||
- Add a rare “Reflash Firmware” card: remove a modifier from 1 card permanently.
|
||
- Disabling a tower could grant a one-time reward (energy, clean patch, or “stability” buff for next program) so it feels worth the detour.
|
||
- Mitigation economy: New resource: “Stability” earned by deliveries or disabling towers. Spend it to cleanse or to defer without energy cost.
|
||
- Add a few more “benign glitches” (small upside with small downside) so the glitch screen isn’t always dread.
|
||
- Rebalance nop: reduced baseline, scale stronger with terrain (e.g. zero energy on dry)
|
||
- “Scrubber” shop service: pay energy to remove a modifier from a card.
|
||
- Avoid “randomly hit my best card” feel: Permanent glitch targeting can be weighted toward a visible “at-risk” subset the player can influence.
|
||
- Reward exploration
|
||
- Hidden caches or “debug terminals” that grant a free reroll, a cleanse, or a preview increase.
|
||
- “Modifiers with active debuff sources are skipped” is subtle. Players need to see what’s suppressed and why.
|
||
- Low-rarity answers to high-rarity problems prevent runs from hinging on rare draws:
|
||
- “Checksum”: remove Temporary modifiers from the next 2 tape cards.
|
||
- Expose a “seed replay” summary. Deterministic runs are a gift: let players replay a seed, share it, and compare strategies.
|
||
- Cosmic Rays should have a flatter rarity weight curve.
|
||
- Remove randomness from RaceCondition
|
||
- Replace randomness from Unreliable with an incrementing wrapping counter, replacing an intent when the counter wraps around. The replaced intent could be some sort of NoOp.
|
||
- Replace "opposite" from Corrupt with Damplen+Wear:
|
||
- Dampen: all numeric deltas produced by that card are shifted 1 step toward zero.
|
||
- ModifyCurrency: +10 → +9, -2 → -1
|
||
- Rest energy, card-cost intents, Move distance, Turn delta magnitude: all shrink by 1 step where applicable
|
||
- Clamp at +/- 1 to not introduce sign-flip betrayal or make cards useless.
|
||
- Wear: after resolution, add a Worn stack to the card.
|
||
- Each Worn stack adds +1 Energy to that card’s play cost (implemented as a follow-up CardCostIntent(+1) when the card is played).
|
||
- Make Jump rare instead of legendary
|
||
- Make Repeat rare instead of legendary
|
||
|
||
## New card ideas
|
||
- Reflash Firmware (Rare): Permanently remove one modifier from a random card in your deck.
|
||
- Load (Uncommon): interact only with crates, bonus carry.
|
||
- Drop (Uncommon): interact only with sheds, bonus delivery.
|
||
- Grabber arm (Rare): Interact with forward Crate or Shed at range 2.
|
||
- Burst (Legendary): Move forward 3 (stops early if blocked).
|
||
- Backflip (Rare): Turn around 180°
|
||
- Strafe right (Rare): Move forward if not blocked, otherwise strafe 60° to the right.
|
||
- Strafe left (Rare): Move forward if not blocked, otherwise strafe 60° to the left.
|
||
- Black Box Recorder (Legendary): Create a copy of the next card and add it to your deck.
|
||
- Adaptive Turn (Legendary): Turn towards the nearest tower, donkey, crate or shed.
|
||
- Macro (Legendary): re-executes the next two cards with safeguards against loops. |