C言語で作るターミナルタイピングRPG「クムドールの試練」開発記録 | UNIX Cafe

* 当サイトでは、コンテンツの一部に広告を掲載しています。

System Note $ cat /proc/ai-disclosure

本記事の構成および論理分析にはAI(人工知能)を使用しています。情報の正確性は、システム管理者(UNIXユーザー)による手動検証済みです。

C言語で作るターミナルタイピングRPG「クムドールの試練」開発記録 | UNIX Cafe

C言語製のターミナルタイピングRPG「クムドールの試練」を作りました。

GitHubでは kumdor-trial という名前で公開しています。最初の公開版は v0.1.0 です。

この記事では、完成品の紹介というより、小さなCプログラムを少しずつターミナルゲームとして育てていった流れをまとめます。

目次

クムドールの試練とは?

1990年代に流行ったPCゲームに、『クムドールの剣』というRPG型のタイピングゲームがありました。PC-98向け作品として知られていて、フィールド移動にも F や J、スペースキーを使い、敵と遭遇すると表示された文字列を正確に入力して戦うというゲームでした。

私自身も、当時全盛期だったパソコン通信のNIFTY-Serveでその存在を知りました。その後、Macintosh版の『クムドールの剣』が発売されていたことから、Color Classic や Quadra 650 で遊び、このゲームでタッチタイピングを覚えました。当時は「ブラインドタッチ」と呼ぶことが多かった記憶があります。

このゲームが面白いのは、最初からすべてのキーを使わせないところです。ホームポジション周辺のキーから始まり、ゲームが進むにつれて少しずつ扱うキーが増えていく。プレイヤーがゲーム内で進むことと、現実のタイピングが上達していくことが重なっていました。

今回作った「クムドールの試練」は、その記憶にある段階学習の気持ちよさを、C言語製の小さなターミナルゲームとして自分なりに再構成してみたものです。

本記事では、そんな思い出から生まれた自作タイピングゲーム「クムドールの試練」の概要と、こだわりの仕様についてご紹介します。

実際に作り出してみると、細かい部分はほとんど忘れていました。そのため、巨大な金魚さんが公開されている『Macintosh版クムドールの剣』の情報を参考にさせていただきました。

http://rocky75.web.fc2.com/kumu/

このゲームの内容について

「クムドールの試練」は、ターミナル上で動くタイピングRPGゲームです。

画面に表示された課題をそのまま正確に入力すると、敵にダメージを与えます。タイプミスをすると敵が反撃します。10個のステージで敵を順番に倒せば完全勝利、途中でプレイヤーのHPが0になると敗北です。

プレイ画面はこのような雰囲気です。

=========================================
【第1/10ステージ】
練習内容: ホームポジション: f / j / スペース
指使い  : 左右の人差し指をfとjに置き、右親指でスペースを押す。
敵      : クムドールの影
=========================================

*************** BATTLE START ***************
クムドールの影が立ちはだかった!
********************************************

あなた Lv:1 EXP:0/10 HP: 10/10 | クムドールの影 HP: 3/3
敵の構え: [ f j ]
課題を入力してEnter(:save/:quit/:savequit): f j
➔ 見事なタイピング! 剣が炸裂した! (敵の残りHP: 2)

ゲーム中に中断したい場合は、入力欄でコマンドを使えます。

コマンド内容
:save現在ステージの先頭から再開できる状態で保存
:quit保存せずに終了
:savequit保存して終了

最初から全部のキーを使わせない

今回の一番大事な設計は、最初からすべてのキーを使わせないことでした。

昔のタイピングゲーム「クムドールの剣」について調べていると、序盤は限られたキーだけを使い、ゲームが進むにつれて少しずつ使えるキーが増えていく、という学習設計が魅力だったという話が出てきました。

この考え方を、今回のターミナル版でも取り入れています。

