Initial commit — Venice of Wasteland sim engine B1-B5
This commit is contained in:
@@ -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)
|
||||
Reference in New Issue
Block a user