跳到正文
zenn · 游戏开发社区· 来源· boraemon2000·· 2 天前AI 评分64

【每日一次部署】制作了在1000种可能中“必定能锁定到一人”的推理游戏

【1日1デプロイ】1000通りで「必ず1人に絞れる」推理ゲームを作った

正文 · 原文

証拠から森の住人を見つける、カサッ!森の足あと探偵

足あと・持ち物・方角の証拠と3人の候補を並べた実際の画面

今回作ったもの

「1日1デプロイ」の新作として、証拠を読み、3人の候補から1人を見つける短編推理ゲーム カサッ!森の足あと探偵 を作りました。

▶ カサッ!森の足あと探偵を遊ぶ

手がかりは次の3種類です。

  • 足あと:丸い、細長い、二股
  • 持ち物:木の実、羽根、鍵
  • 方角:川、丘、森

「足あとは細長い」「川の方へは向かっていない」といった2〜3枚の証拠を、3人の森の住人の特徴と見比べます。全3事件を30秒以内に解決すれば捜査完了です。

間違えてもゲームオーバーにはなりません。残り時間が3秒減り、選んだ相手と正解者を区別できる 追加証拠 が届きます。失敗を答え合わせで終わらせず、次の判断材料へ変えました。

遊び方

  1. 証拠カードを読む
  2. 3人の足あと・持ち物・方角を比べる
  3. 条件をすべて満たす1人をタップする
  4. 3事件を解決する

PCでは数字キーの 1 / 2 / 3 でも選べます。結果には、解決数、ミス数、最大連続正解、残り時間、ランクを表示します。

今日のレベルアップ1:証拠を文章ではなく関数にする

証拠は表示用の文章だけでなく、候補が条件を満たすか判定できる関数として用意しました。

const PREDICATES = [
  {
    id: "fp-slender",
    text: "足あとは細長い",
    test: (suspect) => suspect.footprint === "slender",
  },
  {
    id: "not-river",
    text: "川の方へは向かっていない",
    test: (suspect) => suspect.direction !== "river",
  },
];

同じ test() を、事件生成、画面の正誤判定、追加証拠の選択、自動テストで使います。

表示用の文章と判定ロジックを別々に書くと、「文章では川へ行っていないのに、コードでは川へ行った候補を正解にする」といったずれが起きます。証拠をデータと関数の組にしたことで、1か所の条件を全工程で共有できました。

今日のレベルアップ2:ランダム問題を完成後に検査する

ランダムに証拠を2枚選ぶだけでは、答えが2人残ったり、逆に1枚目だけで正解が分かったりします。

そこで、正解者に当てはまる証拠から2〜3枚の順列を作り、次の条件をすべて満たす組だけを採用しました。

function isValidClueSequence(suspects, answer, clues) {
  if (clues.length < 2 || clues.length > 3) return false;
  if (!clues.every((clue) => clue.test(answer))) return false;

  let previousCount = suspects.length;

  for (let i = 0; i < clues.length; i += 1) {
    const matches = matchingSuspects(suspects, clues.slice(0, i + 1));

    if (matches.length > previousCount) return false;
    if (i === 0 && matches.length < 2) return false;

    previousCount = matches.length;
  }

  const final = matchingSuspects(suspects, clues);
  return final.length === 1 && final[0].id === answer.id;
}

大事なのは、「ランダムに作ったから遊ぶたび違う」で終わらせず、生成したあとに遊べる問題か検査すること です。

  • 証拠はすべて正解者に一致する
  • 1枚目では候補が2人以上残る
  • 証拠を追加して候補が増えない
  • 最後は正解者1人だけになる
  • どの不正解者にも、区別できる追加証拠がある

生成に失敗した場合は、その事件を捨てて別の組み合わせを作ります。同じseedからは同じ事件になる疑似乱数を使い、再現できるようにもしました。

最初の実装は「1枚目だけで解ける問題」だった

工程1の最初の実装にも、一意解の確認はありました。しかし、証拠を空の配列から追加するとき、候補が1人になった証拠だけを採用していました。