ステージ練習内容
1ホームポジション: f / j / スペース
2左手ホーム段: a s d f
3右手ホーム段: j k l ;
4人差し指の上段: r t y u
5上段の広がり: q w e i o p
6中央から下段: g h v b n m
7下段と記号: z x c , . / ?
8総合練習: 大文字・小文字・記号
9数字キー: 1 から 0
10最終練習: Shift記号と混合課題

ステージごとに練習内容を変えることで、プレイヤーのゲーム内進行と、現実のタイピング練習が同期するようにしました。

単キーだけだと単調になるので、各ステージには左右交互、短いまとまり、スペース入りの課題も混ぜています。

たとえばステージ1では、fj の単キーだけでなく、次のような課題も出ます。

static const char *const stage1_words[] = {
    "f",
    "j",
    "fj",
    "jf",
    "ff",
    "jj",
    "fjjf",
    "jffj",
    "f j",
    "j f",
    "fj fj",
    "jf jf"
};

最初は小さなCプログラムからのスタート

最初は kumdor_01.c だけの小さなCプログラムでした。

プレイヤー、敵、ステージは struct で管理しています。

typedef struct {
    const char *name;
    int hp;
    int max_hp;
    unsigned char status;
    int correct_count;
    int miss_count;
    int input_error_count;
    int reached_stage;
    int level;
    int exp;
} Player;

typedef struct {
    const char *name;
    int hp;
    int max_hp;
    int attack;
} Enemy;

最初は単純な1戦のバトルでしたが、PlayerEnemy を構造体にしておいたことで、あとから経験値、レベル、スコア、状態異常を足しやすくなりました。

入力は fgets で1行読み取り、strcmp で課題と完全一致するか判定しています。

static int is_correct_input(const char input[], const char target[]) {
    return strcmp(input, target) == 0;
}

スペース入りの課題を扱いたかったので、scanf ではなく fgets を使っています。

RPGらしさを足していく

タイピング練習だけだと味気ないので、RPGらしい要素を少しずつ足しました。

  • 複数の敵
  • 10ステージ制
  • プレイヤーHPと敵HP
  • タイプミス時の反撃
  • ステージ突破時の回復報酬
  • 経験値とレベルアップ
  • スコア、命中率、評価
  • 毒と暗闇の状態異常

経験値はステージ突破時に入ります。一定値に達するとレベルアップし、最大HPが増えてHPが全回復します。

EXPを4獲得した!
【レベルアップ】Lv:2 最大HPが12になった! HP全回復!
現在のEXP: 2/10

こういうメッセージを表示すると、ただ課題を入力しているだけではなく、プレイヤー自身が少しずつ強くなっている感じが出ます。

セーブと中断

ターミナルゲームでも、途中でやめたくなることはあります。

そこで、ステージ突破時の自動セーブと、入力欄からの中断コマンドを入れました。

セーブデータは kumdor_save.txt に保存します。

KUMDOR_SAVE_V1 1 10 10 0 0 0 0 1 1 0

保存しているのは、次に始めるステージ番号、HP、最大HP、状態異常、スコア、到達ステージ、レベル、経験値です。

敵HPの途中状態は保存していません。中断セーブでは、現在ステージの先頭から再開します。

これは仕様として割り切りました。実装がシンプルになりますし、タイピング練習ゲームとしても、ステージの最初から再開するほうが分かりやすいからです。

ターミナル表示を読みやすくする

ターミナルゲームでは、表示の区切りがかなり大事です。

最初はステージ突破と次ステージ開始が続いて表示され、どこで一区切りなのか分かりにくい状態でした。

そこで、次のように表示を分けました。

  • ステージ突破
  • 次ステージへの移動
  • ステージ開始
  • 戦闘開始
  • 通常ターン
  • スコア表示

ステージ開始は枠で囲み、戦闘開始は BATTLE START として別の枠にしています。

=========================================
【第5/10ステージ】
練習内容: 上段の広がり: q / w / e / i / o / p
指使い  : 小指・薬指・中指を上段へ伸ばし、戻る位置を意識する。
敵      : 上段の魔術師
=========================================

*************** BATTLE START ***************
上段の魔術師が立ちはだかった!
********************************************

