nima1's picture
Publish verified checkpoint and losslessly compressed study evidence
4be6a52 verified
Raw History Blame Contribute Delete
2.11 kB
from dataclasses import replace
import pytest
from stackcraft import engine
from stackcraft.engine import new_game, place
from stackcraft.expert import SearchExpert
from stackcraft.players import observe
def test_expert_never_queries_hidden_sequence(monkeypatch) -> None:
observation = observe(new_game(43))
def forbidden(*args, **kwargs):
raise AssertionError("expert queried hidden future")
monkeypatch.setattr(engine, "piece_at", forbidden)
monkeypatch.setattr(engine, "step", forbidden)
expert = SearchExpert()
values = expert.action_values(observation)
assert set(values) == {action.id for action in observation.legal_actions}
assert expert.choose(observation).action_id == max(values, key=lambda a: values[a])
def test_search_is_independent_of_real_seed_and_turn() -> None:
state = new_game(3)
alternate = replace(state, seed=654123, piece_index=999)
assert SearchExpert().action_values(observe(state)) == SearchExpert().action_values(
observe(alternate)
)
def test_unplaceable_preview_has_declared_penalty() -> None:
state = new_game(0)
board = ((1, 1, 1, 1, 0, 1, 1, 1, 1, 1),) + state.board[1:]
observation = observe(replace(state, board=board, current="I", next_piece="O"))
assert len(observation.legal_actions) == 1
action = observation.legal_actions[0]
_, cleared = place(board, "I", action)
assert cleared == 0
assert SearchExpert().action_values(observation) == {action.id: -10000}
def test_ties_follow_engine_order(monkeypatch) -> None:
observation = observe(new_game(0))
expert = SearchExpert()
monkeypatch.setattr(
expert, "action_values", lambda _: {a.id: 0 for a in observation.legal_actions}
)
assert expert.choose(observation).action_id == observation.legal_actions[0].id
def test_empty_actions_are_rejected() -> None:
observation = replace(observe(new_game(0)), legal_actions=())
assert SearchExpert().action_values(observation) == {}
with pytest.raises(ValueError, match="no legal actions"):
SearchExpert().choose(observation)