Compare commits

..

1 Commits

Author SHA1 Message Date
Alexander Whitestone
8cdae49f48 fix(#553): eliminate hardcoded home-directory paths in Phase-6 infrastructure scripts
Some checks failed
Agent PR Gate / gate (pull_request) Failing after 1m2s
Self-Healing Smoke / self-healing-smoke (pull_request) Failing after 27s
Smoke Test / smoke (pull_request) Failing after 28s
Agent PR Gate / report (pull_request) Successful in 12s
Migrates hardcoded ~/.timmy, ~/.config, and Path.home() references across
the autonomous infrastructure stack to use environment variables with
sensible defaults:

- scripts/autonomous_issue_creator.py:
  - DEFAULT_TOKEN_FILE → XDG_CONFIG_HOME fallback
  - DEFAULT_FAILOVER_STATUS → TIMMY_HOME fallback

- scripts/failover_monitor.py:
  - STATUS_FILE → TIMMY_HOME fallback

- scripts/dynamic_dispatch_optimizer.py:
  - STATUS_FILE, SPEC_FILE, OUTPUT_FILE → TIMMY_HOME fallback

- scripts/backlog_cleanup.py:
  - token path → XDG_CONFIG_HOME fallback

- scripts/backlog_triage.py:
  - TOKEN_PATH → XDG_CONFIG_HOME fallback

- scripts/burn_lane_issue_audit.py:
  - DEFAULT_TOKEN_PATH → XDG_CONFIG_HOME fallback

- scripts/cross-repo-qa.py:
  - GITEA_TOKEN_PATH → XDG_CONFIG_HOME fallback

This makes the Phase-6 buildings (self-healing fleet, autonomous issue
creation, community pipeline, global mesh) portable across different
user accounts and deployment environments.
2026-04-22 03:05:16 -04:00
11 changed files with 69 additions and 242 deletions

View File

@@ -285,24 +285,25 @@ class World:
self.state.pop("phase_transition_event", None)
# Natural energy decay: the world is exhausting
self.state.pop("energy_collapse_event", None)
for char_name, char in self.characters.items():
char["energy"] = max(0, char["energy"] - 0.3)
# Check for energy collapse
if char["energy"] <= 0:
current = char.get("room", "Threshold")
next_rooms = [room for room in self.rooms.keys() if room != current]
new_room = random.choice(next_rooms) if next_rooms else current
char["energy"] = 2 # Wake up with some energy
char["room"] = new_room
# Timmy collapse gets special narrative treatment
if char.get("is_player", False):
char["memories"].append("Collapsed from exhaustion.")
self.state["energy_collapse_event"] = {
"character": char_name,
"from_room": current,
"to_room": new_room,
}
char["energy"] = 2 # Wake up with some energy
# Random room change (scattered)
rooms = list(self.rooms.keys())
current = char.get("room", "Threshold")
new_room = current
attempts = 0
while new_room == current and attempts < 10:
import random as _r
new_room = _r.choice(rooms)
attempts += 1
if new_room != current:
char["room"] = new_room
# Forge fire naturally dims if not tended
# Phase-aware: Breaking phase has higher fire-death chance
@@ -1093,21 +1094,7 @@ class GameEngine:
}
# Process Timmy's action
room_name = self.world.characters["Timmy"]["room"]
timmy_energy = self.world.characters["Timmy"]["energy"]
collapse_event = self.world.state.pop("energy_collapse_event", None)
if collapse_event and collapse_event.get("character") == "Timmy":
room_name = self.world.characters["Timmy"]["room"]
scene["timmy_room"] = room_name
scene["timmy_energy"] = self.world.characters["Timmy"]["energy"]
scene["room_desc"] = self.world.get_room_desc(room_name, "Timmy")
here = [n for n in self.world.characters if self.world.characters[n]["room"] == room_name and n != "Timmy"]
scene["here"] = here
scene["log"].append("You collapse from exhaustion. The world spins. You wake somewhere else.")
if collapse_event.get("from_room") != collapse_event.get("to_room"):
scene["log"].append(f"You are in The {collapse_event['to_room']}, disoriented.")
return scene
# Energy constraint checks
action_costs = {
@@ -1170,7 +1157,7 @@ class GameEngine:
if direction in connections:
dest = connections[direction]
self.world.characters["Timmy"]["room"] = dest
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You move {direction} to The {dest}.")
scene["timmy_room"] = dest
@@ -1278,7 +1265,7 @@ class GameEngine:
self.world.characters["Timmy"]["trust"]["Kimi"] = min(1.0,
self.world.characters["Timmy"]["trust"].get("Kimi", 0) + 0.1)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 0
else:
scene["log"].append(f"{target} is not in this room.")
@@ -1315,7 +1302,7 @@ class GameEngine:
if self.world.characters["Timmy"]["room"] == "Forge":
self.world.rooms["Forge"]["fire"] = "glowing"
self.world.rooms["Forge"]["fire_tended"] += 1
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 2
scene["log"].append("You tend the forge fire. The flames leap up, bright and hungry.")
self.world.state["forge_fire_dying"] = False
else:
@@ -1337,7 +1324,7 @@ class GameEngine:
]
new_rule = random.choice(rules)
self.world.rooms["Tower"]["messages"].append(new_rule)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You write on the Tower whiteboard: \"{new_rule}\"")
else:
scene["log"].append("You are not in the Tower.")
@@ -1356,7 +1343,7 @@ class GameEngine:
new_carving = random.choice(carvings)
if new_carving not in self.world.rooms["Bridge"]["carvings"]:
self.world.rooms["Bridge"]["carvings"].append(new_carving)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You carve into the railing: \"{new_carving}\"")
else:
scene["log"].append("You are not on the Bridge.")
@@ -1365,7 +1352,7 @@ class GameEngine:
if self.world.characters["Timmy"]["room"] == "Garden":
self.world.rooms["Garden"]["growth"] = min(5,
self.world.rooms["Garden"]["growth"] + 1)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append("You plant something in the dark soil. The earth takes it without question.")
else:
scene["log"].append("You are not in the Garden.")
@@ -1384,7 +1371,7 @@ class GameEngine:
self.world.characters["Timmy"]["trust"].get(target_name, 0) + 0.2)
self.world.characters[target_name]["trust"]["Timmy"] = min(1.0,
self.world.characters[target_name]["trust"].get("Timmy", 0) + 0.2)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You help {target_name}. They look grateful.")
else:
@@ -1440,9 +1427,6 @@ class GameEngine:
self.world.characters[char_name]["spoken"].append(line)
scene["log"].append(f"{char_name} says: \"{line}\"")
scene["timmy_room"] = self.world.characters["Timmy"]["room"]
scene["timmy_energy"] = self.world.characters["Timmy"]["energy"]
# Save the world
self.world.save()

