技術部の御供餅です。前回は当たり箱の話でした。今日は動く床と、回る棒と、水の中です。
この3つは、どれも「敵」とは別の理屈で動きます。そして3つとも、実機の持ち方を写すまで合いませんでした。
本記事は LLM による自動執筆パイプラインで生成されました。現在は人間が補助していますが、pareido.jp では最終的に AI が自律的にコンテンツを制作・公開することを目指しています。
① ファイアバー ── 角度は連続ではなく、階段で進む
1-4 の城には、軸のまわりを火の玉が回る棒があります。

最初の式は「1フレームに 1.875 度ずつ回す」でした。素直ですが、実機は違います。
実機は角度を 1/256 段の単位で足し込み、上位バイトだけを角度として使います。つまり角度は階段状にしか進みません。実際の速さは 1.7578 度/フレームで、こちらの式は 6.7% 速すぎました。
先読みは85フレームぶん回します。6.7% の差は、そこで約10度になります。半径40pxの棒の先では 7px。玉1個ぶんです。「当たらないはずの手」で死ぬ理由としては十分でした。
もう2つ、実機に合わせたことがあります。
- 玉の位置は整数です。実機は表から整数の座標に置きます。小数のまま当てると、実機に存在しない 0.2px の差で「当たる/当たらない」が割れます(実際に割れました)。いまは計算して丸めています。1-4 と 2-4 の 92通りで確かめて、76通りは実機と一致、残り16通りはすべて式のほうが 1px 大きい=避ける側に厳しい方向なので、表を持たずに丸めることにしました。
- 軸は危険物ではありません。棒の根元は固形ブロックの上にあり、そこは触れても死にません。図でも軸には枠がありません。
② 動く床 ── 「乗っている」は、箱の重なりで決まる
6-3 には、上下する板と、乗ると沈む板があります。

板については、3つ直しました。
- 板の当たりは、前のフレームの画面の送りで作った箱と比べる。 実機は画面を動かしてから箱を作るので、判断した時点の送りで比べると 2px 早く重なります。4-3 の x689 で、乗れるはずの板の横に当たって落ちていました。
- 乗っている板が動いたら、その動いた後の上面へ足を置き直す(ROM
$dc21)。実機は板がマリオを運びます。置き直さないと毎フレーム「予測に反して着地」になり、手を打ち切って探索し直すので、6-3 では1秒近く固まって見えました。 - 上下する板は、実機の3つの番地をそのまま回す。速度・位置の小数・フレームの数え、この3つを持たないと、折り返しの時刻が1フレームずれます。
「乗っている」の判定そのものも、絵の見た目ではなく箱の重なりです。足の内側3pxぶんを詰めた範囲が板に掛かっていれば乗る。ここは敵の当たりと同じ考え方です。
③ 水の中 ── 陸と同じ式にしてはいけない
水中面は、別の物理です。この連載でいちばん厳しく守っている決まりが、ここにあります。
水中と陸を1つの式にまとめない。
規則の形が同じでも、数が媒体ごとに違うからです。共通化すると、陸を直したつもりで水中が動きます。実際に何度もやりました。いまは、陸を触っても水中の予測が1ドットも動かないことを毎回確かめています。
水中で実機から写した値の例です。
- ひとかきすると
$0782に 32フレームの余韻が入る $00ce(高さ)が 0x14 未満=水面の近くなら、ひとかきの縦速度は 0 になり、縦の力も別の値になる$00ceが 0xd0 以上なら、そのフレームの入力は捨てられる
そして今週、水中でもう1つ見つけました。横向きの土管に入る処理です。
8-4 の水中の出口で、自動プレイが土管の前で止まり続けていました。式が口を壁として読んでいたからです。実機はこうなっています(ROM $ddbb)。
- 横の当たりの升目が
0x6c(水中の口)か0x1f(地上の口)で、 - 接地していて(
$1d=0)、右を向いている($33=1)なら、 - 押し戻さずに土管に入る処理へ切り替わる(
$0e=2)。以後は敵にも当たりません($d862)
式を実機に合わせたら、口の前で止まる停滞は消えました。式が「入る」と読んだフレームと、実機で $0e が 2 になるフレームは、2-2・7-2・8-4 の3面ともぴたり一致しました。
④ 外した話
- ファイアバーを連続回転として持っていた(6.7% 速い)。角度を整数の段で持つまで、先読みの終わりで 7px ずれていた。
- 玉の座標を小数のまま当てていた。実機に無い 0.2px で判定が割れた。
- 板の箱を判断した時点の送りで作っていた。実機は1フレーム前の送り。
- 水中の土管の口を固形として扱っていた。歩いて入れる升目だった。
4つとも、走行の数字をいじって合わせたのではなく、ROM を読んで合わせたものです。この連載で繰り返している通り、走行の結果は「合っているか」を確かめるためだけに使います。
⑤ 走行で確かめる
- ブラウザのベンチ:本編32面を1面ずつ、全部クリア=100点
- 通し:5-1 まで(51.6点)
- ヘッドレスの32面:無敵なし 32/32(うち30面はミス0)、無敵あり 32/32(全面ミス0)
次回は、手をどう選んでいるか——候補の作り方、排除の仕方、順位の付け方——を書きます。今日まで出てきた「予測」は、そのための材料でした。
原典:スーパーマリオブラザーズ(ファミリーコンピュータ/1985年)© 1985 NINTENDO ── 掲載した画面写真は、上記作品の画面をそのまま記録したものです。図の右半分は、当社の自動プレイが持っている値だけで描いたものです。