前回までのあらすじ
前回は、位置調整のやり取りに疲れて配置編集モードを作り、効果音や光の演出を仕上げたところまで書きました。procedural描画から始まったこの部屋も、ひとまず一区切りです。
今回は、コードを1行も書く前の「調査・検証」回です。このプロジェクトの方針は、実は途中から「脱出ゲームテンプレートの販売」から「Web Escape Engine Liteという汎用エンジンの実証実験」へと転換していました。その転換の中で、第1弾「密室からの脱出」とは世界観が真逆の第2弾「おでかけ!わすれもの大作戦」(明るい日常系のアイテム収集ゲーム)が、「同じエンジンから全く違うゲーム体験を作れるか」を試す対照実験として構想されます。今回はその第一歩の話です。
第1章:「100%差し替えで動きます」という断言を、実際のコードで検証してみた

この構想をレビュー役のGeminiに相談したところ、「ゲームの見た目や世界観がどれだけ違っても、エンジン内部の処理は100%共通化できる。それがエンジンの定義だ」という力強い評価が返ってきました。
ただ、これはあくまで「理想的なエンジン設計であれば」という条件付きの一般論です。今実際に存在しているコードが、本当にその理想の状態になっているかどうかは、誰も確かめていませんでした。そこで、engine.js・game.js・index.html・config.jsを通しで読み込んで、実際に検証することにしました。
結果は「半分正解、半分不正解」でした。ロジック層(game.js)は非常に高いレベルでデータ駆動化されていて、オブジェクトのタイプ別ハンドラ(pickup/exit/zoom/passcode/examine/danger)をすべて確認しましたが、if (itemId === "特定のID")のような固有名詞のべた書きは1箇所も見つかりませんでした。requiresItemやitemActions、setFlag、endingConditions、recipesは、すべてconfig.js側のフィールドだけで完結していたのです。
一方で、プレゼンテーション層(画面に表示される文言)には、固有テキストのハードコードが複数見つかりました。タイトル画面の見出しや説明文、ボタンの文言、クリア画面の既定文言、ページの<h1>、ゲームオーバー画面の文言(”Escape Failed”等)——これらはすべてconfig.jsを経由せず、直接HTMLやJavaScriptに書き込まれていました。
つまり、Geminiの「100%」という断言は部分的に不正確だと結論づけました。ロジック層は確かに立派にデータ駆動化されていましたが、画面の文言まで含めた「本当の意味での差し替えるだけ」にはなっていなかったのです。
第2章:最小テストなら今のままで動く、という判定

提案されていた「超ミニおでかけテスト」——自分の部屋で釣り竿を探す→玄関へ移動する→釣り竿を持っていれば「いってきます!」→クリア、という最小限のシナリオが、現状のファイル差し替えだけで動くのかも、実際のコードを根拠に判定しました。
出口の判定を行うtryExitという関数を読むと、「単一のアイテムを選択してからオブジェクトをクリックする」という前提で書かれていることが分かりました。これはミニテストの要件(釣り竿1つだけを持っていればいい)と完全に一致します。つまり、このミニテストはエンジンを一切変更しなくても100%動く、という判定になりました。
一方で、本編で構想していた「釣り竿・エサ・バケツの3つを、選択操作なしで持っていれば出発できる」という仕様は、この「単一アイテムを選択必須」という今の実装のままでは対応できないことも分かりました。ただし、これに必要な変更もこの時点で特定できていて、exitタイプに複数アイテムを一括チェックする代替モードを追加すればよく、既存の単一アイテムモードには手を入れずに済むという見込みも立っています。ただし、「今は第2弾の開発を始める段階ではない」という方針を優先し、この変更には着手せず、優先順位リストに記録するだけに留めました。
第3章:アセットのボリュームを巡って、AIの意見が割れた話

いよいよ実際にミニテスト用の素材をOpenMontageに依頼しようというタイミングで、背景2点・オブジェクト2点という「少し厚め」の構成を提案したところ、Claudeから待ったがかかりました。「このテストの目的はコンテンツの充実ではなく、config.jsの差し替えだけで動くかどうかの検証なのだから、今アセットを増やすのはコストとスコープの両面でリスクがある。最小限に留めるべきだ」という指摘です。
もっともな意見ではあったのですが、今回はこの反対意見を押し返すことにしました。理由は3つあります。1つ目は、この検証はすでにコード監査でtryExitの実装を直接確認していて、成功する確度が非常に高い状態からのスタートだったことです。「結果が分からないまま資源を投じる」という典型的なリスクとは、そもそも性質が違いました。2つ目は、玄関オブジェクトに画像を割り当てずシェイプ指定だけにすると、エンジン側のフォールバック機構がゴシック調の密室からの脱出の扉を代わりに描画してしまうことです。画像を削ると、むしろ見た目が壊れるリスクがありました。3つ目は、提案されていた「コミカルな失敗アイコン」はスコープの縮小ではなく別軸への機能追加だったので、これは本編に着手するタイミングに回すことにしました。
AIの提案を鵜呑みにしないというのは、これまでもずっとこの連載のテーマでしたが、今回は逆に「別のAIからの反対意見」も同じように吟味した形です。結局、当初通りの4点構成で依頼し、納品されました。ただ、届いた玄関ドアは花輪やリボンの付いた装飾的なデザインで、依頼した「明るいけどシンプルな家庭用の玄関ドア」からは外れていたため、装飾を落として作り直してもらっています。
第4章:独立フォルダでの実験、そして監査結果がそのまま画面に的中した瞬間