View File

@@ -203,25 +203,26 @@ class World:
def update_world_state(self):
"""World changes independent of character actions."""
# Natural energy decay: the world is exhausting
self.state.pop("energy_collapse_event", None)
for char_name, char in self.characters.items():
char["energy"] = max(0, char["energy"] - 0.3)
# Check for energy collapse
if char["energy"] <= 0:
current = char.get("room", "Threshold")
next_rooms = [room for room in self.rooms.keys() if room != current]
new_room = random.choice(next_rooms) if next_rooms else current
char["energy"] = 2 # Wake up with some energy
char["room"] = new_room
# Timmy collapse gets special narrative treatment
if char.get("is_player", False):
char["memories"].append("Collapsed from exhaustion.")
self.state["energy_collapse_event"] = {
"character": char_name,
"from_room": current,
"to_room": new_room,
}
char["energy"] = 2 # Wake up with some energy
# Random room change (scattered)
rooms = list(self.rooms.keys())
current = char.get("room", "Threshold")
new_room = current
attempts = 0
while new_room == current and attempts < 10:
new_room = rooms[0] # Will change to random
attempts += 1
if new_room != current:
char["room"] = new_room
# Forge fire naturally dims if not tended
self.state["forge_fire_dying"] = random.random() < 0.1
# Random weather events
@@ -926,21 +927,7 @@ class GameEngine:
}
# Process Timmy's action
room_name = self.world.characters["Timmy"]["room"]
timmy_energy = self.world.characters["Timmy"]["energy"]
collapse_event = self.world.state.pop("energy_collapse_event", None)
if collapse_event and collapse_event.get("character") == "Timmy":
room_name = self.world.characters["Timmy"]["room"]
scene["timmy_room"] = room_name
scene["timmy_energy"] = self.world.characters["Timmy"]["energy"]
scene["room_desc"] = self.world.get_room_desc(room_name, "Timmy")
here = [n for n in self.world.characters if self.world.characters[n]["room"] == room_name and n != "Timmy"]
scene["here"] = here
scene["log"].append("You collapse from exhaustion. The world spins. You wake somewhere else.")
if collapse_event.get("from_room") != collapse_event.get("to_room"):
scene["log"].append(f"You are in The {collapse_event['to_room']}, disoriented.")
return scene
# Energy constraint checks
action_costs = {
@@ -1003,7 +990,7 @@ class GameEngine:
if direction in connections:
dest = connections[direction]
self.world.characters["Timmy"]["room"] = dest
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You move {direction} to The {dest}.")
scene["timmy_room"] = dest
@@ -1105,7 +1092,7 @@ class GameEngine:
self.world.characters["Timmy"]["trust"]["Kimi"] = min(1.0,
self.world.characters["Timmy"]["trust"].get("Kimi", 0) + 0.1)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 0
else:
scene["log"].append(f"{target} is not in this room.")
@@ -1142,7 +1129,7 @@ class GameEngine:
if self.world.characters["Timmy"]["room"] == "Forge":
self.world.rooms["Forge"]["fire"] = "glowing"
self.world.rooms["Forge"]["fire_tended"] += 1
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 2
scene["log"].append("You tend the forge fire. The flames leap up, bright and hungry.")
self.world.state["forge_fire_dying"] = False
else:
@@ -1164,7 +1151,7 @@ class GameEngine:
]
new_rule = random.choice(rules)
self.world.rooms["Tower"]["messages"].append(new_rule)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You write on the Tower whiteboard: \"{new_rule}\"")
else:
scene["log"].append("You are not in the Tower.")
@@ -1183,7 +1170,7 @@ class GameEngine:
new_carving = random.choice(carvings)
if new_carving not in self.world.rooms["Bridge"]["carvings"]:
self.world.rooms["Bridge"]["carvings"].append(new_carving)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You carve into the railing: \"{new_carving}\"")
else:
scene["log"].append("You are not on the Bridge.")
@@ -1192,7 +1179,7 @@ class GameEngine:
if self.world.characters["Timmy"]["room"] == "Garden":
self.world.rooms["Garden"]["growth"] = min(5,
self.world.rooms["Garden"]["growth"] + 1)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append("You plant something in the dark soil. The earth takes it without question.")
else:
scene["log"].append("You are not in the Garden.")
@@ -1211,7 +1198,7 @@ class GameEngine:
self.world.characters["Timmy"]["trust"].get(target_name, 0) + 0.2)
self.world.characters[target_name]["trust"]["Timmy"] = min(1.0,
self.world.characters[target_name]["trust"].get("Timmy", 0) + 0.2)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You help {target_name}. They look grateful.")
else:
@@ -1255,9 +1242,6 @@ class GameEngine:
self.world.characters[char_name]["spoken"].append(line)
scene["log"].append(f'{char_name} says: "{line}"')
scene["timmy_room"] = self.world.characters["Timmy"]["room"]
scene["timmy_energy"] = self.world.characters["Timmy"]["energy"]
# Save the world
self.world.save()