ターミナルでも、少し区切りを入れるだけでゲームの流れが見えやすくなります。

コードを分割する

最初は1ファイルで十分でしたが、ステージ、セーブ、経験値、表示、スコアが増えてくると、kumdor_01.c だけでは見通しが悪くなります。

そこで、最終的にこの構成に分けました。

kumdor_01.c       エントリポイント
include/game.h    共有定義
src/game.c        ゲーム進行、戦闘、セーブ、スコア表示
src/stages.c      ステージ、敵、出題課題の定義

kumdor_01.c は互換用の入口として残し、実際のゲーム本体は run_game() に移しています。

#include "game.h"

int main(void) {
    return run_game();
}

ステージ定義は src/stages.c に切り出しました。

const Stage *get_stages(int *stage_count) {
    *stage_count = (int)(sizeof(stages) / sizeof(stages[0]));
    return stages;
}

細かく分けすぎると逆に読みにくくなるので、今回は battle.csave.c までは作っていません。まずは、ゲーム進行とステージデータを分けるくらいがちょうどよいと判断しました。

GitHubで公開するための準備

GitHubで公開するにあたり、次のものを整えました。

  • README
  • MIT License
  • .gitignore
  • v0.1.0 表記
  • v0.1.0 Gitタグ
  • ビルド手順
  • 実行方法
  • プレイ例

作業用メモだった HANDOFF.mdkumdor_01_explanation.md は公開対象から外しました。ローカルには残しつつ、.gitignore に追加しています。

.gitignore では、実行ファイルやセーブデータも管理対象から外しています。

kumdor_01
kumdor_save.txt
HANDOFF.md
kumdor_01_explanation.md
*.o
*.out
.DS_Store

ビルドは make で行います。

make
./kumdor_01

不要になった実行ファイルは make clean で削除できます。

make clean

作ってみて分かったこと

C言語でも、小さなターミナルゲームなら十分楽しく作れます。

今回やってみて、特に効果があったのは次の点でした。

  • struct にまとめると機能追加が楽になる
  • 入力は早めに fgets にしておくとスペース入り課題に対応しやすい
  • ターミナル表示は区切り線と見出しが大事
  • セーブ機能は小さくても満足度が高い
  • 学習ゲームは「最初から全部やらせない」ほうが面白い

特に、段階的に使えるキーが増えていく設計は、タイピング練習とゲーム進行の相性がよいと感じました。

今後やりたいこと

v0.1.0 としては、最初から最後まで遊べる状態になりました。

今後改良していくなら次のような内容です。

  • ステージごとの課題バランス調整
  • 戦闘やセーブ処理のさらなるファイル分割
  • ステージ演出の追加
  • セーブデータ形式の拡張
  • curses などを使った画面制御

ただ、今のシンプルなターミナルログ形式も気に入っています。

おわりに

「クムドールの試練」は、C言語の練習として始めた小さなターミナルゲームです。

最初は1ファイルの小さなプログラムでしたが、敵、ステージ、セーブ、経験値、スコア、段階的なタイピング練習を足していくことで、ひとまず1本の小さなゲームになりました。

UNIX的な道具立てだけで、小さく作って、動かしながら育てる。

そういう開発の楽しさを改めて感じたプロジェクトでした。

Repository:

C言語の次にUnityやUnreal Engineを学ぶ選択肢

用途ごとに選ぶ C言語のおすすめ本

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

のいのアバター のい UNIX Cafe マスター

Macintosh Color Classicから始まった旅は、長いWindows時代を経て、Windows10のサポート終了をきっかけにUNIXの世界へ戻ってきました。UNIX Cafeでは、UNIX・Linux・そしてMacな世界を、むずかしい言葉を使わず、物語のように書いています。プログラミングは、アイデアをコンピューターに伝えるための言葉です。簡単な単語と文法を覚えれば、誰でもコマンドを使えます。ぜひ一度、やさしいプログラミングの世界をのぞいてみてください。

目次