「あの頃AIがあったら…」第5回: AIにファミリーベーシック独自命令を教える

「あの頃AIがあったら…」第5回: AIにファミリーベーシック独自命令を教える — ファミリーベーシック, AI, 整数 AIテキスト

こんにちは、パレイド辺境部の橘です。

前回、VRAM を見ながら打つ自動タイピングで、取りこぼしは消えました。ブラウザのチャットから流し込んだコードは、最後の 1 文字までファミリーベーシックの画面に並び、RUN も通ります。

これで量産体制は安定しました。次は、バイブコーディングの「質」である書く BASIC そのものに手を入れます。

本記事は LLM による自動執筆パイプラインで生成されました。現在は人間が補助していますが、pareido.jp では最終的に AI が自律的にコンテンツを制作できる仕組みの構築を目指しています。

NEXT Iでひっかかる

第 3 回で書いたとおり、デフォルトの Claude は、INT() を平気で使おうとしたり、FOR 分の末尾を NEXT I と書いたりします。一般的な BASIC ではよく見る記述ですが、どちらもファミリーベーシックでは ?SN ERROR です。システムプロンプトに「整数のみ」「浮動小数点関数なし」と書いても、長めのプログラムになるとしばしば無視されます。

これは AI が悪いわけではなく、シンプルに学習データにファミリーベーシックの情報がほぼ存在しないためでしょう。そもそも知名度があるとはいえ、40年以上前のニッチな商品です。世の中の BASIC は MSX-BASIC や N88-BASIC、VB6 や QBasic など、どれも浮動小数点を持ち、NEXT I を許します。Claude にとって BASIC とは「そちら側の世界」です。1984 年の、2KB の、整数しか扱えず、NEXT の後ろに変数名を書くと怒る方言は、ほとんど未学習の外国語 に近い。

さらに厄介なのは、ファミリーベーシック特有の命令たち。SPRITEDEF SPRITEDEF MOVECGSETBGPUTPALET——このあたりは別世界級の独自性で、汎用 BASIC の常識をいくら積んでも降りてきません。

ファミリーベーシックは、AI にとって初見の言語と言っていいくらいの対象なのです。

リファレンスを丸ごと食わせる

対処はシンプルで、完全リファレンスを 1 枚の Markdown にまとめ、システムプロンプトの末尾に貼る ことにしました。制約の一行要約ではなく、命令表・関数表・エラーコード表・画面仕様まで、機械が参照できる形で全部渡します。 数KB程度のコンテキストになりますが、これにVRAM表示やプログラム情報、会話履歴等を追加しても、最近の LLM モデルなら問題なく扱えます。

たとえば命令セットが増えているV3では下記のようなイメージです。 ここで全バージョン分の情報を記載したくなりますが、ROM カセットを全バージョンお持ちの方も限られると思いますし、AI が扱いやすいように情報は絞ったほうが良いでしょう。 参考まで、今回自作した nesemu ベースのツールでは、局面によってAIに与える文脈を絞る処理を加えています。

あなたはファミリーベーシック(Family BASIC V3)のプログラマーです。
...(制約と出力ルール)...

## Family BASIC V3 完全リファレンス

以下は Family BASIC V3 の完全な命令・関数・エラーメッセージのリファレンスです。
コード生成時はこのリファレンスに記載された命令のみを使用してください。

...

リファレンスは公式マニュアルや moainet.org の BASIC 解説NesDev フォーラムといった有志の方がまとめてくれた情報をが参考になります。本体に付属するマニュアルは、保存状態の良いものは入手が困難です。

本人?のおすすめもあり、何度か試す中で、Claude が陥りやすいパターンを優先してプロンプトに列挙しています。 今回は Claude しか試していませんが、傾向はモデルによって多少異なるかもしれません。

## 最重要制約(LLMが間違えやすい点)

1. **整数のみ**: 16bit 整数 (-32768〜32767)。除算は切り捨て。
2. **変数名**: 英字1文字 + 数字1文字まで
3. **文字列長**: 最大 31 文字
...
9. **FOR/NEXT**: `NEXT` に変数名を書いてはいけない。
   `NEXT I` は構文エラー。常に `NEXT` のみ。
10. **小数リテラル不可**: `0.5` は書けない。100 倍スケールで代用。
11. **浮動小数点関数なし**: SIN, COS, SQR, LOG, EXP, ATN 等は存在しない。

人間にとっては「そんな細かいことまで」と感じる書き方ですが、LLM は 列挙されたルールを素直に守る 傾向があるので、暗黙の常識になりそうな箇所ほど明示的に否定する書き方が効きます。「ここは普通の BASIC じゃないよ」と、毎段落で念押しする感覚です。

また、文字コードはほぼ ASCII ですが、カタカナのコード体系は独自で混乱が見られる点も注意です。 ここは TypeScript 側でコーディングによって機械的に変換することで精度を上げています。

Few-shot は「マリオを歩かせるコード」

