061 返事の遅い無線 — 五段階で作るPyxel教材

動作環境
Python 3.11以降、Pyxel 2.9.9。モデルとテストは標準ライブラリのみです。
教材フォルダへ移動してから実行してください。以下のpythonはPython 3.11以降の実体です。

準備（最初の一回）
python -m venv .venv
Windows: .venv\Scripts\activate
macOS/Linux: source .venv/bin/activate
python -m pip install -r requirements.txt

起動
python 01_clock.py
python 02_commands.py
python 03_delay.py
python 04_candidates.py
python 05_undo.py

各段階は独立した一つの.pyです。他の段階やassetsがなくても起動できます。
別フォルダへコピーして名前を変えることもできます。Pyxelの導入は必要です。
全文の解説・期待結果・練習はLESSON.md、構造化本文はlessons.json。
差分はdiffs/01_02.diffから順に読みます。

操作
Space: 一刻待つ。偶数刻だけ一歩進みます。
2: 安全路、3: 橋T経由、4: 停止（02以降）。
1: 今どこか質問（03以降）。X: 一判断戻す（05のみ）。
R: 初期化。Esc: 終了。全操作キーを離してから次を押します。
通信待ち中の数字キーはBUSYで拒否され、時間も送信数も変わりません。
Spaceで一刻待って返信を受け取ります。読む時間には制限がありません。

順序が大切
新しい刻→受信/指示と移動前標本→偶数刻の歩行→古い標本で返信→終了判定。
03は本人の位置を見せて時刻差を学習。04/05は現在候補だけを表示。
原作Aの真相はS出発に固定。Rで変わりません。12刻ちょうどのH到着は成功。

単体テスト（Pyxelも原作も不要）
python -B test_stages.py

任意の原作照合
原作のmodel.pyがある「061_delayed_radio」フォルダを環境変数
PYXEL_ORIGINAL_061へ指定して、同じtest_stages.pyを実行します。
Windows PowerShell例: $env:PYXEL_ORIGINAL_061="C:\path\to\061_delayed_radio"
macOS/Linux例: export PYXEL_ORIGINAL_061="/path/to/061_delayed_radio"
存在しない場合は原作照合3件のみSKIPと表示します。
通常の教材テストを省略したり、原作を取得する通信を行ったりはしません。

実Pyxelの自動描画検証（導入済みPyxelが必要）
python -B qa/render_check.py
各段階の初期・操作後・改名一ファイル起動の画像と状態をqaへ出力します。
Linux音声デバイス不要環境ではSDL_AUDIODRIVER=dummyを使用します。
qa/render_check.py内でも子プロセスへこの値を設定します。
一段階の例:
python 03_delay.py --headless-smoke --demo-checkpoint --screenshot qa/check.png
必要なら --state-output qa/check.json を追加できます。
--framesは初期4〜600、デモは2×操作数+4〜600。小さすぎる値は拒否。
QAオプションは--headless-smoke必須、画像は.png、状態は.jsonです。
不正値はPyxel初期化前に終了コード2で拒否します。

最終ファイル照合
python -B qa/verify_freeze.py
FROZEN_SHA256.json自身を除く全配布ファイルと集合を照合します。
画像の再生成や編集をするとSHA-256が変わることがあります。
検証後に内容を変えた教材を、凍結済み原本と取り違えないための確認です。

原作との違い
01はSを公開して安全路固定。02は即時指示で通信待ちなし。
03は返信遅延を導入するが位置公開。04/05は原作Aの通常モデル。
数字の直接指示・ASCII画面は教材用の簡略操作です。
原作のB/C、標本時刻の比較モード、表紙/停止、日本語表示、再現記録保存は省略。
英数字画面なので日本語フォントを読みません。
同梱assetsは元のバイトと権利表示の保存用です。

権利
原作LICENSE.txtを変更せず同梱。LICENSEは同一バイトの別名です。
全五段階の先頭にも原作ライセンス全文をコメントで載せています。
assets/glyphs.jsonとassets/NOTO-LICENSE.txt、assets/PYXEL-LICENSE.txtは原作の同一バイト。
Noto由来字形はSIL OFL 1.1。コードのMITと同一視しないでください。

今回の確認と限界
qa/REVIEW.md、portable-tests.txt、full-tests.txt、render-results.jsonを参照。
実Pyxel Linuxヘッドレス・自動の意味入力で描画した証拠です。
OSキー入力、音の実聴、人によるプレイ/面白さ、Windows/macOS実機、ブラウザ動作は未検証。
qa/*_*.jsonの状態は真の出発点を含み、初見の推理に対するネタバレになります。
