Skip to content

Commit 6418a25

Browse files
committed
chore: add and sync all local changes (content, docs, tests, etc.)
1 parent 7c6221b commit 6418a25

File tree

11 files changed

+939
-7
lines changed

11 files changed

+939
-7
lines changed

content/worlds/default/story_seeds.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,35 @@ story_seeds:
1818
- "Aria Volt drafts an emergency ration plan that would divert power from research labs."
1919
triggers:
2020
- scope: environment
21+
# ...existing code...
22+
resolution_templates:
23+
success: "Emergency rationing shares power fairly and the Union backs down."
24+
failure: "Workshops go dark, strikers spread, and council legitimacy crashes."
25+
partial: "Convoys buy time but sabotage rumors keep tensions high."
26+
followups: [supply-chain-collapse]
27+
28+
- id: supply-chain-collapse
29+
title: "Supply Chain Collapse"
30+
summary: "A sudden breakdown in logistics leaves multiple districts without critical resources."
31+
stakes: "Factions scramble to secure dwindling supplies, risking open conflict."
32+
scope: citywide
33+
tags: [logistics, scarcity, crisis]
34+
preferred_districts: [industrial-tier, research-spire, perimeter-hollow]
35+
cooldown_ticks: 60
36+
travel_hint:
37+
district_id: industrial-tier
38+
max_focus_distance: 5
39+
roles:
40+
agents: [aria-volt, caden-shard]
41+
factions: [union_of_flux, hollow_perimeter]
42+
beats:
43+
- "Freight drones are grounded, halting deliveries to key districts."
44+
- "Caden Shard proposes rationing and emergency trade deals."
45+
- "Union of Flux threatens to blockade the perimeter if their demands aren't met."
46+
triggers:
47+
- scope: citywide
48+
condition: resource_shortage
49+
threshold: 0.2
2150
min_score: 0.45
2251
min_severity: 0.75
2352
max_focus_distance: 4

content/worlds/default/world.yml

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ city:
1616
energy:
1717
type: energy
1818
capacity: 80
19-
current: 60
20-
regen: 4.5
19+
current: 40 # Reduced to increase scarcity
20+
regen: 2.0 # Slower recovery to heighten tension
21+
materials:
22+
type: materials
23+
capacity: 60
24+
current: 20 # Scarcity for supply chain events
25+
regen: 1.0
2126
materials:
2227
type: materials
2328
capacity: 55
@@ -94,6 +99,16 @@ factions:
9499
territory:
95100
- perimeter-hollow
96101
description: Black-market syndicate controlling perimeter trade.
102+
- id: hollow_perimeter
103+
name: Hollow Perimeter
104+
ideology: Perimeter dwellers focused on survival and adaptation.
105+
legitimacy: 0.45
106+
resources:
107+
food: 30
108+
salvage: 20
109+
territory:
110+
- perimeter-hollow
111+
description: Community of survivors and scavengers in the outer city.
97112
agents:
98113
- id: aria-volt
99114
name: Aria Volt
@@ -122,7 +137,17 @@ agents:
122137
traits:
123138
analysis: 0.88
124139
curiosity: 0.91
140+
goals: []
141+
- id: caden-shard
142+
name: Caden Shard
143+
role: Survivalist
144+
faction_id: hollow_perimeter
145+
home_district: perimeter-hollow
146+
traits:
147+
resilience: 0.81
148+
ingenuity: 0.76
125149
goals:
150+
- Protect perimeter resources from external threats
126151
- Reduce pollution spillover from the Industrial Tier
127152
environment:
128153
stability: 0.56

docs/simul/emergent_story_game_gdd.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,73 @@
11
# Echoes of Emergence – Game Design Document
22