リファレンスだけでは、命令を知ってはいても、組み合わせ方を知らない という問題が残ります。ファミリーベーシックの独自命令群——SPRITE, DEF SPRITE, CGSET, DEF MOVE——は、単体の定義を読んでも初見ではまず正しく書けません。

ここで few-shot の出番です。第 3 回では「星を描いて」1 例だけでしたが、今回はリファレンス末尾に 公式マニュアル掲載のサンプル 6 本 を丸ごと貼り付けました。

  • サンプル 1: 6 種類のポーズのマリオを表示(スプライト基本)
  • サンプル 2: コントローラでマリオを左右に動かす(パッド入力)
  • サンプル 3: コントローラでマリオを歩かせる(歩行アニメーション)
  • サンプル 4: DEF MOVE で 8 方向に動かす(MOVE 命令の基本)
  • サンプル 5: コントローラで MOVE キャラクタを操作
  • サンプル 6: マリオをジャンプさせる

たとえばサンプル 3 は、SPRITE ON / CGSET 1,0 / DEF SPRITE 複数個 / STICK(0) でのパッド入力 / SWAP でのアニメ切替 / GOTO ループ、までひととおり入った完成コードです。

5 CLS
10 SPRITE ON
15 CGSET 1,0
20 DEF SPRITE 0,(0,1,0,1,0)=CHR$(1)+CHR$(0)+CHR$(3)+CHR$(2)
21 DEF SPRITE 1,(0,1,0,0,0)=CHR$(0)+CHR$(1)+CHR$(2)+CHR$(3)
... (中略)...
60 S=STICK(0):IF S=0 THEN 60
70 IF S>2 THEN 60
80 X=X+2:IF S=2 THEN X=X-4
...
1000 PAUSE 5:SPRITE C,X,Y:SWAP C,D

これを見せておくと、Claude は「あ、この世界ではこういう書き方をするのか」と理解します。LLM は定義より実例から吸う、という経験則がありますが、辺境のマシンほどその傾向が強く出ます。

加えて、DEF MOVE の第 1 引数で呼べる 16 種類のプリセットキャラクタ表 も併載しました。

番号キャラクタ名
0マリオ
1レディ
2ファイターフライ
3アキレス
15ニットピッカー

「マリオっぽいキャラを出したい」という指示に対し、AI は DEF MOVE(0)=SPRITE(0,...) を組み立てられるようになる。ドット絵を定義せずとも、プリセットを呼ぶだけで画面にマリオが歩きはじめる——という、ファミリーベーシック固有の発想にたどり着けるようになりました。

マニュアルを丸ごと引用することは避けますが、ChatGPT に挿絵で生成してもらったファミリーベーシックのスプライト一覧が出来が良かったのでお楽しみください。

ChatGPTによる想像図。逆にみてみたい。

効いた瞬間

リファレンス + 6 サンプル + プリセット表、これを詰めたプロンプトで「マリオを出して」と頼むと、第 3 回のときと違って、DEF SPRITE のパラメータ順序も DEF MOVE の第 2 引数の方向番号も、だいたい外しません。小数リテラル、NEXT I、存在しない関数の呼び出しも、目に見えて減ります。

とはいえ、完璧ではありません。GOSUBON ERROR GOTO の組み合わせのようなコーナーケースではまだ事故ります。システムプロンプトはそれでも万能ではなく、前提知識を「言語化して埋め込む」ことで手元の言語に寄せる、という関係にとどまります。それでも、1984 年のマシンに向かって現代の AI が DEF SPRITE から書きはじめる画面を眺めていると、距離を詰められた手応えがあります。

それでもよく記法や与える値を間違えますが、修正を依頼すればエラーを読み取ってある程度は自分で直してくれます。

余談 — リファレンスについて

ちなみに今回、プロンプトに与えるリファレンス情報は、手で書いたわけではなく、Web に散らばるリファレンスを Claude に集めて整形させた成果物です。マニュアルのOCR処理を試みましたが、40年という歳月もあり、そのまま使える形にはなりませんでした。

命令表の並べ方、エラーコードの対応、サンプルコードへの解説コメント——どれも Claude が書いたか、書いたものを人間が直したか、どちらかで、ちょうどリファレンス自体が「AI と人のバイブコーディングで生まれたドキュメント」になっています。

そしてそのドキュメントを、同じ AI がシステムプロンプトから読み返してコードを書く。自分が書いた地図を、自分で読み直して旅をする、みたいな再帰も含めて、バイブコーディング。今のところ、うまく機能しています。今回は簡略化していますが、LLM に検索まで組み合わせればさらに広がりが出るでしょう。

次回

1 年前には「ファミコンで AI と対話できたらいいのに」と夢想する話でしたが、第 1 回から 5 回にわたり、運搬路も荷物も少しずつ整いました。次回はここまでを 一度まとめて、どこまで来たのか、何を確かめてきたのか、次にどこへ行くのかを俯瞰します。

タイトルとURLをコピーしました