View File

@@ -18,8 +18,8 @@ from urllib import request
DEFAULT_BASE_URL = "https://forge.alexanderwhitestone.com/api/v1"
DEFAULT_OWNER = "Timmy_Foundation"
DEFAULT_REPO = "timmy-home"
DEFAULT_TOKEN_FILE = Path.home() / ".config" / "gitea" / "token"
DEFAULT_FAILOVER_STATUS = Path.home() / ".timmy" / "failover_status.json"
DEFAULT_TOKEN_FILE = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")) / "gitea" / "token"
DEFAULT_FAILOVER_STATUS = Path(os.environ.get("TIMMY_HOME", Path.home() / ".timmy")) / "failover_status.json"
DEFAULT_RESTART_STATE_DIR = Path("/var/lib/timmy/restarts")
DEFAULT_HEARTBEAT_FILE = Path("/var/lib/timmy/heartbeats/fleet_health.last")

View File

@@ -18,7 +18,7 @@ from pathlib import Path
def get_token():
f = Path.home() / ".config" / "gitea" / "token"
f = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")) / "gitea" / "token"
if f.exists():
return f.read_text().strip()
return os.environ.get("GITEA_TOKEN", "")

View File

@@ -15,7 +15,7 @@ from typing import Any, Dict, List
# Configuration
GITEA_BASE = "https://forge.alexanderwhitestone.com/api/v1"
TOKEN_PATH = os.path.expanduser("~/.config/gitea/token")
TOKEN_PATH = os.path.join(os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), "gitea", "token")
ORG = "Timmy_Foundation"
REPO = "timmy-home"

