feat: Add mcrfpy.step() and synchronous screenshot for headless mode (closes #153)

Implements Python-controlled simulation advancement for headless mode:

- Add mcrfpy.step(dt) to advance simulation by dt seconds
- step(None) advances to next scheduled event (timer/animation)
- Timers use simulation_time in headless mode for deterministic behavior
- automation.screenshot() now renders synchronously in headless mode
  (captures current state, not previous frame)

This enables LLM agent orchestration (#156) by allowing:
- Set perspective, take screenshot, query LLM - all synchronous
- Deterministic simulation control without frame timing issues
- Event-driven advancement with step(None)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
John McCardle 2025-12-01 21:56:47 -05:00
commit 60ffa68d04
7 changed files with 409 additions and 10 deletions

View file

@ -110,6 +110,10 @@ private:
bool headless = false;
McRogueFaceConfig config;
bool cleaned_up = false;
// #153 - Headless simulation control
int simulation_time = 0; // Simulated time in milliseconds (for headless mode)
bool simulation_clock_paused = false; // True when simulation is paused (waiting for step())
// Window state tracking
bool vsync_enabled = false;
@ -189,6 +193,11 @@ public:
std::string getViewportModeString() const;
sf::Vector2f windowToGameCoords(const sf::Vector2f& windowPos) const;
// #153 - Headless simulation control
float step(float dt = -1.0f); // Advance simulation; dt<0 means advance to next event
int getSimulationTime() const { return simulation_time; }
void renderScene(); // Force render current scene (for synchronous screenshot)
// global textures for scripts to access
std::vector<IndexTexture> textures;