File size: 5,037 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
import numpy as np
import pytest

from engine.game.game_state import GameState, LiveCard, MemberCard
from engine.models.ability import (
    Ability,
    Condition,
    ConditionType,
    Effect,
    EffectType,
    TargetType,
    TriggerType,
)
from engine.models.enums import Group


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


def test_honoka_blade_buff(game_state):
    """Test Honoka Kosaka: Gain blades per success live (CONSTANT)"""
    state = game_state
    p0 = state.players[0]

    # Ability: {{jyouji.png|常時}}自分の成功ライブカード置き場にあるカード1枚につき、{{icon_blade.png|ブレード}}を得る。
    effect = Effect(EffectType.ADD_BLADES, 1, TargetType.MEMBER_SELF, params={"multiplier": True, "per_live": True})
    ability = Ability(raw_text="常時...", trigger=TriggerType.CONSTANT, effects=[effect])

    # Setup Honoka on stage
    honoka = MemberCard(
        card_id=1,
        card_no="HON-01",
        name="Honoka",
        cost=1,
        hearts=np.zeros(6),
        blade_hearts=np.zeros(7),
        blades=3,
        abilities=[ability],
        groups=[Group.from_japanese_name("ラブライブ!")],
    )
    state.member_db[1] = honoka
    p0.stage[0] = 1

    # 1. Initially 0 success lives
    p0.success_lives = []
    eff_blades = p0.get_effective_blades(0, state.member_db)
    assert eff_blades == 3, "Should have base 3 blades with 0 success lives"

    # 2. Add 2 success lives
    p0.success_lives = [1001, 1002]
    state.live_db[1001] = LiveCard(1001, "L-1001", "S1", 1, np.zeros(7))
    state.live_db[1002] = LiveCard(1002, "L-1002", "S2", 1, np.zeros(7))

    eff_blades = p0.get_effective_blades(0, state.member_db)
    # 3 base + 2 from success lives = 5
    assert eff_blades == 5, "Should have 5 blades (3 + 2 success lives)"


def test_nico_score_bonus(game_state):
    """Test Nico Yazawa: Score bonus +1 if 25 μ's cards in discard (ON_LIVE_START)"""
    state = game_state
    p0 = state.players[0]

    # Ability: {{live_start.png|ライブ開始時}}自分の控え室に『μ's』のカードが25枚以上ある場合、ライブ終了時まで、「ライブの合計スコアを+1する。」を得る。
    cond = Condition(ConditionType.COUNT_GROUP, params={"group": "ラブライブ!", "zone": "DISCARD", "min": 25})
    effect = Effect(EffectType.BOOST_SCORE, 1, TargetType.SELF, params={"until": "live_end"})
    ability = Ability(
        raw_text="ライブ開始時...", trigger=TriggerType.ON_LIVE_START, effects=[effect], conditions=[cond]
    )

    # Setup Nico on stage
    nico = MemberCard(
        card_id=9,
        card_no="NICO-01",
        name="Nico",
        cost=1,
        hearts=np.zeros(6),
        blade_hearts=np.zeros(6),
        blades=1,
        abilities=[ability],
        groups=[Group.from_japanese_name("ラブライブ!")],
    )
    state.member_db[9] = nico
    p0.stage[0] = 9

    # 1. Discard has 24 cards
    p0.discard = [i for i in range(24)]
    for i in range(24):
        state.member_db[i] = MemberCard(
            i,
            f"TEST-{i}",
            f"Card{i}",
            1,
            np.zeros(6),
            np.zeros(7),
            1,
            groups=[Group.from_japanese_name("ラブライブ!")],
        )

    # Trigger live start (simplified)
    state._play_automatic_ability(0, ability, {"area": 0})
    assert p0.live_score_bonus == 0, "Should not gain score bonus with only 24 cards"

    # 2. Add 1 more for 25 cards
    p0.discard.append(24)
    state.member_db[24] = MemberCard(
        24, "TEST-24", "Card24", 1, np.zeros(6), np.zeros(7), 1, groups=[Group.from_japanese_name("ラブライブ!")]
    )

    state._play_automatic_ability(0, ability, {"area": 0})
    assert p0.live_score_bonus == 1, "Should gain score bonus with 25 cards"

    # 3. Test cleanup
    state._clear_expired_effects("LIVE_END")
    assert p0.live_score_bonus == 0, "Score bonus should be cleared after live"


def test_ginko_draw(game_state):
    """Test Ginko Mozume: Draw (ON_PLAY)"""
    state = game_state
    p0 = state.players[0]

    # Ability: 登場:1枚引く。
    effect = Effect(EffectType.DRAW, 1, TargetType.SELF)
    ability = Ability(raw_text="登場...", trigger=TriggerType.ON_PLAY, effects=[effect])

    ginko = MemberCard(
        card_id=20,
        card_no="GIN-01",
        name="Ginko",
        cost=1,
        hearts=np.zeros(6),
        blade_hearts=np.zeros(6),
        blades=1,
        abilities=[ability],
        groups=[Group.from_japanese_name("蓮ノ空")],
    )
    state.member_db[20] = ginko

    p0.main_deck = [101, 102]
    p0.hand = []

    state._play_automatic_ability(0, ability, {"area": 1})
    assert len(p0.hand) == 1
    assert p0.hand[0] == 101