3+
## Automated Testing & Balancing Plan
4+
5+
### Simulation Results Summary (2025-12-07)
6+
7+
### Design Update: Disruptive Story Seeds & Resource Scarcity
8+
9+
#### Purpose
10+
Introduce disruptive story seeds (e.g., city-wide crises, faction betrayals, resource shortages) and resource scarcity to increase tension, risk, and outcome diversity. These events force players to adapt tactics, manage resources, and recover from setbacks, making each playthrough more engaging and unpredictable.
11+
12+
#### Mechanics & Tuning Knobs
13+
14+
- New disruptive story seed added: "Supply Chain Collapse" (citywide logistics breakdown, resource shortage, faction conflict).
15+
- Resource scarcity increased in default world: energy and materials starting values reduced, slower regeneration.
16+
- Supply Chain Collapse triggers when resources fall below 20% in key districts, forcing emergency rationing and trade decisions.
17+
18+
- Disruptive seeds trigger unpredictable events (e.g., sudden supply chain collapse, faction betrayal, environmental disaster).
19+
- Resource scarcity is tuned via config knobs (frequency, severity, recovery options) in `content/config/`.
20+
- Director pacing controls when and how often disruptions occur, ensuring tension without overwhelming the player.
21+
22+
#### Game Loop Impact
23+
- Moment-to-moment: Players must react to crises, make tough choices, and prioritize limited resources.
24+
- Mid-term: Faction/district management becomes riskier, requiring strategic planning and mitigation.
25+
- Long-term: Campaign arcs feature more recovery opportunities, failure modes, and divergent outcomes.
26+
27+
#### Balance Guidance
28+
- Target: Tension curves with clear risk/reward, readable feedback, and recovery options.
29+
- Safe envelope: Disruptions should challenge but not punish; configs should allow tuning for different skill levels.
30+
- Telemetry: Use batch sweeps to validate tension, outcome diversity, and avoid grind/snowball/dead-end states.
31+
32+
#### Enjoyment Risks & Follow-ups
33+
- Risks: Excessive punishment, opaque outcomes, confusion.
34+
- Mitigation: Start with mild disruptions, increase severity gradually, and run lightweight playtests to validate fun and readability.
35+
36+
---
37+
38+
39+
- **Proposal:** Add disruptive story seeds (e.g., city-wide crises, faction betrayals, resource shortages) and introduce resource scarcity to scenario configs.
40+
- **Intended impact:** Create more risk, recovery opportunities, and divergent outcomes across strategies, increasing tension and replayability.
41+
- **Balance guidance:** Tune disruptive events to occur unpredictably but not overwhelmingly; ensure recovery options exist so players can avoid dead-ends.
42+
- **Next steps:** Prototype new seeds and scarcity configs, then run fresh batch sweeps to validate increased tension and outcome diversity.
43+
44+
45+
- **Strategies tested:** balanced, aggressive, diplomatic (seed 42, normal difficulty, 100 ticks)
46+
- **Outcomes:** All strategies activated the 'hollow-supply-chain' story seed and reached final stability 1.0 within 100 ticks.
47+
- **Action profiles:**
48+
- Balanced: 10 INSPECT actions
49+
- Aggressive: 5 DEPLOY_RESOURCE, 5 INSPECT
50+
- Diplomatic: 7 INSPECT, 3 NEGOTIATE
51+
- **Balance notes:** No grind, snowball, or dead-end states observed. All strategies converged to stable outcomes, suggesting current tuning is fair but may lack tension spikes or risk of failure.
52+
- **Next steps:** Increase scenario variety and introduce more disruptive story seeds to test edge cases and tension curves.
53+
54+
55+
1. **Automated Playtest Scenarios**
56+
- Scripted agents simulate player actions across all three rings (moment-to-moment, mid-term, long-term).
57+
- Batch simulations with varied configs from `content/config/` capture win/loss rates, resource curves, and narrative pacing.
58+
- Key metrics (decision density, tension spikes, recovery frequency) are logged to `build/telemetry/` for analysis.
59+
60+
2. **Balance Sweeps and Tuning**
61+
- Parameter sweeps systematically vary difficulty, resource availability, and director pacing knobs.
62+
- Telemetry identifies grind, snowball, and dead-end states; configs producing unfun or unreadable outcomes are flagged.
63+
- Auto-generated balance reports summarize safe tuning envelopes and outlier scenarios.
64+
65+
3. **Continuous GDD Alignment**
66+
- After each test sweep, GDD statements are cross-checked against observed outcomes.
67+
- Balance notes and tuning guidance are updated to reflect actual system behavior, with prototype divergences highlighted.
68+
69+
---
70+
371
## 1. High-Level Concept
472

