ported from perforce
This commit is contained in:
320
design.md
Normal file
320
design.md
Normal file
@@ -0,0 +1,320 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user