つまり「最後に1人になる」は満たしていても、最初の1枚だけで答えが決まる 問題ばかりでした。複数の証拠を照合する推理ゲームにはなっていません。

テストにも問題がありました。

// 修正前
ok("single clue may be ambiguous", matches.length >= 1);

正解者に当てはまる証拠なら、候補が1人以上残るのは当然です。このテストでは「1枚目で絞りすぎていないか」を確認できません。

そこで条件を matches.length >= 2 へ変更し、証拠の順列を調べる方式へ作り直しました。seed 1000〜1999の1000事件で、一意解、1枚目の曖昧さ、追加証拠、同じseedの再現性を検証しています。

OK: 1000 seeds
OK: capture
OK: penalty / lock / timeout
All tests passed.

テストの成功ログは4行にまとめ、失敗した場合だけseedと理由を詳しく出します。大量に確認しても、人が読むべき情報は増やさないようにしました。

今日のレベルアップ3:時間と入力を純粋な状態としてテストする

ミス時は、残り時間を3秒減らし、連続正解を0へ戻します。また、高速で同じ候補を押してもミスが2回加算されないよう、選択処理の最初に入力をロックします。

これらは画面操作の中だけに書かず、game-state.jsへ分けました。

function applyMissPenalty(state) {
  return {
    ...state,
    mistakes: state.mistakes + 1,
    penaltySec: state.penaltySec + 3,
    streak: 0,
  };
}

function remainingSeconds(startMs, nowMs, penaltySec) {
  const raw = 30 - (nowMs - startMs) / 1000 - penaltySec;
  return Math.max(0, Math.ceil(raw));
}

開始時刻、現在時刻、ペナルティを渡せば残り時間が決まるため、30秒待たなくても時間切れをテストできます。入力ロックも状態の変化として検証し、連打された2回目の入力は受け付けないことを固定しました。

今日のデザイン:比較する位置を揃える

舞台は、夕暮れの森に置かれた調査机です。深緑、焦げ茶、生成り、紅葉色を使い、候補は博物画風の森の住人として描きました。

推理しやすさを優先し、3人のカードでは次の順番を固定しています。

  1. 足あと
  2. 持ち物
  3. 方角

カードごとに情報の位置が違うと、内容を読む前に視線を探す必要があります。同じ属性を同じ高さへ揃えることで、横方向に比較できるようにしました。

否定の証拠は朱色の帯だけでなく「否定」の文字も表示し、正解・不正解も「一致」「再調査」の印で伝えます。色だけを見分けられなくても進行が分かる設計です。

非エンジニア初心者がAIでゲームを作るTIPS

AIへ「ランダムな推理問題を作って」と頼むだけでは、たまたま解けない問題や、簡単すぎる問題が混ざりやすくなります。

先に、完成した問題が守る 性質 を文章にします。

3人の候補から1人を特定する推理ゲームを作ってください。証拠は候補を判定する関数として管理します。証拠は2〜3枚で、すべて正解者に一致し、1枚目では候補が2人以上残り、全証拠を使うと正解者1人だけになる問題のみ採用してください。同じseedでは同じ問題を生成してください。

さらに、数件の見本確認だけでなく、まとめて検査する条件を渡します。

連続する1000seedで、候補が3人いること、特徴が重複しないこと、1枚目では2人以上残ること、最後は正解者1人になること、各不正解者を区別する追加証拠が存在することを確認してください。失敗時はseedと理由を表示してください。

画面操作にも、正常ルート以外の確認を加えます。

正解だけでなく、ミスから追加証拠で復帰する、同じ候補を高速連打する、時間切れになる、結果からリトライする、の4ルートを確認してください。

AIに「バグがないように」と頼むより、成立してほしい条件と、壊れやすい操作を具体的に渡す 方が確認可能な成果物になります。

公開

GitHubの main ブランチへpushし、ロリポップ!デプロイナウで公開しました。

▶ カサッ!森の足あと探偵

これまでの反射神経やタイミング中心の遊びとは違い、今回は証拠を並べ、条件を消去して答えへ進むゲームになりました。毎日ひとつ、小さなゲームや便利ツールを公開しています。

来源:zenn · 游戏开发社区 · zenn.dev