Spaces:
Sleeping
Sleeping
File size: 11,343 Bytes
9bd4ce5 | 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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | # metadata.json とバイトコード生成の分析レポート
## 概要
このレポートでは、`data/metadata.json` がバイトコード生成にどのように影響するか、またパーサーとビットマスク処理が過度に複雑かどうかを分析します。
---
## 1. metadata.json の構造
### 1.1 セクション一覧
| セクション | 用途 | エントリ数 |
|-----------|------|-----------|
| `triggers` | 能力の発動タイミング | 11 |
| `targets` | 効果の対象 | 14 |
| `opcodes` | バイトコード命令 | 67 |
| `action_bases` | アクションIDのベース値 | 13 |
| `phases` | ゲームフェーズ | 15 |
| `conditions` | 条件チェック命令 | 54 |
| `costs` | コスト種別 | 95 |
| `extra_constants` | ビットマスク定数 | 26 |
| `unused` | 未使用マーク | 0 (空) |
### 1.2 同期フロー
```mermaid
flowchart TD
A[data/metadata.json] --> B[tools/sync_metadata.py]
B --> C[engine_rust_src/src/core/generated_constants.rs]
B --> D[engine_rust_src/src/core/enums.rs]
B --> E[frontend/web_ui/js/generated_constants.js]
B --> F[engine/models/generated_metadata.py]
B --> G[engine_rust_src/src/core/shader_constants.wgsl]
```
---
## 2. 問題点: 二重定義と不整合
### 2.1 Python側の二重定義問題
**重大な問題**: [`engine/models/ability.py`](engine/models/ability.py) には `metadata.json` とは**独立した** enum定義が存在します。
```python
# ability.py (行10-22) - metadata.json と独立
class TriggerType(IntEnum):
NONE = 0
ON_PLAY = 1
ON_LIVE_START = 2
# ...
```
これは [`engine/models/generated_metadata.py`](engine/models/generated_metadata.py) と**重複**しており、同期されていません。
### 2.2 具体的な不整合例
| 項目 | metadata.json | ability.py | 状態 |
|-----|---------------|------------|------|
| `SEARCH_DECK` | 22 | 22 | ✅ 一致 |
| `FORMATION_CHANGE` | 26 | 26 | ✅ 一致 |
| `SWAP_ZONE` | 38 | 38 | ✅ 一致 |
| `PREVENT_SET_TO_SUCCESS_PILE` | 80 | 80 | ✅ 一致 |
| `SET_HEART_COST` | 83 | 83 | ✅ 一致 |
**現在は値が一致していますが**、`ability.py`のenumは手動管理であり、将来的な不整合のリスクがあります。
### 2.3 AbilityCostType の爆発的増加
[`ability.py`](engine/models/ability.py:303-500) の `AbilityCostType` は **200以上のエントリ** を持ち、その多くが自動生成された「プレースホルダ」です:
```python
# 行410-500: 自動生成されたエントリの例
PLACE_ENERGY_FROM_DECK_TO_DISCARD = 110
PLACE_ENERGY_FROM_DECK_TO_HAND = 111
# ... 90行以上の自動生成エントリ
```
これらは `metadata.json` の `costs` セクション (95エントリ) と比較して**2倍以上の規模**です。
---
## 3. ビットマスク処理の複雑さ分析
### 3.1 _pack_filter_attr のビットレイアウト
[`ability.py`](engine/models/ability.py:1388-1595) の `_pack_filter_attr` メソッドは、64ビット整数に複数のフィルタ条件をパックします:
```
ビットレイアウト (64ビット):
┌─────────────────────────────────────────────────────────────────┐
│ Bits 2-3 : Type (0=Any, 1=Member, 2=Live) │
│ Bit 4 : Group Filter Enable │
│ Bits 5-11 : Group ID (7 bits) │
│ Bit 12 : Tapped Filter │
│ Bit 13 : Has Blade Heart │
│ Bit 14 : Not Has Blade Heart │
│ Bit 15 : Unique Names │
│ Bit 16 : Unit Filter Enable │
│ Bits 17-23 : Unit ID (7 bits) │
│ Bit 24 : Cost Filter Enable ←┐ │
│ Bits 25-29 : Cost Threshold (5b) │ 競合! │
│ Bit 30 : Cost Mode │ │
│ Bit 31 : Color Filter Enable ←┘ │
│ Bits 32-38 : Character ID 1 │
│ Bit 42 : Character Filter Enable │
│ Bits 43-49 : Character ID 2 │
│ Bits 50-56 : Character ID 3 │
│ Bits 57-59 : Special Filter ID │
└─────────────────────────────────────────────────────────────────┘
```
### 3.2 ビット競合の問題
**重大な設計欠陥**: Bits 24-30 が **Cost Filter** と **Color Filter** で競合しています:
```python
# Cost Filter (行1517-1536)
if c_min is not None:
attr |= 1 << 24 # Cost Enable
attr |= (val & 0x1F) << 25 # Cost Value
# Color Filter (行1538-1555) - 同じビット領域を使用!
if color_mask > 0:
attr |= (color_mask & 0x7F) << 24 # ← Cost と重複!
attr |= 1 << 31
```
これにより、Cost Filter と Color Filter は**同時に使用できません**。
### 3.3 Rust側の実装との整合性
[`engine_rust_src/src/core/logic/filter.rs`](engine_rust_src/src/core/logic/filter.rs:20-33) では、同じビットレイアウトを使用:
```rust
/// Bit layout (see generated_constants.rs):
/// - Bits 2-3: Card type (Member=1, Live=2)
/// - Bit 4: Group filter enable
/// - Bits 5-11: Group ID
/// - Bit 16: Unit filter enable
/// - Bits 17-23: Unit ID
/// - Bits 32-38: Color mask ← 異なる! Pythonは24-30
/// - Bit 42: Character filter enable
```
**Rust側は Bits 32-38 を Color に使用**していますが、Python側は Bits 24-30 を使用しており、**不整合**があります。
---
## 4. バイトコードコンパイルの複雑さ
### 4.1 コンパイルフロー
```mermaid
flowchart TD
A[Ability.instructions] --> B{Instruction Type?}
B -->|Condition| C[_compile_single_condition]
B -->|Effect| D[_compile_effect_wrapper]
B -->|Cost| E[_compile_single_cost]
C --> F[Opcode + Value + Attr + Slot]
D --> G{Effect Type?}
G -->|ORDER_DECK| H[LOOK_DECK + ORDER_DECK]
G -->|SELECT_MODE| I[Jump Table生成]
G -->|Other| J[_compile_single_effect]
J --> K[特殊処理]
K --> L[_pack_filter_attr呼び出し]
L --> F
```
### 4.2 特殊処理の分岐数
[`_compile_single_effect`](engine/models/ability.py:949-1386) メソッドには**15以上の特殊ケース分岐**があります:
| Effect Type | 特殊処理内容 | 行番号 |
|-------------|-------------|-------|
| `ORDER_DECK` | LOOK_DECK命令を先行 emit | 859-872 |
| `SELECT_MODE` | ジャンプテーブル生成 | 877-925 |
| `RECOVER_MEMBER/LIVE` | ゾーン再配置ビット処理 | 965-977 |
| `TAP_OPPONENT/TAP_MEMBER` | フィルタ属性パック | 981-986 |
| `PLACE_UNDER` | ソース属性設定 | 989-993 |
| `ENERGY_CHARGE` | ウェイト状態フラグ | 996-998 |
| `SELECT_MEMBER` | フィルタ属性パック | 1001-1002 |
| `PLAY_MEMBER_*` | フィルタ属性パック | 1005-1010 |
| `LOOK_AND_CHOOSE` | キャラクターID + ゾーン処理 | 1013-1099 |
| `SELECT_CARDS/MEMBER/LIVE` | 複雑なビットパッキング | 1102-1130 |
| `SET_HEART_COST` | 6色コスト + ユニットフィルタ | 1133-1194 |
| `META_RULE` | 13種類のルールタイプ | 1275-1302 |
| `REVEAL_UNTIL` | 条件タイプ別エンコード | 1305-1345 |
### 4.3 コードの複雑さ指標
| 指標 | 値 | 評価 |
|-----|-----|------|
| `_compile_single_effect` の行数 | 437行 | 🔴 過大 |
| `_pack_filter_attr` の行数 | 208行 | 🟡 中程度 |
| 特殊処理分岐数 | 15+ | 🔴 過多 |
| ビットシフト演算数 | 50+ | 🔴 過多 |
| ネスト深度 | 最大5レベル | 🟡 中程度 |
---
## 5. 推奨される改善策
### 5.1 短期的改善 (優先度: 高)
1. **二重定義の排除**
- `ability.py` の enum を `generated_metadata.py` から import するよう変更
- または、`sync_metadata.py` が `ability.py` も生成するよう拡張
2. **ビット競合の解消**
- Color Filter を Bits 32-38 に移動 (Rust側に合わせる)
- または、Cost Filter を Bits 8-14 に移動
### 5.2 中期的改善 (優先度: 中)
3. **フィルタ構造体の導入**
```python
@dataclass
class CardFilter:
card_type: Optional[CardType]
group_id: Optional[int]
unit_id: Optional[int]
cost_filter: Optional[tuple[int, bool]] # (threshold, is_le)
color_mask: int
# ...
def pack(self) -> int:
"""構造化されたフィルタをビット列に変換"""
```
4. **エフェクトコンパイラの分割**
- `_compile_single_effect` を各エフェクトタイプ別のハンドラに分割
- Visitor パターンまたは Strategy パターンの採用
### 5.3 長期的改善 (優先度: 低)
5. **バイトコード設計の再検討**
- 現在: 4-int固定長 `[op, v, a, s]`
- 提案: 可変長またはTLV (Type-Length-Value) 形式
6. **宣言的エフェクト定義**
- YAML/JSON でエフェクトを定義し、コード生成
---
## 6. 結論
### 6.1 metadata.json のバイトコードへの影響
| 側面 | 評価 | 説明 |
|-----|------|------|
| Opcode値の定義 | ✅ 良好 | 自動同期されている |
| 条件/コスト値 | ✅ 良好 | 自動同期されている |
| Python enumとの整合性 | 🟡 リスクあり | 手動管理のため将来的に不整合の可能性 |
| ビットマスク定数 | 🔴 不整合あり | Python/Rustでビット位置が異なる |
### 6.2 複雑さの評価
| 側面 | 評価 | 理由 |
|-----|------|------|
| パーサー | 🟡 中程度 | 分岐は多いが構造は理解可能 |
| ビットマスク | 🔴 過度に複雑 | 競合あり、文書化不十分 |
| コンパイラ | 🔴 過度に複雑 | 400行の単一メソッド、15+分岐 |
| 保守性 | 🔴 低い | 二重定義、暗黙のビット操作 |
### 6.3 最優先すべき課題
1. **Color Filter のビット位置修正** (Rust側に合わせる)
2. **ability.py の enum を自動生成に切り替え**
3. **_compile_single_effect の分割リファクタリング**
---
## 付録: 関連ファイル一覧
| ファイル | 行数 | 役割 |
|---------|------|------|
| [`data/metadata.json`](data/metadata.json) | 323 | 定数定義のマスター |
| [`engine/models/ability.py`](engine/models/ability.py) | 1852 | 能力定義・コンパイル |
| [`tools/sync_metadata.py`](tools/sync_metadata.py) | 349 | 定数同期スクリプト |
| [`engine_rust_src/src/core/generated_constants.rs`](engine_rust_src/src/core/generated_constants.rs) | 275 | Rust定数 (自動生成) |
| [`engine_rust_src/src/core/logic/filter.rs`](engine_rust_src/src/core/logic/filter.rs) | 150+ | Rustフィルタロジック |
| [`tools/verify/bytecode_decoder.py`](tools/verify/bytecode_decoder.py) | 307 | バイトコードデコーダ |
|