File size: 5,185 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import numpy as np
import pytest
from pytest_bdd import given, scenario, then, when

from engine.game.game_state import GameState, MemberCard, Phase
from engine.models.ability import Effect, EffectType


@pytest.fixture
def game_state():
    # Reset Class-level DBs
    GameState.member_db = {}
    gs = GameState()
    return gs


@scenario("../features/mechanics.feature", "Baton Touch reduces cost")
def test_baton_touch_reduce():
    pass


@scenario("../features/mechanics.feature", "Baton Touch limit")
def test_baton_touch_limit():
    pass


@scenario("../features/mechanics.feature", "Cost Reduction for Member")
def test_cost_reduction():
    pass


@scenario("../features/mechanics.feature", "Placement Restriction")
def test_placement_restriction():
    pass


@given("a player", target_fixture="p0")
def player_generic(game_state):
    return game_state.players[0]


@given("a player has a member on stage with cost 3", target_fixture="p0")
def player_with_stage_member(game_state):
    p0 = game_state.players[0]
    # Create member in DB
    m1 = MemberCard(1, "C1", "Mem1", 3, np.zeros(6), np.zeros(7), 1)
    # Ensure DB is ready
    GameState.member_db[1] = m1
    p0.stage[0] = 1
    return p0


@given("the player has a member in hand with cost 4")
def player_with_hand_member(game_state, p0):
    m2 = MemberCard(2, "C2", "Mem2", 4, np.zeros(6), np.zeros(7), 1)
    game_state.member_db[2] = m2
    p0.hand = [2]


@given("the player has 1 energy")
def player_energy_1(p0):
    p0.energy_zone = [100]
    p0.tapped_energy = np.zeros(100, dtype=bool)


@given("the player has 3 energy")
def player_energy_3(p0):
    p0.energy_zone = [100, 101, 102]
    p0.tapped_energy = np.zeros(100, dtype=bool)


@given("a player has a cost reduction effect of 1", target_fixture="p0_red")
def player_cost_reduction(game_state):
    p0 = game_state.players[0]
    eff = Effect(EffectType.REDUCE_COST, 1)
    p0.continuous_effects.append({"effect": eff, "expiry": "TURN_END"})
    return p0


@given('a player has a "placement" restriction', target_fixture="p0_res")
def player_restriction(game_state):
    p0 = game_state.players[0]
    p0.restrictions.add("placement")
    return p0


@when("the player plays the hand member onto the stage member")
def play_baton_touch(game_state, p0):
    # Action: Play card 2 (idx 0 in hand) to Area 0
    # Logic is hardcoded to area 0 for this test
    game_state.phase = Phase.MAIN
    game_state._play_member(0, 0)


@when("the player plays the member")
def play_member(game_state, p0_red):
    game_state.phase = Phase.MAIN
    game_state._play_member(0, 0)  # Play from hand idx 0 to area 0


@then("the play should be successful")
def check_play_success(p0):
    # Check if member 2 is on stage 0
    assert p0.stage[0] == 2


@then("the energy used should be 1")
def check_energy_1(p0):
    assert np.sum(p0.tapped_energy) == 1


@then("the energy used should be 3")
def check_energy_3(p0):
    # Depending on which fixture was used, P0 might be passed as p0_red
    assert np.sum(p0.tapped_energy) == 3


@then("the baton touch count should be 1")
def check_baton_count(p0):
    assert p0.baton_touch_count == 1


@given("a player has performed a baton touch this turn")
def setup_baton_done(game_state, p0):
    # Force state
    p0.baton_touch_count = 1
    p0.baton_touch_limit = 1
    # Ensure stage matches post-baton state to allow another?
    # Or just test cost calculation.
    # Logic in _play_member checks limit.


@given("the player has another member in hand")
def player_has_another_member(game_state, p0):
    # Add member 3 to hand
    m3 = MemberCard(3, "C3", "Mem3", 3, np.zeros(6), np.zeros(7), 1)
    GameState.member_db[3] = m3
    p0.hand.append(3)


@when("the player attempts another baton touch")
def attempt_second_baton(game_state, p0):
    # This requires failing the action or checking legal actions
    pass


@then("the cost should not be reduced")
def check_no_reduction(game_state, p0):
    # We check mask instead of executing, as executing might crash or use weird logic if not enough energy
    # But wait, we didn't setup enough energy for full cost!

    # Let's say we have enough energy for reduced (1) but not full (4)
    # If cost is not reduced, checking legality should return False
    mask = game_state.get_legal_actions()
    action_id = 1  # Play hand 0 to area 0
    assert not mask[action_id], "Should not be legal if cost is not reduced"


@when("the player attempts to play a member")
def attempt_play_restriction(game_state, p0_res):
    # Setup necessary state for legality check
    p0_res.hand = [10]
    game_state.member_db[10] = MemberCard(10, "C", "N", 1, np.zeros(6), np.zeros(7), 1)
    p0_res.energy_zone = [100]
    p0_res.tapped_energy = np.zeros(100, dtype=bool)
    game_state.phase = Phase.MAIN


@then("the action should be illegal")
def check_illegal(game_state):
    mask = game_state.get_legal_actions()
    # Any play member action
    action_id = 1
    assert not mask[action_id]