hrxdev
日本語

制作の裏側

1人の開発者と、AI コーディングアシスタントと、機械がチェックする大量のルール。

執筆:Nick

Prison Life は、私が Claude Code(Anthropic のコーディングエージェント)と一緒に書いています。ゲームがどういうものか、どの選択肢を取るかは私が決め、キーボードを叩く作業の多くはアシスタントが担当します。コードを見るのは私とレビュー用の AI エージェントだけなので、自動化に頼っています。ルールは心がけではなく、自動チェックとビルドで強制します。

作業の委任

メインの Claude Code セッションは作業を計画し、タスクトラッカー、設計判断の記録、変更履歴を管理します。自分ではコードを書きません。どんなに小さな変更でも、専門の AI エージェントに渡します。各エージェントには、役割とモデルを定めた定義書があります。

役割モデルの階層仕事
アーキテクチャOpusデータモデル、ティック、スレッド、経路探索、設計判断
シミュレーションコードOpusシミュレーションの各システム、キャラクター AI、ホットループ
パフォーマンスOpusプロファイリング、ベンチマークの劣化調査
レビュー(読み取り専用)Opus差分のレビュー。ファイルは編集できない
クライアントとツールSonnetGodot クライアント、UI、ツール
テストSonnet受け入れ基準に沿ったテスト
コンテンツデータSonnetスキーマに沿った JSON 定義
検索、チェックの実行Haikuコード検索、チェックの実行と失敗の要約

難しい仕事は最も強力なモデルに、定型の仕事はより安価なモデルに任せます。安価な AI エージェントがチェックに2回失敗したらタスクは1段上の階層へ移り、最上位でも2回失敗したら作業を止めて私に確認します。

「ダメ」と言うフック

Claude Code のフックは、アシスタントの操作の前後で動くスクリプトです。私の環境では、次の3つのルールを強制しています。

これらはミスを防ぐためのもので、意図的な回避を防ぐものではありません。腕のあるシェル操作ですり抜けることはできますし、フックのひとつは AI エージェント内でチェックが赤になったことを検知しても、止めることはできません(メインセッションの停止フックが拾います)。そこは正直に書いておきたいと思います。

記録された判断とチェック

決定論的コア

シミュレーションは、Godot への参照を一切持たない素の .NET ライブラリの中にあります。Godot クライアントはその状態を読み、コマンドを送るだけです。コアは固定のルールに従います。世界が変わるのはコマンドを通じてのみ、時間は整数のティック、乱択は世界のシード付き生成器からのみ。同じシードと同じコマンドログからは、同じ世界ができなければなりません。これらのルールは、レビューだけでなく、コンパイラとテストで検証されます。方法は開発ログ #1、世界、セーブ、リプレイについては開発ログ #2をご覧ください。

シミュレーションコアのアーキテクチャコマンドはキューに入ります。各ティックは、フェーズ0(コマンド、コマンドログに書き込み)、フェーズ1(固定順序のシステム)、フェーズ2(ティックの終了処理)を実行します。コマンドログと、タイルマップとシード付き乱数ストリームを含むワールド状態が、状態ハッシュに入力されます。 コマンド入力 プレイヤー、テスト、シナリオ コマンドキュー Enqueue はスレッドセーフ ティック T(1スレッド、整数時間) フェーズ0:コマンド シリアライズ、(tick, seq) を付与 検証、ログに書き込み、Apply 拒否されたコマンドもログに残る フェーズ1:システム コードで定めた固定の順序で実行 (まだ登録なし) フェーズ2:ティックの終了 構造変更(まだ未使用) その後ティックカウンタ + 1 コマンドログ すべてのコマンドと その結果 ワイヤバイト + ダイジェスト リプレイ = シード + ログ ワールド状態 シード、ティック タイルマップ(階層) シードから4本の RNG: Commands, Needs, Ai, Events 状態ハッシュ シード、ティック、マップ、RNG、ログダイジェスト
現時点のシミュレーションコア。システムもキャラクターもまだありません。世界は階層を持つタイルマップを保持し、ハッシュは描画される内容に加えてマップも対象にしています。

設計上の目標は、毎秒20ティックで最大1,000人の受刑者と職員です。あくまで目標です。まだキャラクターがいないため、ベンチマークランナーはあっても、その規模では何も計測していません。