Files
zfxaction25/design.md
2026-04-19 00:43:27 +02:00

320 lines
19 KiB
Markdown
Raw Permalink 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.
# 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 cards 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 robots 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 its 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 programs 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 isnt 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 whats 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 cards 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.