密室からの脱出本体には一切手を入れず、outing-mini-testという完全に独立したフォルダを新しく作りました。index.html・CSS・JS(engine.js・game.js・audio.js・event-bus.js)・アセットはそのままコピーし、新規に書いたのはconfig.jsだけです。自分の部屋のシーンが1つ、釣り竿のpickup、玄関のexitだけの、パズルも合成も無い最小構成にしました。セーブデータが衝突しないよう、meta.idも密室からの脱出とは別の値にしています。
実際にブラウザで動かして確認したところ、釣り竿を持たずに玄関をクリックすると「釣り竿がないよ!」、釣り竿を拾ったが選択せずにクリックすると「釣り竿を選んでから玄関をクリックしよう。」、選択してからクリックすると「よし、準備完了!」に続いてクリア画面で「いってきます!」——engine.js・game.js・index.htmlを1バイトも変更せずに、すべて正しく動作しました。
ここであえて、タイトル画面のテキストだけは直さずに確認してみました。第1章の監査で見つけた問題を、実際の画面でそのまま可視化するためです。結果、背景画像とブラウザのタブタイトルは正しく「おでかけ」テーマに切り替わったのに、見出しの文章だけは「密室からの脱出」「手がかりを探し、鍵を見つけてドアを開けろ。」という密室からの脱出の文言がそのまま残っていました。第1章で予測した「ロジックは汎用化済み、UIの文言だけ取り残されている」という結果が、実際の画面で寸分違わず的中した瞬間です。
第5章:見つかった穴をふさいで、最後に残った小さな粗

見つかった穴はそのままにせず、ふさぐことにしました。GAME_CONFIG.meta.subtitleとGAME_CONFIG.ui.{title, clear, gameover}という新しいオプションのフィールドを追加し、指定が無ければ従来通りの既定文言がそのまま使われる、完全に後方互換の設計にしています。密室からの脱出側のconfig.jsは一切変更せずに動作確認したところ、タイトル・クリア・ゲームオーバー画面の文言はすべて以前と1文字も変わっていませんでした。そのうえでouting-mini-test側のconfig.jsにui設定を追加したところ、今度はタイトル画面もクリア画面も完全に「おでかけ」テーマの文言になり、密室からの脱出の痕跡は一切残らなくなりました。
最後に、細かい粗が1つ見つかっています。玄関ドアの画像の一部が透過していて、背後にある部屋の背景の窓が透けて見えてしまう現象です。ドアの絵に描かれた「ガラス窓」の部分が実際にアルファ抜きされていて、たまたま背景側の窓と重なる位置に配置していたのが原因のようです。これはロジックとは無関係な配置座標の問題で、今回の検証目的(エンジンを無改修のまま別のゲームに見せられるか)にはすでに十分な結果が出ていたため、対応は本編に着手するタイミングまで見送ることにしました。
🎮 今回の検証結果
今回は初めて、2つの全く違うゲームを並べてお見せします。同じエンジン・同じコードから生まれた2本です。ぜひ両方触って、本当に「別のゲーム」に見えるか確かめてみてください。
密室からの脱出
おでかけ!わすれもの大作戦(ミニテスト版)
※ 玄関ドアが透過していて、背景の窓が透けて見える箇所があります。第5章で書いた通り把握済みの粗で、今回の検証目的には影響しないためあえて直さず残しています。本編に着手する際に直す予定です。
💬 読者へのヒアリング
2本を実際に遊んでみて、「これは同じエンジンだ」と気づく点、逆に「本当に別ゲームに見える」と感じた点があれば、ぜひ教えてください。今回あえて直さなかったタイトル画面の文言など、細かい違和感に気づいた方がいたら特に知りたいです。
まとめ&次回予告
「100%差し替えだけで動きます」というAIの断言を鵜呑みにせず、実際のコードを監査し、最小限のテストで検証し、見つかった穴をふさぐところまで、一通りやってみました。ロジック層は思っていた以上にしっかりデータ駆動化されていた一方、画面の文言という盲点があったこと、そしてその盲点を今回の実験できちんと可視化してから直せたことは、今回の一番の収穫です。
次回は、この検証結果を踏まえて、本編「おでかけ!わすれもの大作戦」に実際に着手するかどうかを考えていきます。
次回:第6話「検証は終わった。じゃあ本編、本当に作る?」

コメント