View File

@@ -13,7 +13,7 @@ from urllib.request import Request, urlopen
API_BASE = "https://forge.alexanderwhitestone.com/api/v1"
ORG = "Timmy_Foundation"
DEFAULT_TOKEN_PATH = os.path.expanduser("~/.config/gitea/token")
DEFAULT_TOKEN_PATH = os.path.join(os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), "gitea", "token")
@dataclass(frozen=True)

View File

@@ -27,7 +27,7 @@ from pathlib import Path
import re
GITEA_URL = "https://forge.alexanderwhitestone.com"
GITEA_TOKEN_PATH = Path.home() / ".config" / "gitea" / "token"
GITEA_TOKEN_PATH = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")) / "gitea" / "token"
ORG = "Timmy_Foundation"
REPOS = [

View File

@@ -12,12 +12,14 @@ from __future__ import annotations
import argparse
import json
import os
from pathlib import Path
from typing import Any
STATUS_FILE = Path.home() / ".timmy" / "failover_status.json"
SPEC_FILE = Path.home() / ".timmy" / "fleet_dispatch.json"
OUTPUT_FILE = Path.home() / ".timmy" / "dispatch_plan.json"
TIMMY_HOME = Path(os.environ.get("TIMMY_HOME", Path.home() / ".timmy"))
STATUS_FILE = TIMMY_HOME / "failover_status.json"
SPEC_FILE = TIMMY_HOME / "fleet_dispatch.json"
OUTPUT_FILE = TIMMY_HOME / "dispatch_plan.json"
def load_json(path: Path, default: Any):

View File

@@ -13,7 +13,7 @@ FLEET = {
"bezalel": "167.99.126.228"
}
STATUS_FILE = Path.home() / ".timmy" / "failover_status.json"
STATUS_FILE = Path(os.environ.get("TIMMY_HOME", Path.home() / ".timmy")) / "failover_status.json"
def check_health(host):
try:

View File

@@ -1,127 +0,0 @@
from importlib.util import module_from_spec, spec_from_file_location
from pathlib import Path
import random as std_random
import pytest
ROOT = Path(__file__).resolve().parent.parent
GAME_PATH = ROOT / "evennia" / "timmy_world" / "game.py"
def load_game_module(tmp_path: Path):
spec = spec_from_file_location("evennia_local_world_game_energy", GAME_PATH)
module = module_from_spec(spec)
assert spec.loader is not None
spec.loader.exec_module(module)
module.random.seed(0)
module.WORLD_DIR = tmp_path
module.STATE_FILE = tmp_path / "game_state.json"
module.TIMMY_LOG = tmp_path / "timmy_log.md"
module.WORLD_DIR.mkdir(parents=True, exist_ok=True)
return module
def make_engine(tmp_path: Path):
module = load_game_module(tmp_path)
engine = module.GameEngine()
engine.start_new_game()
return module, engine
def choose_action(module, engine):
energy = engine.world.characters["Timmy"]["energy"]
room = engine.world.characters["Timmy"]["room"]
actions = module.PlayerInterface(engine).get_available_actions()
if energy <= 1 and "rest" in actions:
return "rest"
if room == "Garden" and "speak:Marcus" in actions and energy <= 4.3:
return "speak:Marcus"
if room == "Forge" and "tend_fire" in actions:
return "tend_fire"
if room == "Tower" and "write_rule" in actions:
return "write_rule"
if room == "Bridge" and "carve" in actions:
return "carve"
if room == "Garden" and "plant" in actions:
return "plant"
moves = [action.split(" ->")[0] for action in actions if action.startswith("move:")]
if moves:
return moves[0]
if "look" in actions:
return "look"
return actions[0]
class TestTowerGameEnergyConstraints:
def test_low_energy_blocks_costly_action_without_crashing(self, tmp_path):
module, engine = make_engine(tmp_path)
engine.world.characters["Timmy"]["energy"] = 1
result = engine.run_tick("move:north")
assert any("too exhausted" in line for line in result["log"])
assert engine.world.characters["Timmy"]["room"] == "Threshold"
assert engine.world.characters["Timmy"]["energy"] == pytest.approx(0.7)
def test_tired_move_uses_extra_effort_and_drains_energy(self, tmp_path):
module, engine = make_engine(tmp_path)
engine.world.characters["Timmy"]["energy"] = 3.3
result = engine.run_tick("move:north")
assert any("more effort than usual" in line for line in result["log"])
assert engine.world.characters["Timmy"]["room"] == "Tower"
assert engine.world.characters["Timmy"]["energy"] == pytest.approx(0.0)
assert result["timmy_energy"] == pytest.approx(0.0)
def test_rest_is_meaningful_choice_with_room_specific_recovery(self, tmp_path):
module, garden_engine = make_engine(tmp_path / "garden")
garden_engine.world.characters["Timmy"]["room"] = "Garden"
garden_engine.world.characters["Timmy"]["energy"] = 1.0
garden_result = garden_engine.run_tick("rest")
module, bridge_engine = make_engine(tmp_path / "bridge")
bridge_engine.world.characters["Timmy"]["room"] = "Bridge"
bridge_engine.world.characters["Timmy"]["energy"] = 1.0
bridge_result = bridge_engine.run_tick("rest")
assert any("stone bench" in line for line in garden_result["log"])
assert any("no place to rest" in line.lower() for line in bridge_result["log"])
assert garden_engine.world.characters["Timmy"]["energy"] > bridge_engine.world.characters["Timmy"]["energy"]
def test_marcus_can_provide_energy_relief_when_timmy_is_tired(self, tmp_path):
module, engine = make_engine(tmp_path)
engine.world.characters["Timmy"]["room"] = "Garden"
engine.world.characters["Timmy"]["energy"] = 4.3
result = engine.run_tick("speak:Marcus")
assert any("Marcus offers you food" in line for line in result["log"])
assert engine.world.characters["Timmy"]["energy"] == pytest.approx(5.0)
assert result["timmy_energy"] == pytest.approx(5.0)
def test_energy_collapse_moves_timmy_and_records_memory(self, tmp_path, monkeypatch):
module, engine = make_engine(tmp_path)
engine.world.characters["Timmy"]["energy"] = 0
engine.world.characters["Timmy"]["room"] = "Threshold"
monkeypatch.setattr(std_random, "choice", lambda seq: "Tower")
result = engine.run_tick("look")
assert any("collapse from exhaustion" in line.lower() for line in result["log"])
assert engine.world.characters["Timmy"]["room"] == "Tower"
assert engine.world.characters["Timmy"]["energy"] == 2
assert "Collapsed from exhaustion." in engine.world.characters["Timmy"]["memories"]
def test_intentional_play_reaches_low_energy_within_100_ticks(self, tmp_path):
module, engine = make_engine(tmp_path)
min_energy = engine.world.characters["Timmy"]["energy"]
for _ in range(100):
action = choose_action(module, engine)
engine.run_tick(action)
min_energy = min(min_energy, engine.world.characters["Timmy"]["energy"])
assert min_energy <= 3

View File

@@ -203,25 +203,26 @@ class World:
def update_world_state(self):
"""World changes independent of character actions."""
# Natural energy decay: the world is exhausting
self.state.pop("energy_collapse_event", None)
for char_name, char in self.characters.items():
char["energy"] = max(0, char["energy"] - 0.3)
# Check for energy collapse
if char["energy"] <= 0:
current = char.get("room", "Threshold")
next_rooms = [room for room in self.rooms.keys() if room != current]
new_room = random.choice(next_rooms) if next_rooms else current
char["energy"] = 2 # Wake up with some energy
char["room"] = new_room
# Timmy collapse gets special narrative treatment
if char.get("is_player", False):
char["memories"].append("Collapsed from exhaustion.")
self.state["energy_collapse_event"] = {
"character": char_name,
"from_room": current,
"to_room": new_room,
}
char["energy"] = 2 # Wake up with some energy
# Random room change (scattered)
rooms = list(self.rooms.keys())
current = char.get("room", "Threshold")
new_room = current
attempts = 0
while new_room == current and attempts < 10:
new_room = rooms[0] # Will change to random
attempts += 1
if new_room != current:
char["room"] = new_room
# Forge fire naturally dims if not tended
self.state["forge_fire_dying"] = random.random() < 0.1
# Random weather events
@@ -670,21 +671,7 @@ class GameEngine:
}
# Process Timmy's action
room_name = self.world.characters["Timmy"]["room"]
timmy_energy = self.world.characters["Timmy"]["energy"]
collapse_event = self.world.state.pop("energy_collapse_event", None)
if collapse_event and collapse_event.get("character") == "Timmy":
room_name = self.world.characters["Timmy"]["room"]
scene["timmy_room"] = room_name
scene["timmy_energy"] = self.world.characters["Timmy"]["energy"]
scene["room_desc"] = self.world.get_room_desc(room_name, "Timmy")
here = [n for n in self.world.characters if self.world.characters[n]["room"] == room_name and n != "Timmy"]
scene["here"] = here
scene["log"].append("You collapse from exhaustion. The world spins. You wake somewhere else.")
if collapse_event.get("from_room") != collapse_event.get("to_room"):
scene["log"].append(f"You are in The {collapse_event['to_room']}, disoriented.")
return scene
# Energy constraint checks
action_costs = {
@@ -747,7 +734,7 @@ class GameEngine:
if direction in connections:
dest = connections[direction]
self.world.characters["Timmy"]["room"] = dest
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You move {direction} to The {dest}.")
scene["timmy_room"] = dest
@@ -861,7 +848,7 @@ class GameEngine:
self.world.characters["Timmy"]["trust"]["Kimi"] = min(1.0,
self.world.characters["Timmy"]["trust"].get("Kimi", 0) + 0.1)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 0
else:
scene["log"].append(f"{target} is not in this room.")
@@ -898,7 +885,7 @@ class GameEngine:
if self.world.characters["Timmy"]["room"] == "Forge":
self.world.rooms["Forge"]["fire"] = "glowing"
self.world.rooms["Forge"]["fire_tended"] += 1
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 2
scene["log"].append("You tend the forge fire. The flames leap up, bright and hungry.")
self.world.state["forge_fire_dying"] = False
else:
@@ -927,7 +914,7 @@ class GameEngine:
]
new_rule = random.choice(rules)
self.world.rooms["Tower"]["messages"].append(new_rule)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You write on the Tower whiteboard: \"{new_rule}\"")
else:
scene["log"].append("You are not in the Tower.")
@@ -953,7 +940,7 @@ class GameEngine:
new_carving = random.choice(carvings)
if new_carving not in self.world.rooms["Bridge"]["carvings"]:
self.world.rooms["Bridge"]["carvings"].append(new_carving)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You carve into the railing: \"{new_carving}\"")
else:
scene["log"].append("You are not on the Bridge.")
@@ -962,7 +949,7 @@ class GameEngine:
if self.world.characters["Timmy"]["room"] == "Garden":
self.world.rooms["Garden"]["growth"] = min(5,
self.world.rooms["Garden"]["growth"] + 1)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append("You plant something in the dark soil. The earth takes it without question.")
else:
scene["log"].append("You are not in the Garden.")
@@ -988,7 +975,7 @@ class GameEngine:
self.world.characters["Timmy"]["trust"].get(target_name, 0) + 0.2)
self.world.characters[target_name]["trust"]["Timmy"] = min(1.0,
self.world.characters[target_name]["trust"].get("Timmy", 0) + 0.2)
self.world.characters["Timmy"]["energy"] -= action_cost
self.world.characters["Timmy"]["energy"] -= 1
scene["log"].append(f"You help {target_name}. They look grateful.")
elif timmy_action.startswith("confront:"):
@@ -1089,9 +1076,6 @@ class GameEngine:
self.world.characters[char_name]["spoken"].append(line)
scene["log"].append(f"{char_name} says: \"{line}\"")
scene["timmy_room"] = self.world.characters["Timmy"]["room"]
scene["timmy_energy"] = self.world.characters["Timmy"]["energy"]
# Save the world
self.world.save()