287 lines
7.5 KiB
Markdown
287 lines
7.5 KiB
Markdown
# 🧩 Code of Conquest — Character Generation (Flask API)
|
|
|
|
## Overview
|
|
|
|
This document describes how **character generation** operates inside the Flask API.
|
|
The goal is to produce a fully realized `Entity` (hero, enemy, or NPC) based on **race**, **profession**, **abilities**, and **level** using YAML-defined data and procedural logic.
|
|
|
|
---
|
|
|
|
## ⚙️ Directory Overview
|
|
|
|
```
|
|
app/
|
|
├── blueprints/
|
|
│ ├── main.py # Root routes
|
|
│ └── char.py # Character creation and progression endpoints
|
|
│
|
|
├── game/
|
|
│ ├── generators/ # Procedural content
|
|
│ │ ├── abilities_factory.py # Generates abilities / skills
|
|
│ │ ├── entity_factory.py # Builds complete entity objects
|
|
│ │ ├── level_progression.py # XP and level curve logic
|
|
│ │ └── ... (compiled files)
|
|
│ │
|
|
│ ├── loaders/ # YAML loaders for static templates
|
|
│ │ ├── profession_loader.py
|
|
│ │ ├── races_loader.py
|
|
│ │ └── spells_loader.py # May be deprecated in favor of skills
|
|
│ │
|
|
│ ├── models/ # Dataclasses for core game objects
|
|
│ │ ├── abilities.py
|
|
│ │ ├── entities.py
|
|
│ │ ├── professions.py
|
|
│ │ ├── races.py
|
|
│ │ └── enemies.py
|
|
│ │
|
|
│ ├── systems/
|
|
│ │ └── leveling.py # Handles XP gain, set_level, and skill growth
|
|
│ │
|
|
│ ├── templates/
|
|
│ │ ├── ability_paths.yaml # Defines thematic skill sets (paths)
|
|
│ │ ├── professions/*.yaml # Defines all professions
|
|
│ │ └── races/*.yaml # Defines all playable races
|
|
│ │
|
|
│ └── utils/
|
|
│ └── common.py
|
|
│
|
|
└── utils/
|
|
├── catalogs/ # Compiled catalog data for fast lookups
|
|
│ ├── race_catalog.py
|
|
│ ├── hero_catalog.py
|
|
│ └── skill_catalog.py
|
|
├── api_response.py
|
|
└── settings.py
|
|
```
|
|
|
|
---
|
|
|
|
## 🧬 Entity Generation Pipeline
|
|
|
|
### 1. `entity_factory.build_entity()`
|
|
|
|
Creates a base entity by combining **Race** and **Profession** definitions.
|
|
|
|
**Steps:**
|
|
|
|
1. Load race + profession data from YAML via loaders.
|
|
2. Apply racial ability modifiers.
|
|
3. Apply profession base stats and per-level growth rates.
|
|
4. Initialize HP, MP, XP, and skill lists.
|
|
|
|
---
|
|
|
|
### 2. `leveling.set_level(entity, target_level)`
|
|
|
|
Handles level setting and skill gain.
|
|
|
|
* Calculates XP using `level_progression.py`.
|
|
* Calls `calculate_skills_gained()` (randomized 30% chance per level).
|
|
* Generates new skills via `abilities_factory`.
|
|
|
|
---
|
|
|
|
## 🧝 Races
|
|
|
|
Located in `app/game/templates/races/`.
|
|
|
|
Each race defines:
|
|
|
|
* Base ability modifiers (STR, DEX, CON, INT, WIS, CHA)
|
|
* Optional descriptive text
|
|
* Tags for gameplay classification
|
|
|
|
Example (`elf.yaml`):
|
|
|
|
```yaml
|
|
name: Elf
|
|
description: Graceful and attuned to magic.
|
|
ability_mods:
|
|
DEX: 2
|
|
INT: 1
|
|
CON: -1
|
|
tags: ["playable"]
|
|
```
|
|
|
|
---
|
|
|
|
## ⚔️ Professions
|
|
|
|
Located in `app/game/templates/professions/`.
|
|
|
|
Each profession file defines:
|
|
|
|
* Base HP / MP
|
|
* Scaling per level
|
|
* Primary stat (INT, WIS, etc.)
|
|
* Flavor / lore fields
|
|
|
|
Example (`warlock.yaml`):
|
|
|
|
```yaml
|
|
id: warlock
|
|
name: Warlock
|
|
description: A wielder of forbidden demonic power.
|
|
primary_stat: CHA
|
|
base_hp: 40
|
|
base_mp: 80
|
|
physical_attack_per_level: 1.0
|
|
physical_defense_per_level: 0.5
|
|
magic_attack_per_level: 2.5
|
|
magic_defense_per_level: 1.5
|
|
tags: ["caster","dark"]
|
|
```
|
|
|
|
---
|
|
|
|
## 🧠 Ability / Skill Generation
|
|
|
|
### Path Themes
|
|
|
|
Defined in `templates/ability_paths.yaml`:
|
|
|
|
```yaml
|
|
Hellknight:
|
|
elements: ["fire", "shadow"]
|
|
adjectives: ["Infernal", "Hellfire", "Brimstone", "Abyssal"]
|
|
nouns: ["Edict", "Judgment", "Brand", "Smite"]
|
|
of_things: ["Dominion", "Torment", "Cinders", "Night"]
|
|
```
|
|
|
|
### Generator Function
|
|
|
|
Located in `abilities_factory.py`:
|
|
|
|
```python
|
|
def generate_spells_direct_damage(
|
|
class_name: str,
|
|
path: str,
|
|
level: int,
|
|
per_tier: int = 2,
|
|
content_version: int = 1,
|
|
primary: str = "INT"
|
|
) -> List[Spell]:
|
|
...
|
|
```
|
|
|
|
**Features:**
|
|
|
|
* Deterministic random seed based on `(class, path, level, version)`
|
|
* Generates direct-damage only
|
|
* Scales power and cost by level
|
|
* Names and effects are thematically consistent
|
|
|
|
### Example Output
|
|
|
|
```
|
|
Infernal Judgment — Deal fire damage (power 120, CHA+125%). MP 30, CD 1
|
|
Brand of Cinders — Deal shadow damage (power 118, CHA+125%). MP 30, CD 0
|
|
```
|
|
|
|
---
|
|
|
|
## 📈 Level Progression
|
|
|
|
Handled in `level_progression.py`.
|
|
|
|
* Defines XP thresholds per level (exponential curve)
|
|
* Provides helper: `get_xp_for_level(level)`
|
|
* Ensures `entity.xp_to_next_level` is always accurate after XP updates.
|
|
|
|
---
|
|
|
|
## 🎲 Skill Gain Logic
|
|
|
|
Implemented in `systems/leveling.py`.
|
|
|
|
```python
|
|
def calculate_skills_gained(current_level, target_level, chance_per_level=0.3):
|
|
levels_gained = max(0, target_level - current_level)
|
|
if levels_gained == 0:
|
|
return 0
|
|
|
|
gained = sum(1 for _ in range(levels_gained) if random.random() < chance_per_level)
|
|
if levels_gained < 3:
|
|
gained = max(gained, 2)
|
|
|
|
cap = math.ceil(levels_gained * 0.4)
|
|
return min(gained, cap)
|
|
```
|
|
|
|
* **30% random chance** per level to gain a new skill
|
|
* Guarantees **≥ 2** if leveling fewer than 3 levels
|
|
* Caps maximum growth to **40%** of total levels gained
|
|
|
|
---
|
|
|
|
## 🧮 XP / Level Curve Example
|
|
|
|
| Level | XP Needed (example) | XP Delta | Notes |
|
|
| ----- | ------------------- | -------- | ----------------- |
|
|
| 1 | 0 | — | Starting level |
|
|
| 2 | 100 | +100 | Fast early growth |
|
|
| 5 | 625 | +175 | Moderate |
|
|
| 10 | 2500 | +350 | Midgame plateau |
|
|
| 20 | 10000 | +750 | Late-game scaling |
|
|
|
|
*(Values may differ depending on `level_progression.py` formula)*
|
|
|
|
---
|
|
|
|
## ⚙️ API Integration
|
|
|
|
### Blueprint: `char.py`
|
|
|
|
Handles player-facing endpoints such as:
|
|
|
|
* `POST /char/create` → build entity from race + profession
|
|
* `POST /char/level` → level up existing entity and add new skills
|
|
* `GET /char/:id` → return current character stats, XP, and skills
|
|
|
|
Example:
|
|
|
|
```python
|
|
@char_bp.route("/create", methods=["POST"])
|
|
def create_character():
|
|
data = request.json
|
|
entity = build_entity(data["race"], data["profession"])
|
|
return jsonify(entity.to_dict())
|
|
```
|
|
|
|
---
|
|
|
|
## 📁 Data Flow Summary
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[API Request] --> B[char.py Blueprint]
|
|
B --> C[entity_factory.build_entity()]
|
|
C --> D[races_loader / profession_loader]
|
|
C --> E[level_progression]
|
|
C --> F[abilities_factory]
|
|
F --> G[ability_paths.yaml]
|
|
C --> H[Entity Model]
|
|
H --> I[API Response JSON]
|
|
```
|
|
|
|
---
|
|
|
|
## 🧾 Design Notes
|
|
|
|
* All YAML templates are static assets — easy to edit without code changes.
|
|
* Procedural factories (`abilities_factory`, `entity_factory`) ensure deterministic generation for the same input.
|
|
* Systems (`leveling.py`) handle simulation and logic, isolated from API routes.
|
|
* `utils/catalogs` may eventually cache or precompute available skills, professions, and races for faster response times.
|
|
* The entire pipeline can operate **statelessly** inside Flask routes or **persisted** in a database later.
|
|
|
|
---
|
|
|
|
## 🔮 Future Ideas
|
|
|
|
* Add **passive traits** per race or profession.
|
|
* Implement **rarity** or **tiered skills** (common → legendary).
|
|
* Generate **enemy entities** using the same system with difficulty scaling.
|
|
* Add a **training system** or **skill mastery** mechanic tied to XP.
|
|
* Create **hero_catalog.py** entries for pre-built templates used in story mode.
|
|
|