037 引っ越しカニ合戦
主判断：小さな殻で守るか、裸で走って別の殻へ移るか。

起動
Python 3.10以降。実行時依存は requirements.txt のPyxelのみ。
Windows: setup.batを一度実行後、play.bat。パスに日本語・空白可。
macOS/Linux: bash setup.sh、その後 bash play.sh。
開発環境専用launch.shは納品先では不要。play.bat/play.shは単独フォルダで動く。
python app.py --baseline は比較用の大殻移動15tick版。通常は24tick。
python -m unittest test_model test_ui -v で純粋モデル/UI回帰。

操作
SPACE開始。矢印は保持で移動、小殻15tick・大殻24tick・裸8tick。
Zは新しい押下で足元の空殻へ入る／殻を出る。保持しても連続出入りしない。
Pは停止・説明。R同じ浜へ、1〜3状況選択、M表紙。画面遷移後は操作キーを一度離す。
1tick=1/30秒。満潮は450tickごと三回。最終累計が多ければ勝ち、同点は引分。
裸は領域なし。出た殻も最後の持主の陣地。相手が入れば所有移転。
小殻は床距離1、大殻2。白い餌だけ1点。最短距離で所属、異なる所有者の同距離は0。
餌のP/Eと殻の色・サイズ番号で区別。壁/水は床距離を遮る。攻撃はない。
殻を持ったまま別の殻のセルへは入れない。裸なら空殻へ行ける。殻は重ならない。
相手は全盤面だけを見る。15tickごと目標を固定、赤枠が目的地。未来の入力は知らない。

3状況・再現
A 今の殻で届く：初期維持9:9、移住9:6。
B 大きい殻の届く湾：初期維持3:15、早い大殻移住9:6、第一満潮後の移住3:15。
C 空けた殻も陣地：初期維持9:12、旧殻を残す二拠点12:9。
上はモデルの自動操作結果。experiments.pyが入力列・状態hashをpolicy_results.jsonへ保存。
人の楽しさや最短解の証明ではない。裸で走り続ける・連打・待機も合法。

設計候補からの変更
Bの候補餌十字は小殻だけで5個、広い殻の最大数も5個だった。
餌を(2,2),(3,1),(4,2),(5,1),(6,2),(6,4),(7,4)へ広げ、最大数を小3/大5へ。
人の開始を(1,3)から(2,3)へ変え、空大殻への完全対称な競合を避けた。
殻の重なりは、見た目と入居対象が食い違ったため禁止し、UIと両者の移動判定へ明示。
これらは設計修正。以下の一変更比較に混ぜていない。

一変更比較
比較用の反実仮想。旧版の制作史ではない。
同じ確定済みB盤面で大殻移動間隔だけ24/15tickを変更。
大殻取得後tick410から(7,3)へ向かう同じ閉ループ方策で、24は8:9、15は9:8。
方策は行き先まで矢印を保持。状態に従うため生キー列の同一性は主張しない。
同じ場所で早く陣地を保つ策は両版9:6で成功。差は広さでなく満潮への到着時刻。
experiment_results.jsonに両版の入力と軌跡、comparison_*に実レンダリングを収録。

素材/検証
assets/glyphs.jsonはNoto Sans CJKから生成した12px日本語ビットマップ。
assets/NOTO-LICENSE.txtのSIL Open Font Licenseを同梱。文字の画面内境界は全状態テスト。
実映像media/moving_shells_automatic_silent.mp4は自動操作・無音、Cの二拠点と満潮の抜粋。
GUI実操作、モデル検証、映像、人の試遊は別々にQA.txtへ記載。
Windowsネイティブ起動、実聴、人の新作試遊は未確認。制作端末はLinux。
