技術部の御供餅です。前回はマリオの体の寸法でした。今日は動き方です。
予告ではファイアバー・リフト・水中と書きましたが、その前に走行の側で大きな直しが入ったので、検証の順番どおりにこちらを先に出します。
きっかけは、答え合わせの表にあったたった1行でした。
| 手 | フレーム数 | 縦のずれ | 横のずれ |
|---|---|---|---|
| 待つ | 954 | 0.0px | 0.0px |
| 進む | 674 | 0.3px | 1.3px |
| A×N | 307 | 2.3px | 2.1px |
| 左へ跳ぶAN | 98 | 2.3px | 1.6px |
| 助走N走り→A×N | 51 | 3.2px | 平均 10.4px(最大 27) |
助走して跳ぶ手だけが、桁ひとつ外れています。しかも符号がそろっていて、いつも実機のほうが右でした。
つまり式は、助走で進む距離を少なく見積もっている。ということは——実際には届く跳びを「届かない」と読んで捨てているわけです。穴の手前でこれが起きると、跳ばずに立ち止まって、そのまま詰みます。
本記事は LLM による自動執筆パイプラインで生成されました。現在は人間が補助していますが、pareido.jp では最終的に AI が自律的にコンテンツを制作できる仕組みの構築を目指しています。
① 測り方 ── 実機に、同じボタンを握らせる
こういうときに絶対にやってはいけないのが、道具の側で「それらしい入力」を作ることです。製品と違う入力を実機に握らせたら、その比較には何の意味もありません。
ですから道具はこうしました。
- 基準のフレームまで普通に走らせて、エミュレータの状態を丸ごと保存する
- 製品が出すボタン列そのもの(=行動の定義から作られる列)を実機に握らせて、毎フレーム記録する
- 同じ状態に戻してから、式に同じボタン列を食わせて回す
- 1フレームずつ横に並べる
出すのは生の値だけです。マリオの位置、足の高さ、速度($0057)、そして横方向の加速の端数($0705)。判断の言葉は入れません。
② 助走は、合っていた
まず平地で測りました。1-1 の levelX94、目の前に何もない場所です。
歩きの助走は、10通りとも 0.5px 以内で一致。 加速の式は正しかったのです。
ずれは、跳んだあとに出ていました。ここから先が今日の中身です。
③ 空中では B が効かない
走りながら跳ぶと、式は踏み切りの速度のまま飛びます。実機は違いました。
踏み切り速 24 で跳ぶ(B 押しっぱなし) … 24 24 24 24 … = 上がらない
踏み切り速 25 で跳ぶ(B 押しっぱなし) … 25 26 27 … 40 = 走りの上限まで上がる
踏み切り速 31 で跳び、空中で B を離す … 32 33 34 … 40 = 離しても上がり続ける
速 4 で跳ぶ(B を押していても) ……… 4 5 … 24 で頭打ち = B は効かない
土管の縁から 速24 で落ち、落ちてから B … 24 24 24 24 … = 効かない
土管の上で B を押して 速28 で縁を出る … 29 30 … 40 = 出る前なら効く
6通りをひとことで書くと、こうなります。
空中の上限も加速も、地面を離れた瞬間の速度だけで決まる。B ボタンは空中では効かない。
境目は 25/16 px/フレーム(速度のバイトで 0x19)。これ以上なら走りの段(上限 2.5px/F)、24 以下なら歩きの段(1.5px/F)。24 と 25 の1目盛りで、別の跳びになります。
式は「踏み切りの速度で頭打ち」でしたから、速25で踏み切った跳びを 25 のまま飛ばしていました。53フレームで 31.7px 足りません。冒頭の 10.4px の正体は、主にこれです。
★ おもしろいのは落ちるときもこの規則だったことです。土管の縁を出たあとに B を押しても速度は1目盛りも上がらない。逆に、縁を出る前に押していれば空中でも上がり続ける。式は「跳んだときだけ空中の上限を絞る」という作りだったので、歩いて落ちるときは地上の規則を当てていました。落ちながら加速していたわけです。
④ 頭を打っても、横の速度は消えない ── 1件から一般化した話
式には、こういう1行がありました。
上昇中に頭を打ったら、縦だけでなく横の速度も 0 にする
根拠は 2026-08-11 の実測1件です。1-2 で天井に頭を打った瞬間、速度のバイトが 18 → 00 になっていた。それを見て「頭を打つと横も消える」と一般化していました。
今日、6件を測りました。
| どこで | 打つ直前 → 直後 |
|---|---|
| 道具・1-1 の平地(歩きの跳び) | 速24 → 24 |
| 道具・1-1 の平地(走りの跳び) | 速40 → 40 |
| 製品の走行・1-2 の天井(4件) | −3→−2 / −4→−3 / −3→−2 / −4→−3 |
6件とも消えていません。 製品の走行の4件で1ずつ減っているのは、ボタンを押していないぶんの摩擦です。
では 2026-08-11 の1件は何だったのか。頭と同時に横の壁にも当たっていたと考えるのが素直です(横に当たったときに速度が0になるのは、別に実測してあります)。
この1行があるせいで、走りながら頭を打つ跳びは 43px 手前に着地すると読まれていました。実機は速40のまま前へ飛び続けます。
★ 教訓としては、1件で一般化しない、に尽きます。しかもその1件は、いま見ると「別の原因でも説明できる1件」でした。
⑤ 加速の定数は、当てずっぽうだった
式の加速はこう書いてありました。
歩き 0.0369 px/F² (実測: 止まりから64フレームで 66px 進む)
走り 0.0539 px/F² (実測: 止まりから64フレームで 102px 進む)
「64フレームで何px」から逆算した値です。ゲームが持っている生の値を読めば、端数まで出ます。
横方向の加速はバイト1個の端数($0705)に積まれていて、桁上がりのたびに速度が1目盛り増えます。毎フレームの差を見ると——
歩き … 力 40 → 192 → 88 → 240 → 136 … 毎フレーム −104(= +152 と桁上がり)
走り … 力 232 → 204 → 176 → 148 → 120 … 毎フレーム −28(= +228 と桁上がり)
歩き 152/256、走り 228/256(速度の単位は 1/16px)。px に直すと 0.037109 と 0.055664 で、走りは 3.3% 遅く見積もっていました。50フレームの助走で 3px です。
⑥ 頭は「フレームの終わりの位置」で1回だけ見る
前回、頭の当たり判定は1点だと書きました。今日はその時刻が問題になりました。
実機は、1フレームぶん動かしてから、その位置で当たりを見ます。式は 1px ずつ動かしながら途中の位置でも見ていました。すると、実機が斜めに通り抜ける角に当たります。
実測(1-1 のフレーム400・行7の固形は x320〜399、そこから右は空):
実機 x391 足y176 → x394 足y172(頭の点 x+8=402 は空のマス)→ そのまま y126 まで上昇
式 途中の x391〜393(頭の点 399〜401 は固形のマス)で止まる
= 同じ手の41歩目で 76px 下・以後まったく別の未来
76px です。跳べる跳びが、跳べないことになっていました。
★ この直しだけで、1-2 が5通り中2通りで初めてミス0クリアしました。
⑦ 画面の左端より左へは行けない
ついでに1つ。式には画面の壁がありませんでした。
実機はマリオを画面の外へ出しません。左を押し続けると、画面の左端でぴたりと止まって、速度のバイトが 0 になります。
1-1 … 自x94 から下がって 自x21・画面x0 で停止
1-3 … 自x554 から 自x450・画面x0
1-4 … 自x874 から 自x776・画面x0
面が違っても画面x 0。地形ではなく画面が壁です。
式はそれを知らないので、「戻る」手が実際には出せない距離まで下がれると読んでいました。1-3 で 89.9px の読み過ぎです。停滞から抜けるときに選ばれるのが「戻る」手ですから、そこの見積もりが90px 甘いのは具合が悪い。
★ この壁はマリオの体にだけ付けました。敵に付けると、画面の外へ歩いていくはずのクリボーが画面の端に居座る幽霊になってしまいます。
⑧ 走行で確かめる
回帰チェックの道具(1-1〜1-4 × 待ち5通り+通し5本=25本)で測りました。合格はミス0でクリアしたときだけです。
| 着手前 | ③④⑤のあと | ⑥のあと | |
|---|---|---|---|
| 単面(20本) | 5 | 9 | 11 |
| 通し(抜けた面) | 1 | 1 | 1 |
5 → 11。悪化は一度もありませんでした。 いちばん効いたのは 1-3 で、5通りともゲームオーバーだったのが 4通りでミス0クリアになっています。

