Spaces:
Running
Running
File size: 5,676 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 |
import numpy as np
import pytest
from engine.game.game_state import GameState, Phase
from engine.models.ability import Effect, EffectType, TargetType
from engine.models.card import LiveCard, MemberCard
@pytest.fixture
def base_state():
state = GameState()
state.phase = Phase.MAIN
state.current_player = 0
state.players[0].energy_zone = [1000, 1001, 1002, 1003, 1004] # 5 energy
state.players[0].hand = [1, 2, 3]
# Mock some basic cards
m1 = MemberCard(
card_id=1,
card_no="M1",
name="Member 1",
cost=2,
blades=2,
hearts=np.array([2, 0, 0, 0, 0, 0, 0]),
blade_hearts=np.zeros(7),
)
m2 = MemberCard(
card_id=2,
card_no="M2",
name="Member 2",
cost=2,
blades=2,
hearts=np.array([0, 2, 0, 0, 0, 0, 0]),
blade_hearts=np.zeros(7),
)
m3 = MemberCard(
card_id=3,
card_no="M3",
name="Member 3",
cost=2,
blades=2,
hearts=np.array([0, 0, 2, 0, 0, 0, 0]),
blade_hearts=np.zeros(7),
)
state.member_db[1] = m1
state.member_db[2] = m2
state.member_db[3] = m3
return state
def test_baton_touch_limit_extension():
state = GameState()
state.phase = Phase.MAIN
state.players[0].energy_zone = [1000] * 20 # Lots of energy
state.member_db[1] = MemberCard(
card_id=1, card_no="M1", name="M1", cost=1, blades=1, hearts=[0] * 7, blade_hearts=[0] * 7
)
state.member_db[2] = MemberCard(
card_id=2, card_no="M2", name="M2", cost=1, blades=1, hearts=[0] * 7, blade_hearts=[0] * 7
)
state.member_db[3] = MemberCard(
card_id=3, card_no="M3", name="M3", cost=1, blades=1, hearts=[0] * 7, blade_hearts=[0] * 7
)
state.member_db[4] = MemberCard(
card_id=4, card_no="M4", name="M4", cost=1, blades=1, hearts=[0] * 7, blade_hearts=[0] * 7
)
state.member_db[5] = MemberCard(
card_id=5, card_no="M5", name="M5", cost=1, blades=1, hearts=[0] * 7, blade_hearts=[0] * 7
)
p = state.players[0]
p.hand = [1, 2, 3, 4]
# 1. Fill stage without baton touches
p.stage[0] = 1
p.stage[1] = 2
p.stage[2] = 3
p.hand = [4, 5]
# Now slots are [1, 2, 3]. Baton count = 0, Limit = 1.
# 2. Perform 1st baton touch on Slot 0
# Hand is [4, 5]. Action for Hand 0 to Slot 0 is 1 + 0*3 + 0 = 1.
legal = state.get_legal_actions()
assert legal[1], "Baton touch 1 (Hand 0 to Slot 0) should be legal"
state = state.step(1)
p = state.players[0] # Update p to the new state's player
assert p.baton_touch_count == 1
assert p.stage[0] == 4
# 3. Try to perform 2nd baton touch (Should be illegal by default limit=1)
# Hand is [5]. Action for Hand 0 to Slot 1 is 1 + 0*3 + 1 = 2.
legal = state.get_legal_actions()
assert not legal[2], "Baton touch 2 (Hand 0 to Slot 1) should be illegal (limit 1 reached)"
# 4. Apply Modifier (+1 baton touch)
p.continuous_effects.append(
{"effect": Effect(EffectType.BATON_TOUCH_MOD, 1, TargetType.SELF), "expiry": "TURN_END"}
)
legal = state.get_legal_actions()
assert legal[2], "Baton touch 2 should be legal after BATON_TOUCH_MOD"
def test_heart_requirement_reduction(base_state):
p = base_state.players[0]
# Card 1 is in Slot 0 (2 Pink hearts)
p.stage[0] = 1
p.hand = [2, 3]
# Mock Live Card: Needs 3 Pink hearts
l1 = LiveCard(card_id=101, card_no="L1", name="Live 1", score=2, required_hearts=np.array([3, 0, 0, 0, 0, 0, 0]))
base_state.live_db[101] = l1
p.live_zone = [101]
# 1. Normal Performance: Should fail (2 < 3)
guide = p.get_performance_guide(base_state.live_db, base_state.member_db)
assert guide["lives"][0]["passed"] == False, "Should fail without reduction"
# 2. Add REDUCE_HEART_REQ (-1 Pink)
p.continuous_effects.append(
{"effect": Effect(EffectType.REDUCE_HEART_REQ, 1, TargetType.SELF, {"color": 1}), "expiry": "LIVE_END"}
)
# 3. Now should pass (2 >= 3-1)
guide = p.get_performance_guide(base_state.live_db, base_state.member_db)
assert guide["lives"][0]["passed"] == True, (
f"Should pass with reduction. Req: {guide['lives'][0]['req']}, Have: {guide['total_hearts']}"
)
def test_color_transform(base_state):
p = base_state.players[0]
# Card 2 has 2 Red hearts. Place in Slot 0.
p.stage[0] = 2
# Mock Live Card: Needs 2 Pink hearts
l1 = LiveCard(
card_id=101, card_no="L101", name="Live 101", score=2, required_hearts=np.array([2, 0, 0, 0, 0, 0, 0])
)
base_state.live_db[101] = l1
p.live_zone = [101]
# 1. Normal: Fails (Needs pink, has red)
guide = p.get_performance_guide(base_state.live_db, base_state.member_db)
assert guide["lives"][0]["passed"] == False, "Should fail (Needs Pink, has Red)"
# 2. Add TRANSFORM_COLOR (Red -> Pink)
p.continuous_effects.append(
{
"effect": Effect(EffectType.TRANSFORM_COLOR, 0, TargetType.SELF, {"from_color": 2, "to_color": 1}),
"expiry": "LIVE_END",
}
)
# 3. Now should pass
guide = p.get_performance_guide(base_state.live_db, base_state.member_db)
assert guide["total_hearts"][0] == 2, f"Should have 2 Pink hearts. Got {guide['total_hearts']}"
assert guide["total_hearts"][1] == 0, f"Should have 0 Red hearts. Got {guide['total_hearts']}"
assert guide["lives"][0]["passed"] == True, "Should pass after transform"
|