Spaces:
Running
Running
| 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 | |
| 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 | |