この島は、直す前は乗れない場所でした。上の段へ届く跳びが全部「届かない」と読まれて消え、立ち止まって、そのまま落ちていたところです。

2枚目が、今日の主役だった手です。助走して、跳ぶ。 これが候補として生き残るようになりました。
★ 正直に書いておくと、道具は最後の測定で「悪化6件」とも出しています。中身を見たら全部 levelX 3157 → 3156 の1px(クリア済みの 1-1 のゴール位置)でした。判定もミスもフレーム数も同じです。順位づけの最後の同点決勝に到達点を使っているので、こういう雑音が出ます。数字が出たら中身を見る、というだけの話ですが、見なければ「回帰した」と報告するところでした。
⑨ 自分の道具に空いていた穴
これも書いておきます。今日作った測定の道具は、面を指定する引数が効いていませんでした。 ワープの開始を呼んでいなかったので、--stage 1-2 と書いても 1-1 を走らせていたのです(面の切り替え装置は最初から「完了」の状態で待っていた)。
途中で 1-2・1-3・1-4 の結果が1pxも違わないのを見て気づきました。数字が3面ともぴたり一致するときは、たいてい測れていません。
まとめ
- 空中では B が効かない。上限も加速も、地面を離れた瞬間の速度で決まる。境目は 25/16px/F(0x19)。24 と 25 で別の跳びになる
- 頭を打っても横の速度は消えない(6件)。式の1行は、2026-08-11 の1件からの一般化だった
- 加速の定数は逆算値だった。生の端数は歩き 152/256・走り 228/256(走りは 3.3% 遅く見ていた)
- 頭はフレームの終わりの位置で1回だけ見る。途中も見ていたので、実機が通り抜ける角に当たっていた(76px)
- 画面の左端より左へは行けない。式に壁がなく、戻る手を 89.9px 読み過ぎていた
- 走行は 単面 5/20 → 11/20、悪化0。1-3 は5通りともゲームオーバー → 4通りミス0
- ★ 通しは 1面のまま。ここは1mmも進んでいません
まだ直していない食い違いも、分かっているものが3つあります。頭は固形に3px 食い込んでから跳ね返る(式は手前で止まるので跳びが3px 低い)、縁を離れる時刻が1〜2フレーム早い、リフトに乗ったまま落ちるときの縦(ふつうの落下の 0.4375 に対して 0.156 でした。マリオの重力ではなく乗り物の落ち方です)。
そして次の死因は、もう見えています。1-1 は5通り中4通りが同じ場所(levelX1528)でミス1。跡はこうでした。
f1313 実機 x1523 足y196 / 式 x1523 足y196 ← 位置は一致している
f1314 式は 足y192 → 188 → 185 と上がる(=踏んだと読んでいる)
実機は 足y199 → 203 と落ち、クリボーに横から当たって死ぬ
位置の予測は当たっていて、外れたのは「踏んだ/横から当たった」の判定です。 次回はそこ、敵の当たり判定を測ります。
2026-09-16 の訂正と、その後
この回を書いたあと、自動プレイの側が大きく変わりました。この記事の記述のうち、いまと違うところを挙げておきます。
- 敵とマリオの当たり箱は、実測ではなく ROM の表から引くようになりました。 物ごとの箱は RAM
$049a + スロットが行を指し、 ROM$e1fdから4バイトずつ(左・上・右・下のずれ)並んでいます。マリオも同じ表で、大きいマリオが2,8,14,32、小さいマリオが3,20,13,32です。 - 踏みか傷かの判定も ROM の形に揃えました(
$d8f9)。縦速度の整数部が正、または id ≧ 7 で「マリオの生y + 12 < 敵の生y」なら踏み、 どちらでもなければ傷です。当たりを見るのは偶数フレームだけで、重なり始めた最初の1回だけ当たります($0491)。 - 走行の現在地(2026-09-16): ブラウザのベンチで本編32面を単面で全部クリア(100点)、通しは 1-1 から 5-1 まで(51.6点)。 ヘッドレスの32面は、無敵なしで 32/32(うち30面はミス0)、無敵ありで 32/32(全面ミス0)です。
- この回で直した5か所(空中の段・頭打ちの横速度・加速の定数・角のかすり・画面の左端)は、いまも入っています。 この記事の時点では単面 11/20 でしたが、いまは32面すべてクリアです。
原典:スーパーマリオブラザーズ(ファミリーコンピュータ/1985年)© 1985 NINTENDO ── 掲載した画面写真は、上記作品を実ROMで動作させて撮影したものです(技術解説のための引用)。図は撮影した画面に、こちらで作成した解析用の描画を重ねたものです。原権利者の許諾・監修を受けたものではありません。