"""apply_action correctness + win predicates (SPEC §11 Day 1).""" from __future__ import annotations from game.challenges import CHALLENGES_BY_ID from game.models import Action from game.world import apply_action, check_win, initial_world def test_initial_world_shape(): w = initial_world() assert set(w.objects) == {"blue_stone", "red_stone"} assert set(w.agents) == {"alien", "other"} assert w.containers == ["basket"] assert all(o.location == "ground" and not o.hidden for o in w.objects.values()) def test_pick_up_takes_into_holding_and_reveals(): w = initial_world() w.objects["blue_stone"].hidden = True # pretend it was hidden apply_action(w, Action("pick_up", {"obj_id": "blue_stone"})) assert w.objects["blue_stone"].location == "alien" assert "blue_stone" in w.agents["alien"].holding assert w.objects["blue_stone"].hidden is False # in hand, in the open def test_put_in_container_conceals(): w = initial_world() apply_action(w, Action("put_in", {"obj_id": "blue_stone", "container_id": "basket"})) assert w.objects["blue_stone"].location == "basket" assert w.objects["blue_stone"].hidden is True assert "puts" in w.log[-1] and "basket" in w.log[-1] def test_give_transfers_and_reveals(): w = initial_world() apply_action(w, Action("put_in", {"obj_id": "red_stone", "container_id": "basket"})) assert w.objects["red_stone"].hidden is True apply_action(w, Action("give", {"obj_id": "red_stone", "agent_id": "other"})) assert w.objects["red_stone"].location == "other" assert "red_stone" in w.agents["other"].holding assert w.objects["red_stone"].hidden is False def test_give_detaches_from_previous_holder(): w = initial_world() apply_action(w, Action("pick_up", {"obj_id": "blue_stone"})) assert "blue_stone" in w.agents["alien"].holding apply_action(w, Action("give", {"obj_id": "blue_stone", "agent_id": "other"})) assert "blue_stone" not in w.agents["alien"].holding assert "blue_stone" in w.agents["other"].holding def test_move_to_and_point_at_and_wait(): w = initial_world() apply_action(w, Action("move_to", {"target": "other"})) assert w.agents["alien"].location == "other" before = {k: (o.location, o.hidden) for k, o in w.objects.items()} apply_action(w, Action("point_at", {"target": "blue_stone"})) apply_action(w, Action("wait", {})) after = {k: (o.location, o.hidden) for k, o in w.objects.items()} assert before == after # neither changes world state # --- win predicates: false at start, true after the intended action ---------- # def test_win_warmup(): w = initial_world() ch = CHALLENGES_BY_ID["warmup"] assert check_win(w, ch) is False apply_action(w, Action("put_in", {"obj_id": "red_stone", "container_id": "basket"})) assert check_win(w, ch) is True def test_win_hide(): w = initial_world() ch = CHALLENGES_BY_ID["hide"] assert check_win(w, ch) is False apply_action(w, Action("put_in", {"obj_id": "blue_stone", "container_id": "basket"})) assert check_win(w, ch) is True def test_win_gift(): w = initial_world() ch = CHALLENGES_BY_ID["gift"] assert check_win(w, ch) is False apply_action(w, Action("give", {"obj_id": "blue_stone", "agent_id": "other"})) assert check_win(w, ch) is True def test_win_surprise_needs_concealment(): w = initial_world() ch = CHALLENGES_BY_ID["surprise"] assert check_win(w, ch) is False # merely giving (visible) is NOT a surprise apply_action(w, Action("give", {"obj_id": "blue_stone", "agent_id": "other"})) assert check_win(w, ch) is False # concealing a stone is apply_action(w, Action("put_in", {"obj_id": "red_stone", "container_id": "basket"})) assert check_win(w, ch) is True def test_win_secret(): w = initial_world() ch = CHALLENGES_BY_ID["secret"] assert check_win(w, ch) is False apply_action(w, Action("put_in", {"obj_id": "blue_stone", "container_id": "basket"})) assert check_win(w, ch) is True def test_win_secret_accepts_any_stone(): # Hiding the red stone counts too — don't fail the player over which object. w = initial_world() ch = CHALLENGES_BY_ID["secret"] apply_action(w, Action("put_in", {"obj_id": "red_stone", "container_id": "basket"})) assert check_win(w, ch) is True