File size: 4,057 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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import numpy as np
import pytest

from engine.game.enums import Phase
from engine.game.game_state import GameState
from engine.models.ability import Ability, Effect, EffectType, TriggerType
from engine.models.card import LiveCard, MemberCard


@pytest.fixture
def game_state():
    state = GameState()
    # Mock DB - Reset class variables
    GameState.member_db = {}
    GameState.live_db = {}
    return state


def test_baton_touch_cost(game_state):
    """Verify Baton Touch reduces cost correctly"""
    state = game_state
    # Card 1: Cost 2 (on stage)
    # card_id, card_no, name, cost, hearts, blade_hearts, blades
    c1 = MemberCard(1, "NO-01", "Fan1", 2, np.zeros(6), np.zeros(7), 1)
    # Card 2: Cost 5 (in hand)
    c2 = MemberCard(2, "NO-02", "Fan2", 5, np.zeros(6), np.zeros(7), 1)

    GameState.member_db = {1: c1, 2: c2}

    p = state.players[0]
    p.stage[0] = 1  # Card 1 on Left
    p.hand = [2]  # Card 2 in hand
    p.hand_added_turn = [0] * len(p.hand)
    # Energy: 3 available (enough for 5-2=3, but not 5)
    p.energy_zone = [100, 101, 102]
    p.tapped_energy[:] = False
    p.main_deck = [999]  # Validation: Prevent auto-refresh from discard

    state.phase = Phase.MAIN
    state.current_player = 0

    # Action: Play Card 2 (idx 0) on Area 0 (Left)
    # Action encoding: 1 + hand_idx*3 + area = 1 + 0 + 0 = 1

    # Check if legal (should be, cost 5-2=3 <= 3 energy)
    legal = state.get_legal_actions()
    assert legal[1], "Baton touch play should be legal"

    # Execute
    new_state = state.step(1)
    np0 = new_state.players[0]

    # Verify result
    assert np0.stage[0] == 2, "Card 2 should be on stage"
    assert 1 in np0.discard, "Card 1 should be in discard"
    assert np0.count_untapped_energy() == 0, "Should use all 3 energy (5-2=3)"


def test_live_heart_requirements(game_state):
    """Verify Live card heart checking logic"""
    state = game_state
    # Req: 1 Pink, 1 Red, 1 Any
    req = np.zeros(7, dtype=np.int32)
    req[0] = 1  # Pink
    req[1] = 1  # Red
    req[6] = 1  # Any

    live = LiveCard(100, "L-01", "Song", 1, req)
    GameState.live_db = {100: live}

    p = state.players[0]
    p.live_zone = [100]

    # Case 1: Exact match (Pink, Red, Blue for Any)
    hearts1 = np.zeros(6, dtype=np.int32)
    hearts1[0] = 1
    hearts1[1] = 1
    hearts1[4] = 1  # Blue
    assert state._check_hearts_meet_requirement(hearts1, req), "Should match with exact + blue"

    # Case 2: Insufficient Color (2 Pink, 0 Red, 1 Blue) -> Fail Red
    hearts2 = np.zeros(6, dtype=np.int32)
    hearts2[0] = 2
    hearts2[4] = 1
    assert not state._check_hearts_meet_requirement(hearts2, req), "Should fail missing red"

    # Case 3: Insufficient Any (1 Pink, 1 Red) -> Fail Any
    hearts3 = np.zeros(6, dtype=np.int32)
    hearts3[0] = 1
    hearts3[1] = 1
    assert not state._check_hearts_meet_requirement(hearts3, req), "Should fail missing any"


def test_trigger_stack(game_state):
    """Verify On Play triggers add to stack"""
    state = game_state
    # Card with On Play logic
    ability = Ability("Test", TriggerType.ON_PLAY, [Effect(EffectType.DRAW, 1)])

    c1 = MemberCard(1, "NO-01", "Fan1", 1, np.zeros(6), np.zeros(7), 1, abilities=[ability])

    GameState.member_db = {1: c1}

    p = state.players[0]
    p.hand = [1]
    p.hand_added_turn = [0] * len(p.hand)
    p.energy_zone = [100]

    state.phase = Phase.MAIN
    state.current_player = 0

    # Play Card 1
    # Action: 1 (Hand idx 0, Area 0)
    new_state = state.step(1)

    # Check trigger was processed
    # Note: step() auto-resolves triggers if no choice required.
    # Since DRAW 1 is auto-resolved, pending_effects should be empty.
    assert len(new_state.pending_effects) == 0, "Effect should auto-resolve"

    # Should have drawn a card (if deck had cards, which it doesn't by default here)
    # But main point is verifying the trigger mechanism doesn't crash or hang