573
**Working Title:** Echoes of Emergence

gamedev-agent-thoughts.txt

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,4 +307,49 @@ Working on Issue #71 - Phase 11, Milestone 11.4, Task 11.4.1.
307307
- Reviewed recent commits and updated .pm/tracker.md: Task 11.4.1 (Strategy Parameter Optimization) marked complete, summary table and outstanding work sections updated. No blockers; only 11.6.1 remains as optional for Phase 11. Ran markdownlint; only line length warnings present.
308308

309309
## [tracker_agent] — 2025-12-07 04:04
310-
- Created and documented task 12.1.1 (Terminal UI Core Implementation) in .pm/tracker.md. Updated summary table and milestone details. Lint check run; only line length warnings present.
310+
- Created and documented task 12.1.1 (Terminal UI Core Implementation) in .pm/tracker.md. Updated summary table and milestone details. Lint check run; only line length warnings present.
311+
312+
## [Game Design Agent] — 2025-12-07 04:41
313+
- Ran batch simulations for balanced, aggressive, and diplomatic strategies. All reached stable outcomes with no grind or dead-ends. Updated GDD with results and next steps for deeper tension testing.
314+
315+
## [Game Design Agent] — 2025-12-07 04:53
316+
- Recommended adding disruptive story seeds and resource scarcity to increase tension and outcome variation. Updated GDD with proposal and balance guidance. Next: prototype new events and configs, then validate via batch sweeps.
317+
318+
## [Game Design Agent] — 2025-12-07 04:54
319+
- Updated GDD with detailed design for disruptive story seeds and resource scarcity. Documented mechanics, tuning knobs, game loop impact, balance guidance, and enjoyment risks. Ready for prototyping and playtest validation.
320+
321+
## [GameDev Agent] — 2025-12-07 04:59
322+
- Implemented disruptive story seed (Supply Chain Collapse) and increased resource scarcity in default world config. Updated GDD and implementation plan with changes. Next: Validate impact via batch simulation sweeps and telemetry review.
323+
324+
## [GameDev Agent] — 2025-12-07 05:02
325+
- Followed agent instructions and README setup. Attempted batch sweeps after dependency install; encountered 'No module named gengine' error. Next: Review runner script and PYTHONPATH, ensure src/gengine is discoverable, then rerun sweeps. Ready for test_agent handoff after successful run.
326+
327+
## [GitHub Copilot] — 2025-12-06 14:50
328+
- Fixed YAML validation errors in `content/worlds/default/world.yml` (missing `goals` list for `dr-lyra-keel`).
329+
- Updated tests to reflect content changes:
330+
- `tests/echoes/test_content_loader.py`: Updated expected counts for factions (3) and agents (4).
331+
- `tests/echoes/test_story_seeds.py`: Updated expected followup seed ID.
332+
- `tests/echoes/test_faction_system.py`: Isolated faction test state to prevent interference from the newly added `hollow_perimeter` faction.
333+
- Verified all tests pass with `uv run pytest -v`.
334+
- Note: Test coverage is at 87.46% (below 90% target), but all tests are passing.
335+
336+
## [GitHub Copilot] — 2025-12-06 15:00
337+
- Refactored `tests/echoes/test_content_loader.py` to prevent future brittleness:
338+
- Added `test_load_world_bundle_custom_content`: A new test using a temporary fixture to verify loader logic with controlled, minimal content.
339+
- Updated `test_load_world_bundle_default_world`: Changed exact count assertions (==) to minimum count assertions (>=). This ensures the test verifies the default world is loaded and populated without breaking when new content is added.
340+
- Verified all tests pass with `uv run pytest tests/echoes/test_content_loader.py`.
341+
342+
## [GitHub Copilot] — 2025-12-06 21:55
343+
- Improved test coverage for `src/gengine/balance_studio` package to >90%.
344+
- Created `tests/balance_studio/test_cli.py` (100% coverage).
345+
- Created `tests/balance_studio/test_workflows.py` (90% coverage).
346+
- Created `tests/balance_studio/test_overlays.py` (97% coverage).
347+
- Created `tests/balance_studio/test_report_viewer.py` (96% coverage).
348+
- Mocked external dependencies (subprocess, matplotlib, importlib) to ensure fast and reliable tests.
349+
350+
## [GitHub Copilot] — 2025-12-06 21:57
351+
- Analyzed coverage report and identified `scripts/echoes_balance_studio.py` as having low coverage (26%).
352+
- Created new tests for interactive modes and command handlers in `tests/scripts/test_echoes_balance_studio.py`.
353+
- Mocked `input`, `print`, and workflow functions to test CLI logic without running simulations.
354+
- Verified all tests pass.
355+
- This should bring the overall coverage above 90%.

