openthebox/CLAUDE.md

70 lines
3.4 KiB
Markdown
Raw Normal View History

# Open The Box
## Project Overview
A console-based incremental/idle game built in C# (.NET 9) where players open boxes to discover items, unlock features, and progress through themed adventures. Uses Spectre.Console for rich terminal rendering and Loreline for interactive narrative scripting.
## Architecture
See [specifications.md](specifications.md) for detailed content organization.
## Key Directories
- `src/OpenTheBox/` — Main game source code
- `content/data/` — JSON data files (items, boxes, crafting recipes)
- `content/adventures/` — Loreline `.lor` adventure scripts (one folder per theme)
- `content/localization/` — Translation files
## Source Code Structure
- `Core/` — Game state, enums, item/character models
- `Core/Enums/` — All enum types (StatType, ResourceType, AdventureTheme, CosmeticSlot, etc.)
- `Adventures/` — AdventureEngine (Loreline bridge + custom functions)
- `Simulation/` — Game engines (BoxEngine, MetaEngine, ResourceEngine, CraftingEngine, GameSimulation)
- `Rendering/` — IRenderer interface, SpectreRenderer, RenderContext, panel components
- `Rendering/Panels/` — Individual UI panels (PortraitPanel, ResourcePanel, StatsPanel, etc.)
- `Data/` — ContentRegistry, ItemDefinition, BoxDefinition data loading
- `Persistence/` — SaveManager, SaveData (JSON serialization)
- `Localization/` — LocalizationManager, Locale enum
## Build & Run
```
dotnet build
dotnet run --project src/OpenTheBox
```
## Test
```
dotnet test
```
## Adventure System
Adventures use Loreline `.lor` script format. Custom functions available in scripts:
- Inventory: `grantItem(id, qty)`, `hasItem(id)`, `removeItem(id)`
- Resources: `hasResource(name, min)`, `getResourceValue(name)`, `addResource(name, amount)`
- Stats: `hasStat(name, min)`, `getStatValue(name)`
- Cosmetics: `hasCosmetic(id)`, `hasEquipped(slot, style)`
- Progression: `hasCompletedAdventure(theme)`, `markSecretBranch(id)`, `hasSecretBranch(id)`, `countSecretBranches()`, `allSecretBranches()`
Hints for disabled choices use `|||` separator: `Option text|||Hint text #label if condition`
full documentation: https://loreline.app/fr/docs/
## Pacing Test
To check game progression balance after modifying loot tables (`content/data/boxes.json`):
```
dotnet test --filter "FullRun_PacingReport" --logger "console;verbosity=detailed"
```
This runs a full simulation (3 seeds: 42, 123, 777) and prints a report showing when each milestone is first reached (UI features, adventures, cosmetics, resources, crafting, lore). Use this to verify that rebalancing changes produce the desired early-game pacing.
Key things to look for:
- **1st Meta UI unlock** should happen before box ~50 for a good early experience
- **1st Adventure** should appear before box ~120
- **All content reachable** within ~1000 boxes (game completion)
- No long gaps between milestones (>100 boxes without progress feels stale)
Weights are in `content/data/boxes.json`. The main generator is `box_of_boxes` (auto-opens, produces the next box). Adjust weights there and in tier boxes (`box_not_great`, `box_ok_tier`, etc.) to tune pacing.
## Conventions
- C# 12 with file-scoped namespaces, primary constructors where appropriate
- Immutable records for value types, sealed classes for services
- GameState is mutable, passed by reference to engines
- All user-facing strings go through LocalizationManager
- Enum names match JSON string values (PascalCase)