# AGENTS ## Context - Game genre: roguelite strategy deckbuilder. - Game fantasy: program a robot courier on a hex farmland delivering crate goods to sheds while glitches mutate instructions and patches improve the deck/program. - Use this file to keep new work aligned with the existing design/implementation; see code under RobotAndDonkey.Game and tests under RobotAndDonkey.Tests. ## Design document - Detailed system design exists in the design.md file. - UX design for a card row exists in the cardrow.md file. ## Tech Design - Deterministic core: GameState.GameState.CreateNew seeds Utils.SRandom; CoreLoop owns Board.Generate, glitch deck, robot, decks, and metrics (energy wasted, overspill, path length, visits). Balancing tunables live in Data/Balancing.cs. - Deterministic finite automaton: CoreLoop.RunPhase (ERunPhase) feeds Requests (Execution/Requests/*) and Commands (Execution/Commands/*) via GameRuntime; EnterPreview seeds the first tape/hand; loop is DrawGlitch -> Improve -> (Gamble/BufferOverflow) -> ExecuteProgram/Scoring -> back to DrawGlitch. - Entities/modifiers: cards/robots/cells derive from Modifiers.Entity holding modifiers. Modifier (Kind/Id/Duration) exposes OnAdded/Before/After/OnRemoved; DebuffSources disables effects. ModifierStack pushes robot -> cell -> card layers before each card; immunity/debuff rules are honored when executing intents. - Intent pipeline: cards override Card.CreateIntents to enqueue intents (Intents/*). ModifierStack.Execute runs modifier Before hooks, validates Intent.IsValid (energy + debuffs), runs intents (mutate board/currency/add intents), then After hooks. Results records mirror deltas for UI sync. - Board model: Board.Board stores ImmutableArray and TargetDeliveryAmount; Board.Generate builds axial hex maps sized by difficulty, sprinkling terrain/POIs with Balancing probabilities while preserving connectivity and POI reachability. Towers seed permanent Unreliable to neighbors; corrupt cells added by spread. FindCellIndex is currently O(n). - Robots: Robots.* records define starting deck/program count; base Robot exposes Currency (energy/max carry/preview/tape length/hand size) derived from difficulty. Derived robots add modifiers (e.g., AnalystModifier) and deck tweaks. - Cards/modifiers: Cards/Patches and Cards/Glitches are records; PatchCard/GlitchCard derive from Card with tooltip/modifier metadata. ModifyCardBase handles temporary modifier application; OccupiedSpace respects Efficient. Corruption-aware indexing uses Utils.CardExtensions.NextIndexConsideringCorruption. - Frontend: HexBoard3D builds a 3D board with HexMeshBuilder multimeshes per cell type, billboarded POI sprites cached in dictionaries, highlight/selection meshes, camera-facing pivoted textures, optional debuff VFX from cell modifiers. Exported textures/materials/pivots enable art hookup. ## Code Style & Patterns - Indentation is done with 4 spaces per level. - C# records and expression-bodied members; prefer immutability (ImmutableArray, init props) and explicit DeepClone including modifiers/debuff state. - No modifier duplicates; always use AddModifier/InsertModifier/RemoveModifier so hooks fire. Respect DebuffSources when checking if effects apply. - Intents/results are the only way to mutate state for UI; emit CurrencyResult/HandResult/TapeResult/PoiResult/etc. with a cloned state whenever state changes. - Thread deterministic RNG through CoreLoop.Random (ref SRandom) instead of creating new Random instances; avoid hidden randomness. - Balancing.Instance is the source of truth for costs/probabilities; avoid magic numbers in cards/intents/board generation. - Tests live in RobotAndDonkey.Tests with builders (BoardBuilder, CoreLoopBuilder, TestRuntime, CardTestBase) and card-specific suites; mirror patterns for new content to keep coverage and determinism. - Hex math uses axial coords (Utils.Hex) and EDirection; derive relative directions via helpers instead of manual math to respect corruption/orientation rules. Rendering caches meshes/sprites and small helper methods over monoliths. - Variable names are full words and are not abbreviated (e.g. exception instead of ex, image instead of img). Structs have an S prefix, enums have an E prefix, fields have a m_ prefix, statics have a s_ prefix, members use UpperCamelCase, locals and arguments use lowerCamelCase. - Inside of a class: statics appear first, then methods, then properties, and finally all other members. - Always include method visibility modifiers, especially private. - Don't use regions. - Curly braces each belong in their own line.