Spaces:
Running
Running
| from engine.game.game_state import GameState, initialize_game | |
| from engine.models.ability import AbilityCostType, TriggerType | |
| def test_optional_energy_cost_bp3_001(): | |
| """ | |
| Test card LL-bp3-001-R+: | |
| {{live_start.png|ライブ開始時}}{{icon_energy.png|E}}x6支払ってもよい:... | |
| Verify that the cost is treated as optional in the engine. | |
| """ | |
| gs = initialize_game(use_real_data=True) | |
| # Search for card by number since index might vary | |
| card_no = "LL-bp3-001-R+" | |
| card = None | |
| for c in gs.member_db.values(): | |
| if c.card_no == card_no: | |
| card = c | |
| break | |
| assert card is not None, f"Card {card_no} not found" | |
| # Find the Live Start ability | |
| ability = next(a for a in card.abilities if a.trigger == TriggerType.ON_LIVE_START) | |
| # Check if the cost is optional in the database | |
| assert ability.costs[0].is_optional, f"Cost for {card.card_no} should be optional" | |
| def test_optional_discard_cost_bp1_001(): | |
| """ | |
| Test card LL-bp1-001-R+: | |
| ...好きな組み合わせで合計3枚、控え室に置いてもよい:... | |
| Verify that the cost is treated as optional in the engine. | |
| """ | |
| gs = initialize_game(use_real_data=True) | |
| card_no = "LL-bp1-001-R+" | |
| card = None | |
| for c in gs.member_db.values(): | |
| if c.card_no == card_no: | |
| card = c | |
| break | |
| assert card is not None, f"Card {card_no} not found" | |
| # This card might have its May Discard in effects if the colon was weird, | |
| # but based on my fix it should ideally be in costs if recognized. | |
| # Wait, let's see where it landed in cards_compiled.json. | |
| # Actually, let's just assert it HAS an optional cost if it should. | |
| ability = next(a for a in card.abilities if a.trigger == TriggerType.ON_LIVE_START) | |
| # If it's a cost, it should be optional. | |
| # Note: Some cards might have 'may discard' in effects instead of costs | |
| # if the parser is inconsistent, but the bug report specifically mentioned Costs. | |
| if ability.costs: | |
| assert ability.costs[0].is_optional, f"Cost for {card.card_no} should be optional" | |
| else: | |
| # If it's in effects, check if the effect is optional. | |
| assert any(e.is_optional for e in ability.effects), f"Effect for {card.card_no} should be optional" | |
| def test_optional_discard_cost_logic(): | |
| """ | |
| Test that if a cost is marked as optional, get_legal_actions allows passing. | |
| """ | |
| gs = GameState() | |
| p_idx = gs.current_player | |
| p = gs.players[p_idx] | |
| # Inject a dummy pending choice for an optional cost | |
| from engine.models.ability import Ability, Cost | |
| dummy_ability = Ability( | |
| raw_text="Test", | |
| trigger=TriggerType.ON_PLAY, | |
| effects=[], | |
| costs=[Cost(type=AbilityCostType.DISCARD_HAND, value=1, is_optional=True)], | |
| ) | |
| gs.pending_choices.append( | |
| ("TARGET_HAND", {"player_id": p_idx, "is_optional": True, "effect": "discard", "count": 1}) | |
| ) | |
| mask = gs.get_legal_actions() | |
| # Action 0 is 'Pass' / 'Cancel' | |
| assert mask[0], "Action 0 (Pass) should be legal for an optional cost" | |