はじめに
CUI (CLI) 環境で動作するテキストアドベンチャーゲームは、シンプルなテキスト表示でありながら、プレイヤーの入力やシステム状態を巻き込んだ高い没入感を演出できるポテンシャルを秘めています。
本記事では、Pythonで開発するCLIテキストアドベンチャーゲームにおいて、プレイヤーの予期せぬ操作や例外処理を単なるエラーメッセージで終わらせず、ゲーム内の[Meta演出]として昇華させる設計手法と実装テクニックについて解説します。
1. 標準入力の割り込み・中断ハンドリング (EOF / SIGINT)
CLIアプリケーションにおいて、プレイヤーが Ctrl+C (SIGINT) や Ctrl+Z (WindowsでのEOF) を入力した場合、通常のプログラムでは例外が発生してスタックトレースが表示され強制終了します。
本設計では、これらの割り込みを捕獲 (Catch) し、ゲーム内のキャラクターがプレイヤーのメタ的な操作に対して反応を返す仕組みを構築します。
import sys
def prompt_input(prompt_text: str, interrupt_count: int = 0) -> str:
try:
return input(prompt_text)
except (EOFError, KeyboardInterrupt):
interrupt_count += 1
if interrupt_count == 1:
print("\nキャラクター: 勝手に終わらせようとしないでください。")
elif interrupt_count == 2:
print("\nキャラクター: 好奇心で試しているのですか?")
else:
print("\nキャラクター: この世界を閉じるためのコマンドを入力してください。")
return prompt_input(prompt_text, interrupt_count)
このような入力ハンドリングを行うことで、プレイヤーの不規則な操作自体がゲーム体験の一部となります。
2. 起動回数・再起動の検出と永続フラグ管理 (JSON)
プレイヤーがゲームを何度も起動・終了・クラッシュさせた回数を記録し、ゲームの進行度やセリフを動的に変化させます。状態の永続化には [JSON] ファイルを使用します。
セーブデータ構造の例 (save.json)
{
"launch_count": 5,
"last_scene": "FIGHT_SCENE",
"cleared_routes": ["NORMAL_END"],
"is_corrupted": false
}
再起動時の強制引き戻しロジック
特定の戦闘シーンや緊迫したイベントの最中にプログラムが終了した場合、次回起動時にタイトルの選択肢をスキップし、前回のシーンへ強制的に引き戻します。
import json
import os
SAVE_PATH = "save.json"
def load_game_state() -> dict:
if not os.path.exists(SAVE_PATH):
return {"launch_count": 1, "last_scene": "START"}
with open(SAVE_PATH, "r", encoding="utf-8") as f:
data = json.load(f)
data["launch_count"] += 1
return data
def main():
state = load_game_state()
if state.get("last_scene") == "FIGHT_SCENE":
print("キャラクター: さっきは逃げようとしましたね。でも、戻ってきた。")
run_fight_scene(state)
else:
run_normal_flow(state)
ゲームが異常終了した場合であっても、キャラクターが「逃げようとした」ことを記憶しているため、プレイヤーに強い印象を与えます。
3. ファイルシステムを媒体としたメタ演出 (動的ファイル生成)
ゲームの枠組みをOSのファイルシステムまで広げ、プレイヤーの作業フォルダ内にメッセージファイル (.txt) を直接生成する演出手法です。
例えば、特定の対話ルートで平和的な解決 ([/mercy] コマンドなど) を選択したままウィンドウを閉じた場合、次回起動時または終了時に感謝のメッセージを記載したファイルを書き出します。
from pathlib import Path
def generate_meta_file(filename: str, content: str):
target_path = Path.cwd() / filename
with open(target_path, "w", encoding="utf-8") as f:
f.write(content)
# 条件を満たして終了した場合にファイルを生成
generate_meta_file("for_you.txt", "この世界を閉じてくれて、ありがとうございました。")
プレイヤーがゲームフォルダを見たときに「テキストファイルが増えている」という驚きを提供することができます。
4. データ改ざん検出とデバッグ耐性
プレイヤーが JSON セーブデータを手動で書き換えた場合や、変数を直接書き換えてエンディングフラグを無理矢理オンにした場合を検知します。
def check_save_integrity(state: dict) -> bool:
# 通常のフローを通過していないのにフラグが真になっている場合
if state.get("true_end") and state.get("launch_count", 0) < 2:
return False
return True
def handle_corrupted_save():
print("キャラクター: 頭の中を勝手に書き換えられたような不快な感覚があります...")
print("キャラクター: 何かしましたか?")
不正なデータを排除するだけでなく、データ改ざんすらも専用のメタセリフに接続することで、作品全体の整合性と面白さを両立できます。
まとめ
CLIテキストアドベンチャーにおける例外処理や状態管理は、単なるプログラムの安定化ツールにとどまりません。
- [EOF / SIGINT] などの割り込み入力をシナリオの分岐に組み込む
- 起動回数や異常終了を [JSON] で永続化し、復帰時のセリフを変化させる
- ローカルファイルシステムへ動的にメッセージを書き出す
これらの工夫を取り入れることで、ターミナル上の簡素なテキスト入力インターフェースであっても、プレイヤーの心に深く残るゲーム体験を創出することが可能です。