HN 日本語サマリー

← 一覧へ戻る
AI・機械学習

AIは「スラスト」ゲームを再現できない(しかし、それを理解する手助けはできる)

AI Can't Recreate the Thrust Game (But It Can Help You Understand It) (jamesdrandall.com)

47 pointsby msephton28 コメント

要約

筆者がAI(Claude)に1986年のクラシックゲーム「スラスト」のブラウザ版再現を依頼したところ、最初は表面的な模倣に過ぎず、重力や操作感が全く再現されなかった。しかし、AIはオリジナルのアセンブリコードを解析し、ゲームの複雑なタイミングや物理演算の仕組みを理解するための強力なツールとなることが判明した。この経験から、AIはゲームの「魂」を捉えることはできないが、その技術的詳細を解き明かす「考古学」には役立つことが示唆されている。

全文翻訳

AIはスラストを再現できない(しかし、それを理解する手助けはできる) Annhexation 早期アクセス 私がゼロから構築したターンベースの4Xストラテジーゲーム — カスタムWebGPUエンジン、8つの文明、インストール不要。今すぐブラウザでプレイできます。 ブラウザで無料プレイ Steamでウィッシュリストに追加 Claudeに、クラシックな1986年のゲーム「スラスト」をブラウザで再現するように依頼しました。それはガラクタを作り出し、その後制御不能になりました。 スラストはBBC Microで私のお気に入りのゲームの1つでした。Jeremy C. Smithによって書かれ、1986年に公開されたこのゲームは、驚くべき物理演算とゲームプレイを持つ、見かけによらず奥深いゲームです。あなたは宇宙船を操縦し、洞窟を通り抜け、燃料を集め、砲塔の攻撃を避け、ボーナスポイントのためにポッドを回収しながら、重力と運動量と戦います。Jeremyはその後Peter Irvinと共に、さらに印象的なExileを制作しましたが、1992年に悲劇的な事故で亡くなりました。彼はスラストを書いたとき、16歳から18歳の間でした。オリジナルのゲームはオンラインでプレイできます。私のデスクの横にはBBC Masterがあり、Elite、Exile、Holed Outなどの他のクラシックゲームと共に、時々スラストを起動します。私が繰り返しプレイするゲームの1つです。私は今、これら3つを異なる方法で再現しました…4つ目はますます避けられないものになりつつあります。 ガラクタから始める さて。ある朝、私はかなり気軽にClaude Codeに、それをブラウザで再現するように依頼しました。OpenAIとAnthropicからの最新の能力宣言を読んでいたのだと思います。そこで、私はかなり包括的な仕様を作成し、オリジナルの逆アセンブルされたソースコード、スクリーンショットへのアクセスを与え、「スラストを再現してくれ」と言いました。それは、ガラクタという言葉でさえ優しすぎるようなものを作り出しました。それはスラストを非常に漠然と連想させるものでした — スキャンラインのようなものもありましたが、それは本当にひどいものでした。重力さえ正しく機能しておらず、宇宙船は適切に落下せず、操作感は奇妙で、ただ…陰気でした。ある意味では、スラストに似たものが何とか機能し、何とかスラストのように見えたことは驚くべきことですが、それはプレイ可能ではなく、本物のエレガンスと美しさには程遠いものでした。そして、それがスラストのようなゲームの本質です。通常の物理演算を使用して、表面上は似たようなものを作ることはかなり速くできます — デバイスのフレームレートで実行し、標準的なデルタタイム物理演算を使用し、洞窟を描画するだけです。しかし、それはスラストとは全く異なる感触になるでしょう。魔法は、特定のタイミング、宇宙船の重さ、運動量が構築される方法にあります。特にオリジナルのゲームをプレイしたことがあるなら、それらの詳細はすべてであり、テキストの説明、さらにはオリジナルのソースからさえも作業しているAIは、それらを捉えることができません。 考古学 しかし、それは私に好奇心を抱かせました。オリジナルのゲームはどのように機能していたのでしょうか?私は8ビットマシンでこれらを機能させるために開発者が使用したトリックに魅了されており、それは少し考古学的なセッションになりました。私はすぐにKieran Connellによるオリジナルのソースの素晴らしいコメント付き逆アセンブルを見つけ、それをClaudeにフィードして質問を始めました。ここで物事は興味深いものになりました。AIがコードを書いたからではなく — コード自体は複雑ではありません。それは32KのRAMで実行された1986年のゲームです — Claudeが6502アセンブリを調査するための並外れたツールであることが判明したからです。私は逆アセンブルされたソースコードのブロックをフィードして、「レベルデータはどのように機能しますか?」とか「この物理モデルは何をしていますか?」と質問し、オリジナルのコードが何をしているのかについての詳細で正確な説明を得ることができました。公平を期すために言えば、私はコメント付きの逆アセンブルされたソースコードから作業していましたが、それであっても、コメントとアセンブリの両方から情報を抽出し、ゲームがどのように機能していたのかについての詳細な説明を生成することができました。私の感覚では、コメントが正しい領域に焦点を当てるのを助けてくれなかった場合、それははるかに役に立たなかったでしょう — しかしそれでも、それは仕事をはるかに簡単で楽しいものにしました。そして、はい、コメントをコードから削除して、Claudeがどれほどうまくやるか見てみる可能性が高いです。 これを行ううちに、回答をオリジナルのゲームを再現するための基礎として使用できることに気づき、Claudeにさまざまなサブシステムの仕様を作成するように依頼し始めました。私が生成した仕様のほとんどは、ソースコードのspecsフォルダで見つけることができます。いつかそれらを正式にまとめるかもしれませんが、今のところ、それらはオリジナルのニュアンスについて良い洞察を与えてくれます — 私が思っていたよりも多くのことが行われています。例えば、砲塔がジェネレーターを攻撃すると一時的に発砲を停止することに気づいたことはありませんでしたし、実際のコードを読むと明らかになる発砲角度の微妙な違いもあります。 物理演算 物理演算は、掘り下げるのが最も興味深い分野の1つでした。スラストはQ7.8固定小数点演算を使用しています — これは、浮動小数点ハードウェアを持たない8ビットマシンで一般的なテクニックです。回転システムは、力の成分のためにルックアップテーブルを使用した32ステップを使用しています。しかし、本当に難しい部分はタイミングでした。私の最初の実装は、逆アセンブルからの正しい定数を使用しました — 同じ重力、同じ推力値、同じ抗力 — しかし、宇宙船は速すぎ、機敏すぎました。適切な重さがありませんでした。定数はオリジナルと同じだったので、タイミングの問題でなければなりませんでした。そして、それはそうでした。オリジナルは、BBC Microの50Hz VSyncレートで物理演算を実行していません。ティックループはフレームあたり少なくとも3 centiseconds待機し、約33.33Hzの実効レートを提供します。しかし、それだけではありません。各ティック内で、物理演算の更新は16ティックウィンドウあたり6つのアクティブスロットにのみ制限されています。物理演算ステップのコアは次のようになります。 /** 16ティックウィンドウあたり6つのアクティブな物理スロット */ private static readonly ACTIVE_SLOTS = new Set([0, 3, 5, 8, 11, 13]); private tickStep(input: ThrustInput): void { const slot = this.tickCounter & 0x0F; this.tickCounter = (this.tickCounter + 1) & 0xFF; // 回転: 4ティックごとに3回、整数ステップのみ if ((slot & 0x03) !== 0 && input.rotate !== 0) { s.angle = ((s.angle + input.rotate) + 32) % 32; } const isActiveSlot = ThrustPhysics.ACTIVE_SLOTS.has(slot); // 力の計算 — アクティブスロットのみ(16ティックごとに6回) if (isActiveSlot) { s.forceY += this.gravity; if (input.thrust) { s.forceY += ANGLE_Y[angleIdx] / (1 << this.massShift); s.forceX += ANGLE_X[angleIdx] / (1 << this.massShift); } // 線形抗力 s.forceX *= 1 - 1/64; // X: *= 63/64 s.forceY *= 1 - 1/256; // Y: *= 255/256 } // 位置積分 — 毎ティック s.x += s.forceX; s.y += s.forceY; } このゲーティングにより、実効的な力/抗力レートは約12.5Hzになります。重力と推力は、毎フレームではなく、それらの6つの特定のティックでのみ適用されます。回転でさえ独自のゲーティングを持っています。4ティックごとにスキップします。これらは任意の数値ではありません。これらは6502ソースからの正確なパターンであり、ゲームの感触を定義します。それらをずらすと、すぐに違和感が出始めます。非対称な抗力も興味深いです — X軸(63/64)の方がY軸(255/256)よりもはるかに強く、そのため水平方向の移動は垂直方向よりも「粘着性」があります。これらのタイミングを正しく設定し、定数だけでなくオリジナルの正確な更新ケイデンスに合わせると、完璧に感じられました。BBCエミュレーターと私のバージョンを切り替えることができ、操作感は同じです。 それが私にとって本当に興味深いものになりました。通常の物理演算でスラストのようなゲームを作成することは些細なことです — 特にコーディングAIを使用すると。スラストを再現すること — その特定の感触と重さすべてを含めて — は、ゲームループ内の個々の物理演算更新のタイミングまで、オリジナルの動作を正確に理解する必要がありました。 サウンド もう1つの真剣な焦点が必要だった分野はサウンドでした。私がEliteのTypeScriptバージョンを作成したとき、エミュレーターから直接サウンドをサンプリングしました。Eliteのサウンドは非常に離散的で、短くシャープなエフェクトだったので、それはうまくいきました。ただし、ビームとミリタリーレーザーのエフェクトはオフでした。しかし、スラストでは、エンジンはキー入力に応答する連続的なドローンであり、爆発には特定のエンベロープがあります。それらをサンプリングすることもできましたが、それはただ…間違っているように感じました。だから代わりに、私は