011 反射便 — 一折りだけの郵便局
Python 3.11+ / Pyxel 2.9.9

白い鏡で封筒を一度だけ折り返し、塀の裏の郵便受けへ届ける照準パズル。
最初の便は直射でも成功。次は上、最後は横の鏡を使う。
全３便。考える時間・試射数に制限はありません。音なしで遊べます。

起動
Windows: Python 3.11以降を導入し setup.bat、次に play.bat。
macOS/Linux: bash setup.sh、次に bash play.sh。
インストール後にフォルダを移動したら setup を再実行してください。
この配布物に仮想環境は含みません。launch.sh は制作環境専用です。

操作
タイトル: 左右で便選択、Spaceで開始。Escで終了。
左右: 照準60度/秒。上下: 12度/秒の微調整。
Space: 発射。飛行中は回収だけ。次の押下で再発射。
Z: 直前の試射角へ戻る。飛行中は回収も行う。
R: 同じ面を初期状態から。P: 一時停止。N: 配達後に次の便。
T: 直前の軌跡を表示/非表示。F12: 制作確認用スクリーンショット。
--baseline は前回軌跡なしで起動。表示だけの比較用です。

見分け方
白い面＋斜線=鏡。れんが=止まる壁。黒い丸い穴=郵便受け。
試射後の破線と×が結果を残す。成功時は穴にチェックと広がる輪。
白い鏡で2回目の接触は「折返しは１回まで」。飛行中も狙いを調整できます。
必須条件は配達のみ。反射回数、速さ、試射回数を得点化していません。

実装と検証
model.py はPyxel非依存。距離の線分掃引、最初の接触優先、反射後の余り時間を処理。
30fpsの各描画で1/120秒を4回。半径2の封筒、速さ96px/秒。
矩形壁は半径ぶん四角く膨らませる保守的な近似。角だけ最大約0.83px早く止まります。
角の同時接触はX法線を優先。壁と受取の同時接触は壁を優先。
各刻み4回まで接触解決、接触後0.01px離す。2反射と6秒で有限に終端。
受取の中心許容半径 A=5/B=6/C=7px。鏡の接触面は壁から封筒半径ぶん手前。
B/Cの口だけ拡大した結果は NOTE.txt に記録しています。

python -m unittest -v
python experiment.py
python tools/test_portability.py
テストは技術確認です。Linux実GUIで入力・停止・全３面成功を確認済み。
Windows実機のGUI・人による面白さ評価は未実施。
media の動画は実際のPyxel描画を自動操作した無音映像。人の操作記録ではありません。
PNGとreplay.jsonに対応し、replay.jsonにモデルと画面ソースのSHA-256を収録。

動画の時間軸
MP4は719枚をゲーム更新と同じ30fpsで再配置した23.966667秒、384×328、音声なし。
元GIFは時間単位の丸めにより21.57秒ですが、MP4では元の各フレームを1回ずつ保持して補正しています。
ヘッドレス実Pyxel描画の自動操作デモであり、実時間の画面録画ではありません。
