File size: 6,353 Bytes
2113a6a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
"""Modifier patterns.



Modifiers apply flags and adjustments to parsed abilities:

- is_optional: Whether the effect can be declined

- is_once_per_turn: Usage limit

- duration: How long effects last

- target: Who is affected

"""

from .base import Pattern, PatternPhase

MODIFIER_PATTERNS = [
    # ==========================================================================
    # Optionality (key fix for the bug in legacy parser)
    # ==========================================================================
    Pattern(
        name="optional_may",
        phase=PatternPhase.MODIFIER,
        regex=r"てもよい",
        priority=10,
        output_params={"is_optional": True},
    ),
    Pattern(
        name="optional_can",
        phase=PatternPhase.MODIFIER,
        regex=r"てよい",
        priority=10,
        output_params={"is_optional": True},
    ),
    Pattern(
        name="optional_cost",
        phase=PatternPhase.MODIFIER,
        regex=r"(?:支払うことで|支払えば)",
        priority=15,
        output_params={"cost_is_optional": True},
    ),
    # ==========================================================================
    # Usage limits
    # ==========================================================================
    Pattern(
        name="once_per_turn",
        phase=PatternPhase.MODIFIER,
        regex=r"1ターンに1回|ターン終了時まで1回|に限る|ターン1回|[ターン1回]|【ターン1回】",
        priority=10,
        output_params={"is_once_per_turn": True},
    ),
    # ==========================================================================
    # Duration modifiers
    # ==========================================================================
    Pattern(
        name="until_live_end",
        phase=PatternPhase.MODIFIER,
        keywords=["ライブ終了時まで"],
        priority=20,
        output_params={"duration": "live_end"},
    ),
    Pattern(
        name="until_turn_end",
        phase=PatternPhase.MODIFIER,
        regex=r"ターン終了まで|終了時まで",
        priority=20,
        excludes=["ライブ終了時まで"],  # More specific pattern takes precedence
        output_params={"duration": "turn_end"},
    ),
    # ==========================================================================
    # Target modifiers
    # ==========================================================================
    Pattern(
        name="target_all_players",
        phase=PatternPhase.MODIFIER,
        any_keywords=["自分と相手", "自分も相手も", "全員", "自分および相手"],
        priority=20,
        output_params={"target": "ALL_PLAYERS", "both_players": True},
    ),
    Pattern(
        name="target_opponent",
        phase=PatternPhase.MODIFIER,
        regex=r"相手は.*?(?:する|引く|置く)",
        priority=25,
        excludes=["自分は", "自分を"],
        output_params={"target": "OPPONENT"},
    ),
    Pattern(
        name="target_opponent_hand",
        phase=PatternPhase.MODIFIER,
        keywords=["相手の手札"],
        priority=20,
        output_params={"target": "OPPONENT_HAND"},
    ),
    # ==========================================================================
    # Scope modifiers
    # ==========================================================================
    Pattern(
        name="scope_all",
        phase=PatternPhase.MODIFIER,
        keywords=["すべての"],
        priority=30,
        output_params={"all": True},
    ),
    # ==========================================================================
    # Multiplier modifiers
    # ==========================================================================
    Pattern(
        name="multiplier_per_unit",
        phase=PatternPhase.MODIFIER,
        regex=r"(\d+)(枚|人)につき",
        priority=20,
        output_params={"has_multiplier": True},
    ),
    Pattern(
        name="multiplier_per_member",
        phase=PatternPhase.MODIFIER,
        keywords=["人につき"],
        priority=25,
        output_params={"per_member": True},
    ),
    Pattern(
        name="multiplier_per_live",
        phase=PatternPhase.MODIFIER,
        any_keywords=["成功ライブカード", "ライブカード"],
        requires=["につき", "枚数"],
        priority=25,
        output_params={"per_live": True},
    ),
    Pattern(
        name="multiplier_per_energy",
        phase=PatternPhase.MODIFIER,
        keywords=["エネルギー"],
        requires=["につき"],
        priority=25,
        output_params={"per_energy": True},
    ),
    # ==========================================================================
    # Filter modifiers (for effect targets)
    # ==========================================================================
    Pattern(
        name="filter_cost_max",
        phase=PatternPhase.MODIFIER,
        regex=r"コスト(\d+)以下",
        priority=25,
        output_params={"has_cost_filter": True},
    ),
    Pattern(
        name="filter_group",
        phase=PatternPhase.MODIFIER,
        regex=r"『(.*?)』",
        priority=30,
        consumes=True,
        extractor=lambda text, m: {"params": {"group": m.group(1)}},
    ),
    Pattern(
        name="filter_names",
        phase=PatternPhase.MODIFIER,
        regex=r"「(?!\{\{)(.*?)」",
        priority=30,
        consumes=True,
        extractor=lambda text, m: {"params": {"target_name": m.group(1)}},
    ),
    Pattern(
        name="filter_has_ability",
        phase=PatternPhase.MODIFIER,
        any_keywords=["アクティブにする」を持つ", "【起動】"],
        priority=25,
        output_params={"has_ability": "active"},
    ),
    # ==========================================================================
    # Meta modifiers
    # ==========================================================================
    Pattern(
        name="opponent_trigger_allowed",
        phase=PatternPhase.MODIFIER,
        keywords=["対戦相手のカードの効果でも発動する"],
        priority=10,
        output_params={"opponent_trigger_allowed": True},
    ),
]