bayesian_game / tests /test_game_coordination.py
thompsonson's picture
fix: move imports to top-level to resolve linting errors
f63cf4c
import pytest
from domains.belief.belief_domain import BeliefUpdate
from domains.coordination.game_coordination import BayesianGame, GamePhase, GameState
from domains.environment.environment_domain import EnvironmentEvidence
class TestGameState:
"""Test the GameState dataclass."""
def test_game_state_creation(self):
"""Test creating game state with required parameters."""
state = GameState(round_number=5, max_rounds=10, phase=GamePhase.PLAYING)
assert state.round_number == 5
assert state.max_rounds == 10
assert state.phase == GamePhase.PLAYING
assert state.target_value is None
assert state.evidence_history == []
assert state.current_beliefs == []
def test_game_state_with_optional_params(self):
"""Test creating game state with optional parameters."""
evidence = [EnvironmentEvidence(dice_roll=3, comparison_results=["higher"])]
beliefs = [0.2, 0.3, 0.5]
state = GameState(
round_number=2,
max_rounds=5,
phase=GamePhase.PLAYING,
target_value=4,
evidence_history=evidence,
current_beliefs=beliefs,
most_likely_target=3,
belief_entropy=1.5,
)
assert state.target_value == 4
assert state.evidence_history == evidence
assert state.current_beliefs == beliefs
assert state.most_likely_target == 3
assert state.belief_entropy == 1.5
class TestBayesianGame:
"""Test the BayesianGame class."""
def test_initialization_default(self):
"""Test game initialization with default parameters."""
game = BayesianGame()
assert game.dice_sides == 6
assert game.max_rounds == 10
assert game.environment.dice_sides == 6
assert game.belief_state.dice_sides == 6
assert game.game_state.phase == GamePhase.SETUP
assert game.game_state.round_number == 0
assert game.game_state.max_rounds == 10
def test_initialization_custom(self):
"""Test game initialization with custom parameters."""
game = BayesianGame(dice_sides=8, max_rounds=15, seed=42)
assert game.dice_sides == 8
assert game.max_rounds == 15
assert game.environment.dice_sides == 8
assert game.belief_state.dice_sides == 8
assert game.game_state.max_rounds == 15
def test_start_new_game_random_target(self):
"""Test starting new game with random target."""
game = BayesianGame(seed=42)
state = game.start_new_game()
assert state.phase == GamePhase.PLAYING
assert state.round_number == 0
assert 1 <= state.target_value <= 6
assert len(state.evidence_history) == 0
assert len(state.current_beliefs) == 6
assert state.most_likely_target in range(1, 7)
assert state.belief_entropy > 0
def test_start_new_game_specific_target(self):
"""Test starting new game with specific target."""
game = BayesianGame()
state = game.start_new_game(target_value=4)
assert state.phase == GamePhase.PLAYING
assert state.target_value == 4
assert game.environment.get_target_value() == 4
def test_start_new_game_resets_state(self):
"""Test that starting new game resets previous state."""
game = BayesianGame(seed=42)
# Start first game and play some rounds
game.start_new_game(target_value=3)
game.play_round()
game.play_round()
# Start new game
state = game.start_new_game(target_value=5)
assert state.target_value == 5
assert state.round_number == 0
assert len(state.evidence_history) == 0
assert len(game.belief_state.evidence_history) == 0
def test_play_round_not_playing(self):
"""Test playing round when not in playing phase."""
game = BayesianGame()
# Game starts in setup phase
with pytest.raises(ValueError, match="Game is not in playing phase"):
game.play_round()
def test_play_round_game_finished(self):
"""Test playing round when game is already finished."""
game = BayesianGame(max_rounds=1, seed=42)
# Start game and play one round (should finish)
game.start_new_game(target_value=3)
game.play_round()
# Try to play another round
with pytest.raises(ValueError, match="Game is not in playing phase"):
game.play_round()
def test_play_round_updates_state(self):
"""Test that playing round updates game state correctly."""
game = BayesianGame(seed=42)
game.start_new_game(target_value=3)
initial_round_number = game.get_current_state().round_number
# Play one round
updated_state = game.play_round()
assert updated_state.round_number == initial_round_number + 1
assert len(updated_state.evidence_history) == 1
assert len(updated_state.current_beliefs) == 6
assert updated_state.most_likely_target in range(1, 7)
assert updated_state.belief_entropy >= 0
# Evidence should be valid
evidence = updated_state.evidence_history[0]
assert 1 <= evidence.dice_roll <= 6
# At least one basic comparison result should be present
basic_results = {"higher", "lower", "same"}
assert any(result in basic_results for result in evidence.comparison_results)
def test_play_multiple_rounds(self):
"""Test playing multiple rounds."""
game = BayesianGame(max_rounds=5, seed=42)
game.start_new_game(target_value=4)
for expected_round in range(1, 6):
state = game.play_round()
assert state.round_number == expected_round
assert len(state.evidence_history) == expected_round
if expected_round < 5:
assert state.phase == GamePhase.PLAYING
else:
assert state.phase == GamePhase.FINISHED
def test_get_current_state(self):
"""Test getting current game state."""
game = BayesianGame()
# Initial state
state = game.get_current_state()
assert state.phase == GamePhase.SETUP
# After starting game
game.start_new_game(target_value=2)
state = game.get_current_state()
assert state.phase == GamePhase.PLAYING
assert state.target_value == 2
def test_is_game_finished(self):
"""Test checking if game is finished."""
game = BayesianGame(max_rounds=2, seed=42)
# Initially not finished
assert not game.is_game_finished()
# Start game - still not finished
game.start_new_game(target_value=3)
assert not game.is_game_finished()
# Play one round - still not finished
game.play_round()
assert not game.is_game_finished()
# Play final round - now finished
game.play_round()
assert game.is_game_finished()
def test_get_final_guess_accuracy_no_target(self):
"""Test getting final guess accuracy without target set."""
game = BayesianGame()
with pytest.raises(ValueError, match="Target value not set"):
game.get_final_guess_accuracy()
def test_get_final_guess_accuracy(self):
"""Test getting final guess accuracy."""
game = BayesianGame(seed=42)
game.start_new_game(target_value=3)
# Play some rounds
game.play_round()
game.play_round()
accuracy = game.get_final_guess_accuracy()
# Should be probability assigned to target value 3
assert 0 <= accuracy <= 1
expected_accuracy = game.belief_state.get_belief_for_target(3)
assert accuracy == expected_accuracy
def test_was_final_guess_correct_no_target(self):
"""Test checking final guess correctness without target set."""
game = BayesianGame()
with pytest.raises(ValueError, match="Target value not set"):
game.was_final_guess_correct()
def test_was_final_guess_correct(self):
"""Test checking if final guess was correct."""
game = BayesianGame(seed=42)
game.start_new_game(target_value=3)
# Play rounds until we get definitive evidence
for _ in range(10): # Play enough rounds to get clear evidence
if game.is_game_finished():
break
game.play_round()
is_correct = game.was_final_guess_correct()
most_likely = game.game_state.most_likely_target
assert isinstance(is_correct, bool)
assert is_correct == (most_likely == 3)
def test_get_game_summary(self):
"""Test getting game summary."""
game = BayesianGame(max_rounds=3, seed=42)
game.start_new_game(target_value=4)
# Play all rounds
while not game.is_game_finished():
game.play_round()
summary = game.get_game_summary()
# Check all required fields
assert summary["rounds_played"] == 3
assert summary["max_rounds"] == 3
assert summary["true_target"] == 4
assert summary["final_guess"] in range(1, 7)
assert isinstance(summary["guess_correct"], bool)
assert 0 <= summary["final_accuracy"] <= 1
assert summary["final_entropy"] >= 0
assert summary["evidence_count"] == 3
assert len(summary["final_beliefs"]) == 6
# Check that final beliefs are properly indexed (1-6)
for i in range(1, 7):
assert i in summary["final_beliefs"]
def test_belief_updates_with_evidence(self):
"""Test that belief updates properly reflect evidence."""
game = BayesianGame(seed=42)
game.start_new_game(target_value=1) # Low target for predictable evidence
# Store initial beliefs for comparison
_initial_beliefs = game.belief_state.get_current_beliefs()
# Play several rounds
states = []
for _ in range(5):
if game.is_game_finished():
break
state = game.play_round()
states.append(state)
# Beliefs should change as evidence accumulates
final_beliefs = game.belief_state.get_current_beliefs()
# Should not be uniform anymore (unless very unlikely)
assert not all(abs(b - 1 / 6) < 1e-10 for b in final_beliefs)
# Evidence should influence beliefs correctly
for state in states:
for evidence in state.evidence_history:
if "higher" in evidence.comparison_results:
# Target must be less than dice roll
for _target in range(evidence.dice_roll, 7):
# These targets should have reduced probability
pass # Detailed verification would require complex logic
def test_game_with_evidence_updates(self):
"""Test game behavior with evidence updates."""
game = BayesianGame(seed=42)
game.start_new_game(target_value=3)
# Apply evidence that changes beliefs
update = BeliefUpdate(comparison_results=["higher"])
game.belief_state.update_beliefs(update)
# Update game state to reflect the belief change
game.game_state.most_likely_target = game.belief_state.get_most_likely_target()
# Beliefs should have changed from uniform
prob_1 = game.belief_state.get_belief_for_target(1)
prob_6 = game.belief_state.get_belief_for_target(6)
assert prob_1 > prob_6 # Lower targets should be more likely after "higher"
assert game.belief_state.get_most_likely_target() in range(1, 7)
assert 0 <= game.get_final_guess_accuracy() <= 1
def test_reproducibility_with_seed(self):
"""Test that games are reproducible with same seed."""
# Run two games with same seed
game1 = BayesianGame(seed=42)
game1.start_new_game(target_value=3)
game2 = BayesianGame(seed=42)
game2.start_new_game(target_value=3)
# Play same number of rounds
for _ in range(5):
if game1.is_game_finished() or game2.is_game_finished():
break
state1 = game1.play_round()
state2 = game2.play_round()
# Evidence should be identical
assert len(state1.evidence_history) == len(state2.evidence_history)
for ev1, ev2 in zip(
state1.evidence_history, state2.evidence_history, strict=False
):
assert ev1.dice_roll == ev2.dice_roll
assert ev1.comparison_results == ev2.comparison_results
# Beliefs should be identical
assert state1.current_beliefs == state2.current_beliefs