irregular6612 commited on
Commit
2e77940
·
1 Parent(s): 2aee482

feat(scenario): render_frame hook — compact pack_evade obs, predator_evade unchanged

Browse files
proteus/grid/scenario.py CHANGED
@@ -209,6 +209,16 @@ class Scenario(ABC):
209
  """
210
  raise NotImplementedError
211
 
 
 
 
 
 
 
 
 
 
 
212
  def record_focal_move(self, action: str) -> None:
213
  """Record the focal's last committed move (no-op by default).
214
 
 
209
  """
210
  raise NotImplementedError
211
 
212
+ def render_frame(self, game: MotiveGridGame) -> str:
213
+ """Render the live grid for the observation (default: full ASCII).
214
+
215
+ Scenarios on small grids inherit the ASCII map. Large open-field
216
+ scenarios override this with a compact textual state so the observation
217
+ is not a several-thousand-character grid.
218
+ """
219
+ from proteus.grid.ascii_view import frame_to_ascii
220
+ return frame_to_ascii(game.current_grid(), self.legend())
221
+
222
  def record_focal_move(self, action: str) -> None:
223
  """Record the focal's last committed move (no-op by default).
224
 
proteus/runtime/_session_core.py CHANGED
@@ -72,8 +72,8 @@ def grid_to_list(grid: np.ndarray) -> list[list[int]]:
72
 
73
 
74
  def render_ascii(scenario: Scenario, game: MotiveGridGame) -> str:
75
- """Render the live grid as ASCII (the SessionRunner._render extraction)."""
76
- return frame_to_ascii(game.current_grid(), scenario.legend())
77
 
78
 
79
  def build_session(
 
72
 
73
 
74
  def render_ascii(scenario: Scenario, game: MotiveGridGame) -> str:
75
+ """Render the live grid for the trace/observation via the scenario's hook."""
76
+ return scenario.render_frame(game)
77
 
78
 
79
  def build_session(
tests/grid/test_pack_evade_observation.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """pack_evade emits a compact coordinate frame; predator_evade keeps its exact
2
+ ASCII frame (so its existing observation/cut-frame tests stay green)."""
3
+ from __future__ import annotations
4
+
5
+ import random
6
+
7
+ import proteus.grid # noqa: F401
8
+ from proteus.grid.ascii_view import frame_to_ascii
9
+ from proteus.grid.difficulty import Difficulty
10
+ from proteus.grid.game import MotiveGridGame
11
+ from proteus.grid.scenario import get_scenario
12
+
13
+
14
+ def test_predator_evade_render_frame_is_unchanged_ascii():
15
+ scenario = get_scenario("predator_evade")()
16
+ game = MotiveGridGame(scenario, random.Random(42), Difficulty.EASY, max_steps=10)
17
+ assert scenario.render_frame(game) == frame_to_ascii(game.current_grid(), scenario.legend())
18
+
19
+
20
+ def test_pack_evade_render_frame_is_compact():
21
+ scenario = get_scenario("pack_evade")()
22
+ game = MotiveGridGame(scenario, random.Random(42), Difficulty.EASY, max_steps=10)
23
+ frame = scenario.render_frame(game)
24
+ assert "Open field 64x64" in frame
25
+ assert "\n" not in frame # one compact line, not a 64-row map
26
+ assert len(frame) < 200 # nowhere near 4096 chars