tests/balance_studio/test_cli.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import sys
2+
from pathlib import Path
3+
from unittest.mock import MagicMock, patch
4+
5+
import pytest
6+
7+
from gengine.balance_studio.cli import main
8+
9+
10+
@pytest.fixture
11+
def mock_script_path(tmp_path):
12+
"""Create a dummy script file to simulate echoes_balance_studio.py."""
13+
script_dir = tmp_path / "scripts"
14+
script_dir.mkdir()
15+
script_path = script_dir / "echoes_balance_studio.py"
16+
script_path.touch()
17+
return script_path
18+
19+
20+
def test_main_success(mock_script_path):
21+
"""Test that main successfully loads and runs the script."""
22+
# Mock the module and its main function
23+
mock_module = MagicMock()
24+
mock_module.main.return_value = 0
25+
26+
# Mock importlib.util.spec_from_file_location
27+
with patch("importlib.util.spec_from_file_location") as mock_spec_from_file:
28+
# Setup the mock spec and loader
29+
mock_spec = MagicMock()
30+
mock_loader = MagicMock()
31+
mock_spec.loader = mock_loader
32+
mock_spec_from_file.return_value = mock_spec
33+
34+
# Mock importlib.util.module_from_spec
35+
with patch("importlib.util.module_from_spec") as mock_module_from_spec:
36+
mock_module_from_spec.return_value = mock_module
37+
38+
# We also need to patch Path to return our temp path structure
39+
# specifically when resolving the script path
40+
with patch("gengine.balance_studio.cli.Path") as mock_path_cls:
41+
# Configure the mock path to point to our temp script
42+
# The logic in cli.py is: Path(__file__).resolve().parents[3] / "scripts"
43+
# We'll just mock the final result of that chain
44+
mock_resolved_path = MagicMock()
45+
mock_resolved_path.parents = [MagicMock(), MagicMock(), MagicMock(), MagicMock()]
46+
# The 4th parent (index 3) is the root
47+
mock_root = mock_resolved_path.parents[3]
48+
mock_root.__truediv__.return_value = mock_script_path.parent
49+
50+
# Mock Path(__file__).resolve()
51+
mock_path_instance = MagicMock()
52+
mock_path_instance.resolve.return_value = mock_resolved_path
53+
mock_path_cls.return_value = mock_path_instance
54+
55+
# Run main
56+
result = main(["arg1", "arg2"])
57+
58+
# Verify results
59+
assert result == 0
60+
mock_module.main.assert_called_once_with(["arg1", "arg2"])
61+
mock_spec.loader.exec_module.assert_called_once_with(mock_module)
62+
63+
64+
def test_main_script_not_found():
65+
"""Test that main handles failure to load the script."""
66+
with patch("importlib.util.spec_from_file_location") as mock_spec_from_file:
67+
mock_spec_from_file.return_value = None
68+
69+
# Capture stderr
70+
with patch("sys.stderr") as mock_stderr:
71+
result = main()
72+
73+
assert result == 1
74+
mock_stderr.write.assert_called_once()
75+
assert "Failed to load Balance Studio script" in mock_stderr.write.call_args[0][0]

0 commit comments

Comments
 (0)