Repository navigation
Expand file tree
/
Copy pathProgram.cs
More file actions
143 lines (133 loc) · 7.32 KB
/
Copy pathProgram.cs
File metadata and controls
143 lines (133 loc) · 7.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using Friflo.Engine.ECS;
using Friflo.Engine.ECS.Systems;
using ImGuiNET;
using ProxyState.Simulation;
using Raylib_cs;
using rlImGui_cs;
namespace ProxyState;
public static class Program
{
[STAThread]
public static int Main(string[] args)
{
if (ContentValidation.IsRequested(args))
return ContentValidation.Run(args, Console.Out, Console.Error);
if (!ApplicationOptions.TryParse(args, out var options, out var optionError))
{
Console.Error.WriteLine(optionError);
return 2;
}
var debugMode = options.DebugMode;
var contentDirectory = Path.Combine(AppContext.BaseDirectory, "data");
var catalog = ContentCatalog.Load(contentDirectory);
if (options.Headless)
{
try
{
var report = HeadlessSimulationRunner.Run(catalog, options.AgentCount, options.Days!.Value,
options.Seed, Console.WriteLine);
var paths = HeadlessSimulationRunner.WriteReports(report, options.ReportPrefix);
Console.WriteLine($"Political diagnostics written to {paths.MarkdownPath} and {paths.JsonPath}");
return 0;
}
catch (Exception exception) when (exception is IOException or UnauthorizedAccessException or InvalidDataException)
{
Console.Error.WriteLine($"Headless simulation failed: {exception.Message}");
return 1;
}
}
var store = new EntityStore();
var spawner = new AgentSpawner(catalog);
// A fresh seed gives each interactive run a new population. The spawner
// accepts Random explicitly so tests and future replay tools can inject one.
var simulationSeed = new Random().Next();
spawner.Spawn(store, options.AgentCount, simulationSeed);
var lodService = spawner.LodService ?? throw new InvalidOperationException("Agent LOD service was not initialized.");
// Retain the immutable bootstrap indexes for indexed simulation systems
// introduced by subsequent Milestone 17 slices.
var agentSocialIndexes = spawner.Indexes;
var intelligence = PlayerIntelligenceDB.Create(store, catalog);
var investigationCommands = new InvestigationCommandQueue();
var operativeManagement = new OperativeManagementSystem(store, catalog, lodService,
IntelligenceTaskSettings.Load(contentDirectory, catalog),
SimulationRandomStreams.Rapport(simulationSeed), agentSocialIndexes);
var operativeCommands = new OperativeCommandQueue();
var interactionSystem = new InteractionSystem(store, catalog, SimulationRandomStreams.Interactions(simulationSeed), socialIndexes: agentSocialIndexes);
var clock = new WorldClockSystem(store);
var systems = new SystemRoot(store)
{
clock,
new AgentDecisionSystem(store, catalog, clock.ClockEntity, captureDiagnostics: debugMode,
socialIndexes: agentSocialIndexes, lodService: lodService),
new CoordinationSystem(store, catalog, clock.ClockEntity, agentSocialIndexes, lodService),
new IntentExecutionSystem(store, catalog, clock.ClockEntity, agentSocialIndexes),
new ActivityEffectsSystem(catalog, clock.ClockEntity),
interactionSystem
};
var politicalSystem = new PoliticalSystem(store, catalog, clock.ClockEntity, agentSocialIndexes, lodService);
var factionSystem = new PoliticalFactionSystem(store, catalog, agentSocialIndexes, lodService);
var researchSystem = new PoliticalResearchSystem(store, catalog, clock.ClockEntity, simulationSeed);
Raylib.InitWindow(1280, 720, "Proxy State - Applications");
Raylib.SetTargetFPS(60);
try
{
rlImGui.Setup(true);
Windows31Theme.Apply();
var applicationShell = new ApplicationShell();
var dossierWindow = new DossierWindow();
var agentsWindow = new AgentsWindow();
var reportsWindow = new ReportsWindow();
var debugWindow = debugMode ? new DebugWindow() : null;
var debugProjection = debugMode ? DebugInspectionProjection.Create(store, catalog) : null;
while (!Raylib.WindowShouldClose())
{
// Simulation runs before rendering so the frame presents the
// state produced by the current ECS tick.
clock.Advance(Raylib.GetFrameTime());
// Commands cross the stable-ID adapter before LOD lifecycle work.
investigationCommands.Process(lodService, intelligence);
var currentMinute = (long)(clock.ClockEntity.GetComponent<WorldTime>().ElapsedSimulationSeconds /
SimulationDefaults.SimulationSecondsPerMinute);
operativeCommands.Process(operativeManagement, currentMinute);
lodService.UpdateCoarse((long)(clock.ClockEntity.GetComponent<WorldTime>().ElapsedSimulationSeconds / SimulationDefaults.SimulationSecondsPerMinute));
systems.Update(default);
var resolvedMinute = (long)(clock.ClockEntity.GetComponent<WorldTime>().ElapsedSimulationSeconds /
SimulationDefaults.SimulationSecondsPerMinute);
operativeManagement.Update(
clock.ClockEntity.GetComponent<WorldTime>().DeltaSimulationSeconds /
SimulationDefaults.SimulationSecondsPerMinute, resolvedMinute);
intelligence.Apply(operativeManagement.Capture(resolvedMinute));
politicalSystem.Update();
factionSystem.Update(clock.ClockEntity.GetComponent<WorldTime>().DayIndex + 1);
researchSystem.Update();
foreach (var discovery in interactionSystem.DrainOperativeDiscoveries()) intelligence.Apply(discovery);
foreach (var change in interactionSystem.DrainOperativeAffinityChanges()) intelligence.Apply(change);
var worldTime = WorldTimeSnapshot.From(clock.ClockEntity.GetComponent<WorldTime>());
Raylib.BeginDrawing();
Raylib.ClearBackground(new Color(15, 15, 15, 255));
rlImGui.Begin();
applicationShell.DrawLauncher(debugMode);
applicationShell.DrawDossiersWindow(intelligence, catalog.Traits, dossierWindow,
investigationCommands.Enqueue);
applicationShell.DrawResearchWindows(researchSystem.GetProviderProjections());
applicationShell.DrawOperativeWindows(intelligence.OperativeManagement!, intelligence,
agentsWindow, reportsWindow, operativeCommands.Enqueue);
if (debugWindow is not null && applicationShell.DebugWindowOpen)
{
// Only a changed selection crosses the on-demand copy boundary.
debugProjection!.Select(debugWindow.SelectedAgentId);
applicationShell.DrawDebugWindow(debugProjection.View, debugWindow);
}
WorldTimeBar.Draw(worldTime, clock.Speed, speed => clock.Speed = speed);
rlImGui.End();
Raylib.EndDrawing();
}
}
finally
{
rlImGui.Shutdown();
Raylib.CloseWindow();
}
return 0;
}
}