Document offline fork support architecture
Add long-term design consideration for forking the RPG campaign as a standalone offline experience. ARCHITECTURE.md: - Add 'Offline Standalone Fork' section explaining: - Why offline support matters (single-player RPG focus) - Architecture principles for fork compatibility - Core engine independence requirements - Potential package structures and distribution options - What stays vs what goes in a fork AGENTS.md: - Add 'Core Engine Independence' section with: - Rules for keeping app/core/ decoupled - Import boundary examples (allowed vs forbidden) - Link to full architecture docs This ensures all contributors understand the design constraint: the game engine must remain completely independent of network, database, and authentication concerns.
This commit is contained in:
parent
91ad2cf0a5
commit
703bed07fb
40
AGENTS.md
40
AGENTS.md
@ -223,6 +223,46 @@ opponent_deck_count=len(opponent.deck) # ONLY count
|
||||
5. **Tests**: Include docstrings explaining "what" and "why" for each test.
|
||||
6. **Phaser in Vue**: Keep Phaser scenes focused on rendering. Game logic lives in backend.
|
||||
7. **Services**: Never bypass the service layer for business logic.
|
||||
8. **Core Engine Independence**: Keep `app/core/` decoupled from DB/network (see below).
|
||||
|
||||
---
|
||||
|
||||
## Core Engine Independence (Offline Fork Support)
|
||||
|
||||
> **Long-term goal**: The `backend/app/core/` module should remain forkable as a standalone offline game.
|
||||
|
||||
The game engine must stay **completely decoupled** from network and database concerns to enable a future offline/standalone version of the RPG campaign mode.
|
||||
|
||||
### Rules for `app/core/` Module
|
||||
|
||||
| DO | DON'T |
|
||||
|----|-------|
|
||||
| Accept `CardDefinition` objects as parameters | Import from `app.services` or `app.api` |
|
||||
| Use `RandomProvider` protocol for RNG | Import database session types |
|
||||
| Keep state self-contained in `GameState` | Make network calls or database queries |
|
||||
| Use sync logic (async wrappers at service layer) | Require authentication or user sessions |
|
||||
| Load configuration from `RulesConfig` objects | Hard-code database connection strings |
|
||||
|
||||
### Import Boundaries
|
||||
|
||||
```python
|
||||
# ALLOWED in app/core/
|
||||
from app.core.models import CardDefinition, GameState
|
||||
from app.core.config import RulesConfig
|
||||
from app.core.rng import RandomProvider
|
||||
|
||||
# FORBIDDEN in app/core/
|
||||
from app.services.card_service import CardService # NO - DB dependency
|
||||
from app.api.deps import get_current_user # NO - Auth dependency
|
||||
from sqlalchemy.ext.asyncio import AsyncSession # NO - DB dependency
|
||||
```
|
||||
|
||||
### Why This Matters
|
||||
|
||||
See `docs/ARCHITECTURE.md#offline-standalone-fork` for full details. The core engine should be directly copyable to a standalone Python application with:
|
||||
- Card definitions loaded from JSON files
|
||||
- Save data stored locally
|
||||
- No network or authentication requirements
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ This document provides a detailed technical overview of the Mantimon TCG archite
|
||||
6. [Game Engine](#game-engine)
|
||||
7. [AI System](#ai-system)
|
||||
8. [Security Considerations](#security-considerations)
|
||||
9. [Offline Standalone Fork](#offline-standalone-fork)
|
||||
|
||||
---
|
||||
|
||||
@ -820,3 +821,115 @@ async def validate_action(game: GameState, player_id: str, action: dict) -> Vali
|
||||
|
||||
return ValidationResult(False, "Unknown action type")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Offline Standalone Fork
|
||||
|
||||
> **Design Consideration**: The architecture intentionally supports forking as a completely offline, standalone experience for the RPG/campaign mode.
|
||||
|
||||
### Why This Matters
|
||||
|
||||
The primary gameplay experience is a single-player RPG campaign. While the live service provides multiplayer and cloud saves, many players may prefer:
|
||||
- Offline play without internet dependency
|
||||
- Local save files they fully control
|
||||
- A self-contained executable with no account requirements
|
||||
- Modding and customization freedom
|
||||
|
||||
### Architecture Principles for Fork Compatibility
|
||||
|
||||
The `backend/app/core/` game engine is designed to be **completely decoupled** from network and database concerns:
|
||||
|
||||
| Component | Live Service | Offline Fork |
|
||||
|-----------|--------------|--------------|
|
||||
| Game Engine (`core/`) | Same | Same (copy directly) |
|
||||
| Card Definitions | PostgreSQL | Embedded JSON files |
|
||||
| Save Data | PostgreSQL + Redis | Local JSON/SQLite files |
|
||||
| Authentication | OAuth/JWT | None needed |
|
||||
| Multiplayer | WebSocket/Socket.io | Removed entirely |
|
||||
| RNG | SecureRandom | SeededRandom (for replays) |
|
||||
|
||||
### Core Engine Independence
|
||||
|
||||
The game engine has **zero dependencies** on:
|
||||
- Database connections
|
||||
- Network I/O
|
||||
- Authentication/sessions
|
||||
- Redis caching
|
||||
- WebSocket communication
|
||||
|
||||
All it needs:
|
||||
- `RulesConfig` (can be hardcoded or loaded from JSON)
|
||||
- `CardDefinition` objects (can be embedded or loaded from files)
|
||||
- `RandomProvider` (SeededRandom works offline)
|
||||
|
||||
### Potential Offline Package Structure
|
||||
|
||||
```
|
||||
mantimon-offline/
|
||||
├── game/
|
||||
│ ├── core/ # Direct copy of backend/app/core/
|
||||
│ ├── campaign/ # NPC definitions, dialog, progression
|
||||
│ │ ├── clubs/ # Club data (NPCs, leaders, rewards)
|
||||
│ │ ├── dialog/ # NPC dialog trees
|
||||
│ │ └── progression.py # Campaign state machine
|
||||
│ ├── cards/ # Card definitions as JSON
|
||||
│ │ ├── base_set.json
|
||||
│ │ └── expansion_1.json
|
||||
│ └── saves/ # Local save directory
|
||||
│ └── slot_1.json
|
||||
├── ui/ # Could reuse Phaser or use PyGame/Godot
|
||||
├── assets/ # Card images, sounds
|
||||
└── main.py # Entry point
|
||||
```
|
||||
|
||||
### Packaging Options for Distribution
|
||||
|
||||
| Approach | Bundle Size | Complexity | UI Reuse |
|
||||
|----------|-------------|------------|----------|
|
||||
| **Electron + Python** | ~150MB | Medium | Full web UI |
|
||||
| **Tauri + Python** | ~30MB | High | Full web UI |
|
||||
| **PyInstaller + PyGame** | ~50MB | Low | New UI needed |
|
||||
| **Godot + GDScript port** | ~40MB | Medium | New UI needed |
|
||||
| **Nuitka + embedded browser** | ~80MB | Medium | Phaser reuse |
|
||||
|
||||
### What Stays, What Goes
|
||||
|
||||
**Keep (copy to fork):**
|
||||
- `backend/app/core/` - Entire game engine
|
||||
- `frontend/src/game/` - Phaser scenes (if using web UI)
|
||||
- Card definitions (export from DB to JSON)
|
||||
- Campaign/NPC data
|
||||
|
||||
**Remove (not needed offline):**
|
||||
- `backend/app/api/` - REST endpoints
|
||||
- `backend/app/websocket/` - Multiplayer sync
|
||||
- `backend/app/services/` - DB-backed services
|
||||
- Authentication system
|
||||
- Matchmaking/lobby
|
||||
|
||||
### Development Guidelines
|
||||
|
||||
To maintain fork compatibility, follow these rules when developing the core engine:
|
||||
|
||||
1. **No imports from `app.api`, `app.websocket`, or `app.services`** in `app.core`
|
||||
2. **No database session dependencies** in core engine functions
|
||||
3. **Card definitions passed in**, not fetched - `GameEngine.create_game()` receives a card registry
|
||||
4. **RNG injected via protocol** - `RandomProvider` allows swapping implementations
|
||||
5. **State is self-contained** - `GameState` includes everything needed to resume a game
|
||||
6. **No async required** - Core logic is sync; async wrappers added at service layer
|
||||
|
||||
### Testing Offline Viability
|
||||
|
||||
The existing test suite validates offline compatibility:
|
||||
- All `tests/core/` tests run without database
|
||||
- `SeededRandom` enables deterministic testing
|
||||
- Card fixtures are created in-memory, not loaded from DB
|
||||
|
||||
### Future: Official Offline Release
|
||||
|
||||
If demand exists, an official offline version could be released:
|
||||
1. Export campaign data and card definitions to JSON
|
||||
2. Bundle core engine with a lightweight UI wrapper
|
||||
3. Distribute as standalone executable (itch.io, Steam, etc.)
|
||||
4. Optional: Steam Workshop for community card sets
|
||||
|
||||
Loading…
Reference in New Issue
Block a user