Initial commit — Venice of Wasteland sim engine B1-B5

This commit is contained in:
Corback
2026-06-15 22:38:35 +00:00
commit 3039961b51
21 changed files with 3130 additions and 0 deletions
+130
View File
@@ -0,0 +1,130 @@
"""
Brique 4 — Équipement / Inventaire
Gestion du poids, consommation d'items, équipement armure/armes.
Carry Weight = 150 + (STR × 10) lbs — Rules Booklet p.12
Consommation nourriture/eau → relie à survival.py (feed/hydrate).
"""
import db
import survival
def get_carry_weight(strength: int) -> int:
# Manuel FR p.52 : 75 + (FOR × 5) kg
return 75 + strength * 5
def get_current_weight(character_id: int, session_id: int) -> float:
items = db.get_inventory(character_id, session_id)
return sum(i["weight"] * i["quantity"] for i in items)
def is_overencumbered(char: dict) -> bool:
max_w = get_carry_weight(char["strength"])
current_w = get_current_weight(char["id"], char["session_id"])
return current_w > max_w
def consume_food(session_id: int, char_id: int, day: int, tick: int,
item_slug: str) -> dict:
"""
Consomme 1 unité de nourriture depuis l'inventaire.
Retourne {"ok": bool, "reason": str, "effect": dict}
"""
items = db.get_inventory(char_id, session_id)
item = next((i for i in items if i["item_slug"] == item_slug and i["item_type"] == "food"), None)
if not item:
return {"ok": False, "reason": f"Item '{item_slug}' absent de l'inventaire"}
if item["quantity"] < 1:
return {"ok": False, "reason": "Quantité insuffisante"}
# Type de nourriture : cooked si hp_heal >= 7 (nourriture cuisinée), soup si slug contient 'soupe'
food_type = "normal"
if "soupe" in item_slug or "bouillon" in item_slug:
food_type = "soup"
elif item.get("hp_heal", 0) >= 7:
food_type = "cooked"
db.remove_item(char_id, session_id, item_slug, 1)
survival.feed_character(session_id, char_id, day, tick, food_type=food_type)
# Soins PV
hp_heal = item.get("hp_heal", 0)
if hp_heal > 0:
chars = [c for c in db.get_characters(session_id) if c["id"] == char_id]
if chars:
char = chars[0]
new_hp = min(char["max_hp"], char["hp"] + hp_heal)
db.update_character(char_id, hp=new_hp)
# Radiations
rad_gain = 0
props = item.get("properties") or {}
if isinstance(props, dict) and props.get("irradiated"):
rad_gain = props.get("rad_on_eat", 1)
chars = [c for c in db.get_characters(session_id) if c["id"] == char_id]
if chars:
new_rads = chars[0]["rads"] + rad_gain
db.update_character(char_id, rads=new_rads)
db.log_event(
session_id=session_id, day=day, tick=tick,
event_type="inventaire",
description=f"Consomme {item['item_name']} (food_type={food_type}, +{hp_heal}PV, +{rad_gain}RAD)",
actor_id=char_id,
mechanical_effect={"item": item_slug, "hp_heal": hp_heal, "rad": rad_gain},
)
return {"ok": True, "reason": "ok", "effect": {"hp_heal": hp_heal, "rad_gain": rad_gain, "food_type": food_type}}
def consume_drink(session_id: int, char_id: int, day: int, tick: int,
item_slug: str) -> dict:
"""Consomme 1 boisson depuis l'inventaire."""
items = db.get_inventory(char_id, session_id)
item = next((i for i in items if i["item_slug"] == item_slug and i["item_type"] == "drink"), None)
if not item:
return {"ok": False, "reason": f"Item '{item_slug}' absent de l'inventaire"}
water_type = "purified" if "purifie" in item_slug or "purif" in item_slug else "normal"
db.remove_item(char_id, session_id, item_slug, 1)
survival.hydrate_character(session_id, char_id, day, tick, water_type=water_type)
hp_heal = item.get("hp_heal", 0)
if hp_heal > 0:
chars = [c for c in db.get_characters(session_id) if c["id"] == char_id]
if chars:
new_hp = min(chars[0]["max_hp"], chars[0]["hp"] + hp_heal)
db.update_character(char_id, hp=new_hp)
props = item.get("properties") or {}
rad_gain = 0
if isinstance(props, dict) and props.get("irradiated"):
rad_gain = props.get("rad_on_drink", 1)
chars = [c for c in db.get_characters(session_id) if c["id"] == char_id]
if chars:
db.update_character(char_id, rads=chars[0]["rads"] + rad_gain)
db.log_event(
session_id=session_id, day=day, tick=tick,
event_type="inventaire",
description=f"Boit {item['item_name']} (water_type={water_type}, +{hp_heal}PV, +{rad_gain}RAD)",
actor_id=char_id,
mechanical_effect={"item": item_slug, "hp_heal": hp_heal, "rad": rad_gain},
)
return {"ok": True, "reason": "ok", "effect": {"hp_heal": hp_heal, "rad_gain": rad_gain}}
def inventory_summary(character_id: int, session_id: int, char: dict) -> str:
"""Résumé texte de l'inventaire pour le MJ LLM."""
items = db.get_inventory(character_id, session_id)
max_w = get_carry_weight(char["strength"])
cur_w = sum(i["weight"] * i["quantity"] for i in items)
lines = [f"Inventaire de {char['name']} ({cur_w:.1f}/{max_w} kg)"]
for i in items:
eq = " [ÉQUIPÉ]" if i.get("is_equipped") else ""
lines.append(f" {i['item_name']} ×{i['quantity']} ({i['item_type']}){eq}")
return "\n".join(lines)