Spaces:
Running
Running
| """Condition patterns. | |
| Conditions are gating requirements that must be met for an ability to activate. | |
| Examples: COUNT_GROUP, SCORE_COMPARE, HAS_MEMBER, etc. | |
| """ | |
| from .base import Pattern, PatternPhase | |
| # Helper function for extracting Japanese numbers | |
| def _extract_number(text: str, match) -> int: | |
| """Extract a number from match, handling full-width and kanji numerals.""" | |
| val_map = { | |
| "1": 1, | |
| "2": 2, | |
| "3": 3, | |
| "4": 4, | |
| "5": 5, | |
| "6": 6, | |
| "7": 7, | |
| "8": 8, | |
| "9": 9, | |
| "0": 0, | |
| "一": 1, | |
| "二": 2, | |
| "三": 3, | |
| "四": 4, | |
| "五": 5, | |
| "六": 6, | |
| "七": 7, | |
| "八": 8, | |
| "九": 9, | |
| "〇": 0, | |
| } | |
| if match.lastindex and match.lastindex >= 1: | |
| val = match.group(1) | |
| return int(val_map.get(val, val)) if not str(val).isdigit() else int(val) | |
| return 1 | |
| CONDITION_PATTERNS = [ | |
| # ========================================================================== | |
| # Count conditions | |
| # ========================================================================== | |
| Pattern( | |
| name="count_group", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"『(.*?)』.*?(\d+)(枚|人)以上", | |
| priority=20, | |
| output_type="ConditionType.COUNT_GROUP", | |
| extractor=lambda text, match: { | |
| "type": "ConditionType.COUNT_GROUP", | |
| "value": int(match.group(2)), | |
| "params": {"group": match.group(1), "min": int(match.group(2))}, | |
| }, | |
| ), | |
| Pattern( | |
| name="count_stage", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"(\d+)(枚|人)以上", | |
| priority=50, | |
| requires=["ステージ"], | |
| output_type="ConditionType.COUNT_STAGE", | |
| ), | |
| Pattern( | |
| name="count_energy", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"エネルギーが(\d+)枚以上", | |
| priority=30, | |
| output_type="ConditionType.COUNT_ENERGY", | |
| ), | |
| Pattern( | |
| name="count_success_live", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"成功ライブカード置き場.*?(\d+)枚以上", | |
| priority=20, | |
| output_type="ConditionType.COUNT_SUCCESS_LIVE", | |
| ), | |
| Pattern( | |
| name="count_live_zone", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"ライブ中のカード.*?(\d+)枚以上", | |
| priority=20, | |
| output_type="ConditionType.COUNT_LIVE_ZONE", | |
| ), | |
| Pattern( | |
| name="count_hearts", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"(?:ハート|heart).*?(\d+)(つ|個)以上", | |
| priority=30, | |
| output_type="ConditionType.COUNT_HEARTS", | |
| ), | |
| Pattern( | |
| name="count_blades", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"ブレード.*?(\d+)(つ|個)以上", | |
| priority=30, | |
| output_type="ConditionType.COUNT_BLADES", | |
| ), | |
| # ========================================================================== | |
| # Comparison conditions | |
| # ========================================================================== | |
| Pattern( | |
| name="score_compare_gt", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"(?:スコア|コスト).*?相手.*?より(?:高い|多い)", | |
| priority=25, | |
| output_type="ConditionType.SCORE_COMPARE", | |
| output_params={"comparison": "GT", "target": "opponent"}, | |
| ), | |
| Pattern( | |
| name="score_compare_ge", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"(?:スコア|コスト).*?同じか(?:高い|多い)", | |
| priority=25, | |
| output_type="ConditionType.SCORE_COMPARE", | |
| output_params={"comparison": "GE", "target": "opponent"}, | |
| ), | |
| Pattern( | |
| name="score_compare_lt", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"(?:スコア|コスト).*?相手.*?より(?:低い|少ない)", | |
| priority=25, | |
| output_type="ConditionType.SCORE_COMPARE", | |
| output_params={"comparison": "LT", "target": "opponent"}, | |
| ), | |
| Pattern( | |
| name="score_compare_eq", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"(?:スコア|コスト).*?同じ(?:場合|なら|とき)", | |
| priority=25, | |
| output_type="ConditionType.SCORE_COMPARE", | |
| output_params={"comparison": "EQ", "target": "opponent"}, | |
| ), | |
| Pattern( | |
| name="opponent_hand_diff", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"相手の手札(?:の枚数)?が自分より(\d+)?枚?以上?多い", | |
| priority=25, | |
| output_type="ConditionType.OPPONENT_HAND_DIFF", | |
| ), | |
| Pattern( | |
| name="opponent_energy_diff", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"相手のエネルギーが自分より(?:(\d+)枚以上)?多い", | |
| priority=25, | |
| output_type="ConditionType.OPPONENT_ENERGY_DIFF", | |
| ), | |
| Pattern( | |
| name="life_lead_gt", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"ライフが相手より多い", | |
| priority=25, | |
| output_type="ConditionType.LIFE_LEAD", | |
| output_params={"comparison": "GT", "target": "opponent"}, | |
| ), | |
| Pattern( | |
| name="life_lead_lt", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"ライフが相手より少ない", | |
| priority=25, | |
| output_type="ConditionType.LIFE_LEAD", | |
| output_params={"comparison": "LT", "target": "opponent"}, | |
| ), | |
| Pattern( | |
| name="opponent_choice_select", | |
| phase=PatternPhase.CONDITION, | |
| keywords=["相手", "選ぶ"], | |
| excludes=["自分か相手"], | |
| priority=30, | |
| output_type="ConditionType.OPPONENT_CHOICE", | |
| output_params={"type": "select"}, | |
| ), | |
| Pattern( | |
| name="opponent_choice_discard", | |
| phase=PatternPhase.CONDITION, | |
| keywords=["相手", "手札", "捨て"], | |
| priority=30, | |
| output_type="ConditionType.OPPONENT_CHOICE", | |
| output_params={"type": "discard"}, | |
| ), | |
| # ========================================================================== | |
| # State conditions | |
| # ========================================================================== | |
| Pattern( | |
| name="is_center", | |
| phase=PatternPhase.CONDITION, | |
| keywords=["センターエリア", "場合"], | |
| priority=40, | |
| output_type="ConditionType.IS_CENTER", | |
| ), | |
| Pattern( | |
| name="has_moved", | |
| phase=PatternPhase.CONDITION, | |
| keywords=["移動している場合"], | |
| priority=30, | |
| output_type="ConditionType.HAS_MOVED", | |
| ), | |
| Pattern( | |
| name="has_live_card", | |
| phase=PatternPhase.CONDITION, | |
| keywords=["ライブカードがある場合"], | |
| priority=30, | |
| output_type="ConditionType.HAS_LIVE_CARD", | |
| ), | |
| Pattern( | |
| name="has_choice", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"(?:1つを選ぶ|どちらか.*?選ぶ|選んでもよい|のうち.*?選ぶ)", | |
| priority=40, | |
| output_type="ConditionType.HAS_CHOICE", | |
| ), | |
| Pattern( | |
| name="group_filter", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"『(.*?)』", | |
| priority=60, | |
| requires=["場合", "なら", "がいる"], | |
| output_type="ConditionType.GROUP_FILTER", | |
| ), | |
| Pattern( | |
| name="has_member", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"「(.*?)」.*?(?:がある|がいる|登場している)場合", | |
| priority=30, | |
| output_type="ConditionType.HAS_MEMBER", | |
| ), | |
| # ========================================================================== | |
| # Once per turn / Turn restrictions | |
| # ========================================================================== | |
| Pattern( | |
| name="turn_1", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"\[Turn 1\]|1ターン目|ターン1(?!回)", | |
| priority=20, | |
| output_type="ConditionType.TURN_1", | |
| output_params={"turn": 1}, | |
| ), | |
| # ========================================================================== | |
| # Revealed/Milled card conditions | |
| # ========================================================================== | |
| Pattern( | |
| name="all_revealed_are_members", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"それらがすべてメンバーカード.*?場合", | |
| priority=15, | |
| output_type="ConditionType.GROUP_FILTER", | |
| output_params={"filter_type": "all_revealed", "card_type": "member"}, | |
| ), | |
| Pattern( | |
| name="is_in_discard", | |
| phase=PatternPhase.CONDITION, | |
| regex=r"この(カード|メンバー)が控え室にある場合のみ起動できる", | |
| priority=10, | |
| output_type="ConditionType.IS_IN_DISCARD", | |
| ), | |
| ] | |