Spaces:
Sleeping
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 同期フロー
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 には metadata.json とは独立した enum定義が存在します。
# ability.py (行10-22) - metadata.json と独立
class TriggerType(IntEnum):
NONE = 0
ON_PLAY = 1
ON_LIVE_START = 2
# ...
これは 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 の AbilityCostType は 200以上のエントリ を持ち、その多くが自動生成された「プレースホルダ」です:
# 行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 の _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 で競合しています:
# 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 では、同じビットレイアウトを使用:
/// 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 コンパイルフロー
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 メソッドには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 短期的改善 (優先度: 高)
二重定義の排除
ability.pyの enum をgenerated_metadata.pyから import するよう変更- または、
sync_metadata.pyがability.pyも生成するよう拡張
ビット競合の解消
- Color Filter を Bits 32-38 に移動 (Rust側に合わせる)
- または、Cost Filter を Bits 8-14 に移動
5.2 中期的改善 (優先度: 中)
フィルタ構造体の導入
@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: """構造化されたフィルタをビット列に変換"""エフェクトコンパイラの分割
_compile_single_effectを各エフェクトタイプ別のハンドラに分割- Visitor パターンまたは Strategy パターンの採用
5.3 長期的改善 (優先度: 低)
バイトコード設計の再検討
- 現在: 4-int固定長
[op, v, a, s] - 提案: 可変長またはTLV (Type-Length-Value) 形式
- 現在: 4-int固定長
宣言的エフェクト定義
- YAML/JSON でエフェクトを定義し、コード生成
6. 結論
6.1 metadata.json のバイトコードへの影響
| 側面 | 評価 | 説明 |
|---|---|---|
| Opcode値の定義 | ✅ 良好 | 自動同期されている |
| 条件/コスト値 | ✅ 良好 | 自動同期されている |
| Python enumとの整合性 | 🟡 リスクあり | 手動管理のため将来的に不整合の可能性 |
| ビットマスク定数 | 🔴 不整合あり | Python/Rustでビット位置が異なる |
6.2 複雑さの評価
| 側面 | 評価 | 理由 |
|---|---|---|
| パーサー | 🟡 中程度 | 分岐は多いが構造は理解可能 |
| ビットマスク | 🔴 過度に複雑 | 競合あり、文書化不十分 |
| コンパイラ | 🔴 過度に複雑 | 400行の単一メソッド、15+分岐 |
| 保守性 | 🔴 低い | 二重定義、暗黙のビット操作 |
6.3 最優先すべき課題
- Color Filter のビット位置修正 (Rust側に合わせる)
- ability.py の enum を自動生成に切り替え
- _compile_single_effect の分割リファクタリング
付録: 関連ファイル一覧
| ファイル | 行数 | 役割 |
|---|---|---|
data/metadata.json |
323 | 定数定義のマスター |
engine/models/ability.py |
1852 | 能力定義・コンパイル |
tools/sync_metadata.py |
349 | 定数同期スクリプト |
engine_rust_src/src/core/generated_constants.rs |
275 | Rust定数 (自動生成) |
engine_rust_src/src/core/logic/filter.rs |
150+ | Rustフィルタロジック |
tools/verify/bytecode_decoder.py |
307 | バイトコードデコーダ |