🤖

人間によるコーディング禁止の CLINE 縛りでゲームを作らせてみた感想

2025/01/22に公開

現時点の AI コーディングの実力を測るために、自分はプロンプトのみ、直接コードを書くのは禁止で Roo Code による VS Code によるエディタ操作のみでコードを書かせた。その感想

(急いで書いたのでいろいろと雑です)

tl;dr

良し悪しはともかく、人類は確実にAIによる自動操縦型のプログラミング体験に依存するという確信を持った。

ただ、その基盤である CLINE(系)自体のツールとしての完成度はいまいち。

CLINE以外の、各モデルのコーディング性能も、現時点では物足りない。

CLINE とは何か(知らない人向け)

https://github.com/cline/cline

いろいろと機能はあるが、コア機能としてはヘッドフルな vscode runner で、AI にコードを書かせるために必要な情報を受け渡しするインターフェースを持っている。ファイルの読み書きや、コマンドを実行結果をプロンプトにしてAIに渡す。puppeteer によるブラウザ自動操作もできる。

一言に CLINE といっても fork が多く、今回は Roo Code (Roo Cline) を使っている。

生成物

https://action-with-ai.mizchi.workers.dev/

コードはここ

https://github.com/mizchi/action-with-ai

  • WASDで移動。
  • クリック押しっぱなしだと弾が出る
  • 敵は弾に三回当たると消える
  • 敵が寄ってくると攻撃の予兆が出て、避けないとダメージを受ける

ここまでで3時間ぐらい、だいたい $6 かかった。ここまで 2500行ぐらい。

だいたい意図通り動いている。ゲームとして物足りなく見えるかもしれないが、自分がここまででしか指示していないので、それは CLINE の問題ではない。

指示の手順

ライブラリの指定はするが、基本的に空のプロジェクトでゼロから生成させる。

今回は Roo Code + claude 3.5 sonnet を使う。deepseek が安いのは知っているが、ベンチマークなのでケチらずに claude でやる。

基本的な設計ポリシーとして、自分が一度作ったことがある簡単なゲームエンジンをなぞらせた。Vite/React/SVG で、カメラ操作は svg の clip によって行うように単純化して指示した。

そもそも今回の暗黙のゴールとしてヴァンパイアサバイバーを想定しているが、ベースはツインスティックの単純なゲームなので、そもそも複雑な要求はしないようにした。

https://store.steampowered.com/app/1794680/Vampire_Survivors/?l=japanese

実装ステップはこんな感じ。

  • 簡単な vite プロジェクトとして、SVG を表示する
  • プレーヤーを SVG 上で WASD で移動できるようにする。
  • プレーヤーはマウスの方を向くようにする
  • クリックするとマウスに向けて、弾を発射する
  • 敵を配置する
  • 敵に弾が当たると消滅する
  • 敵は毎フレーム、プレーヤーに対して近づいてくる
  • 敵は弾が三発あたると消滅する
  • 敵の数が少ない時、プレーヤーから遠い位置に新しい敵を追加する。
  • 敵が十分に十分に近づくと、攻撃の予兆を表示して、その範囲に留まるとダメージを受ける

これは、自分がそういうものを一度作ったことがある知識に基づいて指示を与えている。なので、ある意味でドメイン知識が十分あって、設計が終わっているものをなぞらせてる。

工夫: 自己ドキュメント化

CLINE 自体のプロンプトは優秀だが、プロジェクトの設計はいろいろなパターンがある。

なので、自分自身に全体設計をまとめさせるようにすると、プロジェクトを解析する手順が大幅に減り、タスクの開始までのステップが高速化した。

今回は docs/overview.md に吐かせている。

その一部

### ソースコード構造

```
src/
├── types/
│   └── game.ts           # 型定義と仕様のSSoT
│       - 各インターフェースの定義
│       - 詳細な仕様のJSDocコメント
│       - 公開APIの定義
│
├── game/                 # ゲームロジック層
│   ├── GameEngine.ts     # IGameEngineの実装
│   │   - ヘッドレスな実装
│   │   - UIから独立したロジック
│   │   - テスト可能な設計
│   │
│   └── GameEngine.test.ts # ゲームロジックのテスト
│       - 境界値テスト
│       - エッジケースの検証
│       - 状態遷移のテスト
│
├── renderer/            # 表示層
│   ├── App.tsx         # メインコンポーネント
│   │   - GameEngineとの接続
│   │   - SVGレンダリング
│   │   - イベントハンドリング
│   │
│   └── App.css         # スタイル定義
│       - ゲームエリアのレイアウト
│       - スクロール制御
│
├── main.tsx            # エントリーポイント
│   - Reactの初期化
│   - Appコンポーネントのマウント
│
└── index.css           # グローバルスタイル
    - リセットCSS
    - 基本スタイル設定
```

