feat: implement core D&D helpers logic and system architecture
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from src.llm.models import CharacterStateUpdate
|
||||
|
||||
DATA_CHARS_DIR = Path("data/chars")
|
||||
|
||||
|
||||
def ensure_chars_dir():
|
||||
"""Ensures the character data directory exists."""
|
||||
DATA_CHARS_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def get_character_state(character_name: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Reads character state from a JSON file.
|
||||
If the character doesn't exist, returns a default state.
|
||||
"""
|
||||
ensure_chars_dir()
|
||||
file_path = DATA_CHARS_DIR / f"{character_name}.json"
|
||||
|
||||
if not file_path.exists():
|
||||
return {
|
||||
"character_name": character_name,
|
||||
"stats": {"hp": 0, "max_hp": 0, "ac": 0},
|
||||
"status_effects": [],
|
||||
"inventory": [],
|
||||
}
|
||||
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def update_character_state(update: CharacterStateUpdate):
|
||||
"""
|
||||
Updates character state based on a CharacterStateUpdate model.
|
||||
Reads the current state, applies changes, and writes it back.
|
||||
"""
|
||||
ensure_chars_dir()
|
||||
|
||||
state = get_character_state(update.character_name)
|
||||
|
||||
# Update HP
|
||||
if update.hp_change is not None:
|
||||
current_hp = state.get("stats", {}).get("hp", 0)
|
||||
state["stats"]["hp"] = current_hp + update.hp_change
|
||||
|
||||
# Update Status Effects
|
||||
status_effects = set(state.get("status_effects", []))
|
||||
for effect in update.status_effects_added:
|
||||
status_effects.add(effect)
|
||||
for effect in update.status_effects_removed:
|
||||
status_effects.discard(effect)
|
||||
state["status_effects"] = list(status_effects)
|
||||
|
||||
# Update Inventory
|
||||
inventory = state.get("inventory", [])
|
||||
for change in update.inventory_changes:
|
||||
# Find if item already exists
|
||||
item_exists = False
|
||||
for item in inventory:
|
||||
if item["item"] == change.item:
|
||||
if change.action == "added":
|
||||
item["quantity"] = item.get("quantity", 1) + change.quantity
|
||||
elif change.action == "removed":
|
||||
item["quantity"] = max(0, item.get("quantity", 1) - change.quantity)
|
||||
item_exists = True
|
||||
break
|
||||
|
||||
if not item_exists:
|
||||
if change.action == "added":
|
||||
inventory.append(
|
||||
{
|
||||
"item": change.item,
|
||||
"quantity": change.quantity,
|
||||
"weight": 0, # Default weight if not provided
|
||||
}
|
||||
)
|
||||
elif change.action == "removed":
|
||||
# Item not in inventory, do nothing or log
|
||||
pass
|
||||
|
||||
state["inventory"] = inventory
|
||||
|
||||
file_path = DATA_CHARS_DIR / f"{update.character_name}.json"
|
||||
with open(file_path, "w", encoding="utf-8") as f:
|
||||
json.dump(state, f, indent=4)
|
||||
|
||||
return str(file_path)
|
||||
Reference in New Issue
Block a user