029 ずれる星座: 木と世界座標の五段階教材
原作C「枝の中にもう一枝」を採用。01/02は練習、03からCの完成パズル。

必要環境
Python 3.11以上、Pyxel 2.9.9。検査はcloud Linux / Python 3.12.14。
python -m venv .venv
仮想環境を有効化して python -m pip install -r requirements.txt
個別に入れる場合: python -m pip install pyxel==2.9.9

実行
python 01_tree.py
python 02_world_rotation.py
python 03_pivot_puzzle.py
python 04_preview.py
python 05_undo.py
各ソースは一つだけ別フォルダーへコピーしても実行できます。
パスに空白があれば python "日本語 フォルダー/05_undo.py" のように引用します。
教材の実行に原作・画像・フォント・隣の教材は不要。Pyxelだけ別途必要です。

段階
01 親配列をたどって子孫を選ぶ。位置は変えない。
02 Oを中心に全子孫を一回ずつ90度回転。目標・成功判定はまだない。
03 上下で基点、左右で回転。同じIDの目標へ全員そろえば完成。
04 SPACEで時計回り候補を表示。確定するまでは状態不変。
05 Zで直前の確定回転をUndo。完成後も戻せる。
全段階Rで初期化、Escで終了。各操作の後に全キーを離します。

03以降の例
左→下→右→下→右: O反時計回り→A時計回り→B時計回り、MOVES 3で完成。
Dは初めから目標に一致していますが途中で動かしてかまいません。
初期位置で下→下→左: DがAに重なるためCOLLISION、手数0のまま。
画面x右/y下。右は(dx,dy)→(-dy,dx)。線の交差と回転途中の弧は衝突判定しません。

読む順序
LESSON.mdの日本語本文→各ソース→diffs/の段階差分。
lessons.jsonは本文・正確な抜粋・キー列と期待State、lesson_meta.jsonは原作との差分。
qa/reference_fixture.jsonは原作から生成した36到達状態の規則比較。

再検査
python -B -S test_stages.py
python -B -S qa/cp932_regression.py
python -B qa/render_check.py
python -B qa/verify_freeze.py
最初の二つは標準ライブラリだけ。描画検査にはPyxel2.9.9が必要です。
必要ならPYXEL029_ORIGINALを原作029フォルダーへ設定してtest_stages.pyを実行するとlive比較します。
fixture再生成: python -B -S qa/generate_reference.py "原作029フォルダー"
CLI自動確認: python 05_undo.py --headless-smoke --demo-checkpoint --screenshot "確認.png" --state-json "状態.json"
自動出力オプションは--headless-smokeと一緒に使ってください。
固定hashは納品時の内容を確認します。再生成したログや画像が変わればhashも変わります。

検査範囲と権利
実Pyxel headless自動描画、模擬キー列、単一ファイル・日本語/空白パス・別cwdを検査。
実ブラウザー、ネイティブWindows/macOS、OS経由の実キー入力、人による試遊、音の実聴は未確認。
音は実装しません。自動検査だけから面白さや理解しやすさは主張しません。
原作MIT全文を全5ソース先頭とLICENSE.txtに保持。
元ライセンス末尾が参照するassets/NOTO-LICENSE.txtも保持しますが、教材はNoto字形を使用・収録しません。