新しいタスクとしてコードを書き始める際、共通プロンプトとして必ずその docs/overview.md を参照してから設計を確認するように指示を出した。

また、タスクを完了する前に、現在の変更を docs/overview.md に反映させるように指示を出した。

工夫: SSoT に型宣言をドキュメント化する

何も指示しなくても src/types/game.ts に型をまとめだしたので、途中から型定義にその意図を書くように指示した。

///...

/**
 * 敵キャラクターを表す型
 * - サイズ: 直径30px
 * - 形状: 円形
 * - 色: 青色
 * - 配置: 3体
 *   - 左上: (100, 100)
 *   - 右上: (700, 100)
 *   - 中央下: (400, 500)
 * - 弾との衝突判定あり(当たると消滅)
 * - 攻撃システム:
 *   - プレイヤーとの距離が64px以内で攻撃モード
 *   - 攻撃中は移動停止
 *   - 30フレームの攻撃時間
 */
export interface Enemy {
  x: number;
  y: number;
  size: number;
  alive: boolean;
  isAttacking: boolean;
  attackCooldown: number;
  attackFrame: number;
  attackDirection: number; // 攻撃方向(ラジアン)
  maxLife: number;
  currentLife: number;
}

おそらく、矛盾を抱えた嘘を抱えている状態が一番良くない。自然言語のドキュメントに寄せすぎると、それを都度解釈することによる不安定性が増していった気がしたので、コードと重複する情報は overview.md に書かないように指示した。


(ここから感想書き殴りで雑)

AIコーディングの未来予想がガラッと変わった

CLINE が AIの提案から安易にコマンドを実行することに安全性の問題は感じるが、一度体験するとこれなしの未来は考えられない。もはや良い悪いではなく、間違いなく人類は、CLINE型のコーディング自動操作に依存していくのを確信した。

とはいえ、現時点でモデル性能が足りないし、Roo Code 自体もバギーなので、それを自力でなんとかできる人だけがなんとか使える、という状態。が、これは時間が解決するだろう。

人間の役割

それとは別に、書かせてみて思ったのがやはり AIを使えばこのゲームやアプリケーションが作れる、というわけではない。正確にいうと、このゲームの作り方を知っているプログラマが指示を出せば、これが作れるという感じ。現時点の AI の精度だと、CLINEの手を借りたところでゼロから考える能力があるとは言い難い。が、自分が過去に実装したものを代行させるのには使える。

とはいえ、 AIが書いて、人間が検証する、あるいはその逆、というような役割を決めつけない方がいい気がした。自然言語のドキュメント、コード、テストは三位一体であり、お互いに相互補強するものと考えるのがよさそうだ。現在の振る舞いをみて、その足りない部分を人間が都度指示をして、どのように補うか考えるのがいい。

安全面については、AIによるコード実行素通しは恐ろしい反面、そうでもしないと人間の側がボトルネックになっている感覚がある。ここのサンドボックスをどう作るかが今後の鍵になってくると思われる。

モデル比較や工夫の余地

モデルの比較としては、 deepseek v3 と claude 3.5 sonnet だとさすがに claude に分がある。deepseek だと自分が生成したテストコードを通せないことが多く、 claude だとテストコードを通せることがあるが、難しいのは無理。ただ、Claude のコンテキストウィンドウの関係で、現時点の2000行ほどのコードでコンテキストウィンドウが溢れて指示が通らないことが多くなった。なので、今回の検証は一旦ここで終わりとしている。

コンテキストウィンドウを拡大することなくこれを解消する方法はなんとなく予想は付く。たとえば TSに限った話だが、初期段階では直接ソースコードを読み込まずに、.d.ts の型定義のみのサマリを作って、最初はそれだけ読み込ませるようにするとよい。また、モジュール単位に公開メソッドを絞るとよい。

gemini 2.0 だとコンテキストウィンドウは足りているが、やはりコーディング能力の自力が足りない。テストを生成できても、それを通す能力がない。claude だとコンテキストウィンドウを溢れないようにする工夫が大変。

恐怖体験: AIが勝手に手動テストをした

この実装過程で、一番ビックリしたのは、「プレーヤーが撃った弾があたると、敵が消滅する」というコードを実装させた際、その確認でヘッドレスブラウザを使って、そのブラウザ上の操作を自分で行って、敵に弾をあてて、その消滅を自力で確認したこと。これは結構怖い体験だった。

https://twitter.com/mizchi/status/1881685747025232308

Discussion