Spaces:
Running
Running
File size: 3,299 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 |
import os
import sys
# Add project root to path
# CWD should be loveca-copy
sys.path.insert(0, os.getcwd())
print(f"DEBUG: sys.path[0] = {sys.path[0]}")
print(f"DEBUG: CWD = {os.getcwd()}")
import numpy as np
from engine.game.game_state import GameState
from engine.models.ability import Ability, AbilityCostType, Cost, Effect, EffectType, TriggerType
from engine.models.card import MemberCard
def test_pr_027_self_salvage():
"""
Verify that a card with 'Cost: Send self to waiting room' and 'Effect: Add member from waiting room to hand'
can target itself.
"""
# 1. Setup Game
game = GameState()
p1 = game.players[0]
# 2. Mock Card
# Ability: [Startup] Cost: Self to WR -> Effect: Salvage 1 Member
# We construct the ability manually to match the expected parser output for:
# "{{kidou.png|起動}}このメンバーをステージから控え室に置く:自分の控え室からメンバーカードを1枚手札に加える。"
ability = Ability(
raw_text="Activate: Self to WR -> Salvage 1",
trigger=TriggerType.ACTIVATED,
costs=[Cost(type=AbilityCostType.SACRIFICE_SELF, value=1)],
effects=[Effect(effect_type=EffectType.ADD_TO_HAND, value=1, params={"from": "discard", "filter": "member"})],
)
card = MemberCard(
card_id=9999,
card_no="PL!S-PR-027-PR",
name="Matsuura Kanan",
cost=1,
hearts=np.zeros(7, dtype=np.int32),
blade_hearts=np.zeros(7, dtype=np.int32),
blades=1,
abilities=[ability],
)
# Register card
game.member_db[9999] = card
# 3. Setup State
# Place card on stage
p1.stage[0] = 9999
p1.hand = [] # Empty hand
p1.discard = [] # Empty discard to ensure we only pick self
p1.main_deck = [101, 102] # Non-empty deck to prevent auto-refresh
from engine.game.enums import Phase
game.phase = Phase.MAIN
# 4. Action: Activate Ability
# Action 200 = Activate Area 0
game._execute_action(200)
# Cost should be paid: Card moves Stage -> Discard
assert p1.stage[0] == -1, "Card should be removed from stage"
assert len(p1.discard) == 1, "Card should be in discard"
assert p1.discard[0] == 9999, "Card 9999 should be in discard"
# Choice should be pending: Select card from discard
assert len(game.pending_choices) > 0, "Should have pending choice for effect"
choice_type, params = game.pending_choices[0]
# Updated expectation: SELECT_FROM_DISCARD
assert choice_type == "SELECT_FROM_DISCARD", f"Expected SELECT_FROM_DISCARD, got {choice_type}"
assert params["filter"] == "member", "Should filter for members"
# 5. Execute Choice: Select the card itself (which is in discard now)
# SELECT_FROM_DISCARD choice handler uses actions 660-719.
# params['cards'] should be [9999] in this case.
# So we choose index 0 (Action 660).
game._execute_action(660)
# 6. Verify Result
assert len(p1.hand) == 1, "Hand should have 1 card"
assert p1.hand[0] == 9999, "Should have drawn self"
assert len(p1.discard) == 0, "Discard should be empty"
if __name__ == "__main__":
test_pr_027_self_salvage()
|