ported from perforce

This commit is contained in:
2026-04-19 00:43:27 +02:00
commit 6c0c33f5d4
700 changed files with 19735 additions and 0 deletions

35
AGENTS.MD Normal file
View File

@@ -0,0 +1,35 @@
# 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<Cell> 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.