File size: 2,937 Bytes
bb3fbf9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""

Test to ensure PlayerState slots are complete.



This test prevents the class of bugs where dynamic attributes are lost during state copying

because they aren't declared in __slots__.

"""

import numpy as np
import pytest

from engine.game.player_state import PlayerState


class TestPlayerStateSlotCompleteness:
    """Verify all attributes are properly declared in __slots__."""

    def test_no_dynamic_attributes_after_init(self):
        """PlayerState should have no __dict__ (pure __slots__ class)."""
        ps = PlayerState(0)
        # __slots__ classes should not have __dict__ unless explicitly added
        # However, if parent class doesn't use __slots__, __dict__ may exist but be empty
        if hasattr(ps, "__dict__"):
            assert len(ps.__dict__) == 0, f"PlayerState has dynamic attributes not in __slots__: {ps.__dict__}"

    def test_all_slots_have_default_values(self):
        """All slots should be initialized in __init__."""
        ps = PlayerState(0)
        for slot in PlayerState.__slots__:
            assert hasattr(ps, slot), f"Slot '{slot}' not initialized in __init__"

    def test_copy_preserves_all_slots(self):
        """copy() should preserve all slot values."""
        ps1 = PlayerState(0)

        # Modify some values to non-default
        ps1.hand = [1, 2, 3]
        ps1.tapped_members[0] = True
        ps1.rested_members[1] = True
        ps1.performance_abilities_processed = True
        ps1.revealed_hand = True
        ps1.deck_refreshed_this_turn = True
        ps1.baton_touch_count = 5

        # Copy
        ps2 = ps1.copy()

        # Verify all values copied
        assert ps2.hand == [1, 2, 3]
        assert ps2.tapped_members[0] == True
        assert ps2.rested_members[1] == True
        assert ps2.performance_abilities_processed == True
        assert ps2.revealed_hand == True
        assert ps2.deck_refreshed_this_turn == True
        assert ps2.baton_touch_count == 5

        # Verify copies are independent (deep copy for mutable types)
        ps2.hand.append(4)
        assert ps1.hand == [1, 2, 3], "hand should be deep copied"

        ps2.tapped_members[0] = False
        assert ps1.tapped_members[0] == True, "numpy arrays should be deep copied"

    def test_reset_clears_all_mutable_state(self):
        """_reset() should restore all slots to defaults."""
        ps = PlayerState(0)

        # Modify state
        ps.hand = [1, 2, 3]
        ps.performance_abilities_processed = True
        ps.revealed_hand = True
        ps.rested_members[0] = True

        # Reset
        ps._reset(0)

        # Verify reset
        assert ps.hand == []
        assert ps.performance_abilities_processed == False
        assert ps.revealed_hand == False
        assert not np.any(ps.rested_members)


if __name__ == "__main__":
    pytest.main([__file__, "-v"])