import unittest from terrarium.large_world import generate_large_world from terrarium.neural_schema import NEURAL_ACTION_SCHEMA_VERSION, NEURAL_OPTIONS from terrarium.option_controller import ( OPTION_RESOLUTION_SCHEMA_VERSION, apply_resolution_step, option_scores_from_context, resolve_option, ) class OptionControllerTest(unittest.TestCase): def test_all_neural_options_resolve_without_direct_coordinates(self): world = generate_large_world(seed=515) position = tuple(world["creature_spawn"]) for option in NEURAL_OPTIONS: resolution = resolve_option( option, world, position, user_position=tuple(world["user_spawn"]), resources={"hunger": 0.45, "energy": 0.7, "fear": 0.2}, temperament={"careful": 0.5, "playful": 0.4, "social": 0.4, "curious": 0.6}, slow_steering={ "directive": {"mode": "inspect", "strength": 0.6, "urgency": 0.3}, "option_priors": {"inspect_novelty": 0.2}, }, ) self.assertEqual(resolution["schema_version"], OPTION_RESOLUTION_SCHEMA_VERSION) self.assertEqual(resolution["action_schema_version"], NEURAL_ACTION_SCHEMA_VERSION) self.assertEqual(resolution["option"], option) self.assertNotIn("coordinates", resolution) self.assertNotIn("resource_mutation", resolution) self.assertNotIn("direct_logits", resolution) def test_unsafe_user_approach_is_refused_by_controller(self): world = generate_large_world(seed=616) creature = tuple(world["creature_spawn"]) user = tuple(world["user_spawn"]) x0, y0 = creature x1, y1 = user for x in range(min(x0, x1), max(x0, x1) + 1): world["terrain"][y0][x] = "hazard" for y in range(min(y0, y1), max(y0, y1) + 1): world["terrain"][y][x1] = "hazard" world["terrain"][y0][x0] = "open" world["terrain"][y1][x1] = "open" resolution = resolve_option( "approach_user", world, creature, user_position=user, resources={"hunger": 0.2, "energy": 0.8, "fear": 0.1}, temperament={"careful": 0.9, "social": 0.7}, ) self.assertEqual(resolution["primitive_action"], "wait") self.assertEqual(resolution["arbiter_override"], "unsafe_user_approach") def test_resolution_step_moves_only_for_passable_move_actions(self): world = generate_large_world(seed=717) position = tuple(world["creature_spawn"]) resolution = resolve_option("explore_frontier", world, position, visited={position}) next_position = apply_resolution_step(world, position, resolution) if resolution["primitive_action"].startswith("move_"): self.assertNotEqual(next_position, position) else: self.assertEqual(next_position, position) x, y = next_position self.assertNotEqual(world["terrain"][y][x], "wall") def test_option_scores_reflect_temperament_memory_and_slow_steering(self): world = generate_large_world(seed=818) position = tuple(world["creature_spawn"]) careful = option_scores_from_context( world, position, user_position=tuple(world["user_spawn"]), resources={"hunger": 0.3, "energy": 0.8, "fear": 0.2}, temperament={"careful": 0.9, "playful": 0.1, "social": 0.2, "curious": 0.4}, memory={"negative_pull": 0.7}, ) playful = option_scores_from_context( world, position, user_position=tuple(world["user_spawn"]), resources={"hunger": 0.3, "energy": 0.8, "fear": 0.2}, temperament={"careful": 0.1, "playful": 0.9, "social": 0.8, "curious": 0.4}, memory={"negative_pull": 0.0}, slow_steering={"directive": {"mode": "approach_user", "strength": 0.6}}, ) self.assertGreater(careful["avoid_or_retreat"], playful["avoid_or_retreat"]) self.assertGreater(playful["approach_user"], careful["approach_user"]) self.assertGreater(playful["follow_slow_directive"], careful["follow_slow_directive"]) if __name__ == "__main__": unittest.main()