029 ずれる星座
実装・機能検証済み／面白さは人による確認待ち

そろった星を残したいなら、回す枝の根元を選ぶ。
光の枝で結ばれた星座盤。中心を選んで、その先の星だけを回す小さなパズルです。
3つの手作り配置。時間制限、残機、減点、待機操作はありません。

起動
Windows: Python 3.10以降を用意し、setup.batを一度実行。以後play.bat。
単独フォルダーだけで動作します。BATはASCII・引用済みパス・失敗時pause。
macOS/Linux: ./setup.sh の後 ./play.sh
Pythonから: python app.py
実装依存: Pyxel 2.9.9。動作確認はクラウドLinuxです。
Windows実機GUIと音の実聴は未確認です。ゲームと動画は意図的に無音です。

操作
最初の画面: 左右でA/B/Cを選ぶ、SPACEで開始。
上下: 基点をO→A→B→C→Dの存在するID順で選択（端で循環）。
右: 時計回り90度。左: 反時計回り90度。矢印は一つずつ。
SPACE: 時計回り後の位置予告を表示/非表示。小さなR輪が予告です。
Z: 直前の確定回転を一つ戻す。R: 同じ配置を最初から。
P: 説明と停止。M: 星座選択へ。成功後N: 次の配置へ。ESC: 終了。
入力は押下1回につき1行動。長押しでは回転や基点選択を繰り返しません。
開始/次面/停止/再開/リセット/選択画面への遷移は、操作キーを全て離してから受け付けます。

読めるルール
・白い二重輪の星が中心。親から子へ矢印が向きます。
・黄色の枝/星はその中心の全子孫。中心自身、祖先、別枝は残ります。
・星ごとにIDと形が違います。O=固定の輪、A=四角、B=三角、C=丸、D=ひし形。
・同じID/形の中抜き目標へ全星が重なれば成功。色だけに依存しません。
・葉には「葉」と表示。選ぶと「この先に枝はありません」。回転しても手数/履歴は増えません。
・盤外または星同士の重なりが発生する候補は全体を拒否し、理由と該当IDを表示します。
・光の線は交差できます。途中の回転弧は衝突判定しません。離散の星座盤です。
・一度合った星を動かしても合法。正当な別順を隠し条件で排除しません。

幾何の定義
格子点はx右/y下、0..6。根Oは固定。
時計回り: 中心からの(dx,dy)を(-dy,dx)、反時計回りは(dy,-dx)。
全子孫の旧世界座標を、選択星の旧世界座標の周りで1回ずつ一斉に変換します。
子の位置を更新してから孫へ再帰的に加算する処理ではありません。
Stateは整数の世界座標と回転数。木の親関係は不変Level。描画/選択/音/時刻は解判定に入りません。
終端は全座標の一致から導出。undoで座標・手数・履歴・終端を戻します。

採用した3面（設計候補から座標変更なし）
A 枝ごと一回: O時計回り。最短1、到達12状態、最短列1通り。
B 合った星を置いておく: O時計回り→A反時計回り。最短2、到達12、最短列2通り。
C 枝の中にもう一枝: O反時計回り→A時計回り→B時計回り。最短3、到達36、最短列6通り。
B/CはOだけでは解けません。CのDは初期一致していますが、固定し続ける制約はありません。
ソルバーは全到達グラフを列挙。状態候補上限4^内部節点数は16/16/64、実測状態数とは別です。
最短は任意の参考値で、プレイの制限にはしません。可解性は面白さの証明ではありません。

収録物
media/shifted_stars_automatic_silent.mp4: 実Pyxelの自動入力による機能確認映像。無音。
全719元GIFフレームを一度ずつ30fpsへ配置、23.966667秒。人の試遊や壁時計録画ではありません。
media/runtime_*.png: 実Pyxelから保存した画面。Bで全体を回しすぎる→戻す→枝だけ直す場面を含む。
media/experiment_baseline.png / experiment_highlight.png: 子孫強調だけを替えた同一状態。
model.py / solver.py / solver_results.json: 純粋モデル・全探索・リプレイとhash。
test_model.py / test_ui.py / test_results.txt: 不変量、入力遷移、全表示・日本語字形・文字範囲。
NOTE.txt / X_POSTS.txt: 公開していない日本語原稿。
QA.txt: 確認範囲と未確認点。EXPERIMENT.txt: 比較の条件。

再検査（作業用。プレイには不要）
python -m unittest discover -s . -p "test_*.py" -v
python solver.py
python experiment.py
python tools/test_portability.py
python app.py --headless --demo
python tools/export_video.py （Pillowとffmpeg/ffprobeが必要）
python tools/capture_comparison.py
python tools/capture_comparison.py --baseline
python tools/build_font.py （PillowとNoto CJK元フォントが必要）
全テキストファイル入出力はUTF-8を明示。cp932既定・日本語/空白パス・任意cwd回帰を別実行。
元のコード/絵はMIT、同梱字形はNoto Sans CJK由来のSIL OFL。assets/NOTO-LICENSE.txtを参照。
