File size: 3,527 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
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,
    Condition,
    ConditionType,
    Effect,
    EffectType,
    TargetType,
    TriggerType,
)
from engine.models.card import MemberCard


@pytest.fixture
def state():
    gs = GameState()
    # Mock databases
    GameState.member_db = {}
    GameState.live_db = {}
    return gs


def test_q171_live_end_expiry(state):
    """

    Q171 Verification:

    Ruling: "Until end of live" effects expire at the end of Live Result phase.

    """
    p0 = state.players[0]

    # 1. Apply a "until end of live" effect (e.g., +1 score bonus)
    # Note: BOOST_SCORE is usually handled in live result if it has UNTIL=LIVE_END
    effect = Effect(EffectType.BOOST_SCORE, 1, TargetType.PLAYER, params={"until": "live_end"})
    p0.continuous_effects.append({"effect": effect, "expiry": "LIVE_END", "source_name": "Test Card"})
    p0.live_score_bonus = 1

    # 2. Advance through phases to LIVE_RESULT
    state.phase = Phase.LIVE_RESULT

    # 3. Complete live result and check if bonus is cleared
    # This should call _finish_live_result internally
    state._finish_live_result()

    # Verification
    assert p0.live_score_bonus == 0, "Q171 FAIL: live_score_bonus should be reset after live"
    # Check if continuous effect is gone
    has_live_end = any(e.get("expiry") == "LIVE_END" for e in p0.continuous_effects)
    assert not has_live_end, "Q171 FAIL: LIVE_END continuous effects should be cleared"


def test_q129_cost_reduction_in_hand(state):
    """

    Q129 Verification:

    Ruling: Cost-reducing constant abilities on cards in hand MUST be accounted for.

    Card: LL-bp2-001-R+ (Cost 10, reduced by 1 for each other card in hand)

    """
    p0 = state.players[0]

    # Ability: [常時]手札にあるこのメンバーカードのコストは、このカード以外の自分の手札1枚につき、1少なくなる。
    # This is a bit tricky to mock because the engine currently doesn't have a specific Hook for 'in hand constant'
    # But Q129 says it SHOULD work.

    # Setup card with cost 10
    # Define the cost reduction ability
    cond = Condition(
        ConditionType.COUNT_HAND, params={"min": 0}
    )  # Logic check handled by effect param `per_hand_other`
    # NOTE: The engine fix looks for REDUCE_COST and then checks conditions.
    # The condition "1 for each other card" is usually implemented as a multiplier.
    eff = Effect(EffectType.REDUCE_COST, 1, TargetType.SELF, params={"multiplier": True, "per_hand_other": True})
    ability = Ability(raw_text="Test Ability", trigger=TriggerType.CONSTANT, effects=[eff], conditions=[cond])

    special_card = MemberCard(
        card_id=100,
        card_no="LL-bp2-001-R+",
        name="渡辺 曜&...",
        cost=10,
        hearts=np.zeros(6),
        blade_hearts=np.zeros(7),
        blades=0,
        abilities=[ability],
    )
    state.member_db[100] = special_card

    # Add to hand with 4 other cards (total 5 cards)
    p0.hand = [100, 101, 102, 103, 104]

    # Current Engine check: get_member_cost
    effective_cost = p0.get_member_cost(100, state.member_db)

    # According to Q129, with 5 cards (4 other), cost should be 10 - 4 = 6.
    assert effective_cost == 6, f"Q129 FAIL: Effective cost should be 6 with 4 other cards, but got {effective_cost}"