ソースコード読解に興味ある方へ


概要

 ゲームの内部事情に興味があって、幻想蛮怒のソースコードを読むのにちょっとトライしてみたいなと思う方向けの記事です。ソースコードの導入(DL)方法、読むのに便利なもの、いくつかの読解事例を紹介します。

※以下の内容はv2.0.12のものを題材にして記述しています。「◯行目」のようなところが徐々に乖離していくと思いますが、ご承知おきください。

ソースコードのダウンロード

 幻想蛮怒配布サイトの下部「ソースコード」からのリンクを辿ってgithubへ。top画面の中央右より「Code」>「Download ZIP」でファイル一式をダウンロードできます。解凍した中身のうち、「src」フォルダの中身が今回の対象です。どのファイルもwindows付属のメモ帳で開けますが、そのまま/それだけだとかなり読みづらいですので、以下の「あると便利なもの」も導入することをお勧めします。

図:ソースコード一式のダウンロード

読解にあると便利なもの

テキストエディタ
 メモ帳も広義ではテキストエディタですが、ここではプログラミング向けの高機能なものをいいます。プログラム言語の構文を見やすく可視化してくれるので、可読性が劇的に向上します。「テキストエディタ」でweb検索すると、お勧め紹介サイトがたくさん出てきます。どれでも大丈夫ですが、「プログラミング」とか「コーディング」みたいな言葉が併記されていたり、使用画面のスクリーンショットで文字がカラフルになっているやつだと間違いありません。
図: 左=win11付属メモ帳、右=テキストエディタ(TepaEditor)

grepツール
 ファイルを横断して文字列を検索することができるツールです。これも「grepツール」で検索すると色々出てきます。↑のテキストエディタの中でも高機能なものには備えているものもあるようです。本稿ではこれを使うほどの読解はほぼ扱わないのですが、ある処理の中で別のファイルにある処理を行う、ということがよくありますので、そういうのを読み進める時に便利です。また、ゲーム内で気になるメッセージを見た時に、それで検索を掛けて、起こった事象の内実を読み解くようなことにも使えます。
図: grepツール(TresGrep)でアレを食らった時のメッセージを検索した例


読解のための参考文書

 この記事では個別の読解事例を例示するだけですが、おそらく本業とされている方が書いていると思しき、プログラムをプログラムとして読み進める作法を、ローグライクを題材にして解説した記事を紹介します。


 なお、幻想蛮怒のソースコードは、幻想蛮怒で新規に取り入れられた要素については、作者さんが丁寧にコメントを入れていて、その処理で意図していることや通常プレイにおける結論がほぼ確実に書かれています。そのため、文法がわからなくても書いてあることがわかることが多いです。また、ゲーム攻略的にほしい情報は、この後に示すように、その多くがデータ群が決まった型に並んでいる形です。まずは先行の読解事例を参考にしながら自分で開いてみることをお勧めします。


読解事例

各verの更新事項

 githubの幻想蛮怒top画面の「asamayim」のリンクを踏むと、これまでの更新verが上から新しい順に並んでいます。所望のバージョン(v2.0.12とか)のリンクをたどると、内容に更新があったソースコードのファイルと、その変更箇所を確認できます。また、各verの右にある「<>」から、上の「ソースコードのダウンロード」と同様の方法で、当該バージョンのソースコード一式をダウンロードすることができます。

図: リンクのたどり方

図: 各verの更新事項の様子(v2.0.12)

職業(ユニーククラス)関係

ステータス補正など

ファイル名
tables.c
記述箇所冒頭
const player_class class_info[MAX_CLASS]
一連のデータが並んでいる箇所の冒頭部分の文字列です。これで検索するとverが変わっても見つけやすいはずです。以下、同じ。
解説
2430行目から各クラスの能力修正など一式がならんだデータ群があります。最初から戦士、メイジ、神官(巫女)・・・と一般職が続き、3195行目から宵闇の妖怪(ルーミア)、半人半霊の庭師(妖夢)・・・とユニーククラスが出てきます。ちなみに1556行目からは種族の能力修正など一式が似たような感じで並んでいます。データ群の冒頭のところに簡単に読み方が記載されているので、ついでに見てみてはどうでしょうか。
読解例
5386行目~「森で垂迹した魔法地蔵」


レベルごとの特殊能力など

ファイル名
xtra1.c
記述箇所冒頭
職業とレベル毎の耐性を計算
解説
4986行目から各クラスのレベル毎に得られる特性についてのデータ群があります。最初に「case CLASS_WARRIOR」つまり「職業 戦士の場合は以下のようにする」とあり、以下「case CLASS_ARCHER」「case CLASS_PRIEST」…と続き、5149行目から「case CLASS_RUMIA」と以降ユニーククラスのデータが並びます。ちなみに上記のように「CLASS_XXXX(東方キャラ名)」以下でユニーククラスに関する個別の扱いの記述がされていることが多いので、色々自分で調べる場合は覚えておくといいと思います。特殊性格や、聖の転読のようにレベルごとに強化内容が進化していくバフの効果の内容なんかもここに同様の形で書かれています
読解例
5186行目~ 華仙


クエスト「古い城」の報酬

ファイル名
cmd2.c
記述箇所冒頭
else if(o_ptr->sval == SV_CHEST_OLDCASTLE)
解説
807行目から戦士「if(p_ptr->pclass == CLASS_WARRIOR)」、騎兵「if(p_ptr->pclass == CLASS_CAVALRY)」と、「if … CLASS_XXXX」を目印にした箇条書きで記載されています。905行目以降、華仙「CLASS_KASEN」を筆頭にユニーククラスが並んでいます。
 実は一連の内容は、「箱を開ける」という行為の処理内容の一環として書かれており、この内容の前後には他のクエスト報酬の箱やMARIPOの箱の中身についても列記されています。なお、多分この内容については、所望のクラスのキャラを作り、ウィザードモードで「大きな葛籠=古い城の報酬箱」を生成して開けるのが早いと思います。
読解例
912~933行目


職業特技

ファイル名
new_class_power.c
記述箇所冒頭
ファイル冒頭から記述が始まっている。
個別の職業・キャラは「class_power_type class_power_xxx[] =」(xxxをキャラ名・クラス名に置き換える)
解説
冒頭に概要的なコメントが少々あって、17行目から慧ノ子の内容の記述が始まります。各クラス毎にまず、技の名称、習得レベル、コスト、説明などがカンマ区切りでまとめられたデータ群があり、その後に各特技の個別の処理内容が書かれている、という形です。
読解例
1248行目~ 飯綱丸
 この一連のデータ群の下に、各特技の処理内容が記載されていますが、多種多様にわたり発散してしまうので、ここでは割愛します。多くの場合、威力、効力、効果時間の計算式が書かれています。計算式のところでよく使われる書かれ方をいくつか紹介しておきます。

  • plev や p_ptr->lev:プレイヤーのレベル
  • chr_adj:魅力影響値
  • randint1(xxx):1~xxxの乱数。1d(xxx)と同じ
  • randint0(xxx):0~(xxx -1)の乱数。1d(xxx) -1 と同じ
  • DETECT_RAD_DEFAULT:感知系特技のデフォルト効果範囲、つまり30

 ちなみにこの「new_class_power.c」の下の方(36062行目以降)にはEXTRAモード時のアイテムカードのデータ群があります。アイテムカードは基本的にユニーククラスの職業特技の一部を切り出して行使するものなので、このファイル内にまとまっているようです。

専用格闘パターン

ファイル名
cmd1.c(条件分岐), table.c(個別の格闘パターン内容)
記述箇所冒頭
cmd1.c(条件分岐): int find_martial_arts_method(int findmode)
table.c(個別の格闘パターン内容): const martial_arts_new ma_blows_new[]
解説
格闘及び格闘パターン一覧を参照のこと。


特別なアイテムドロップ処理

この部分はモンスターの固定ドロップアイテムを参照すると理解が深まると思います。

特定モンスターによる特定アイテムドロップ

ファイル名
xtra2.c
記述箇所冒頭
case MON_MORGOTH
解説
2264行目から、『モルゴス』が★グロンドを落とす処理(case MON_MORGOTH )を筆頭に、「case_MON_XXXX」を区切りとした箇条書きで『混沌のサーペント』、デスソード…と2974行目まで続きます。この部分は特定モンスターによる特定アイテムドロップに相当します。モンスターを撃破したときの処理の一環として書かれているので、この上の方には『ロレント』が自爆する処理なんかも書かれています。
読解例
2664行目~ 魔理沙

銃の特別ドロップ

ファイル名
xtra2.c
記述箇所冒頭
if (drop_chosen_item && !gun_free_world)
解説
2997行目から、特定のモンスターが銃をドロップする処理が並んでいます。『清蘭』(case MON_SEIRAN)、『鈴瑚』(case MON_RINGO)が高級品確定のルナティックガンを落とす処理から、『うどんげ』、イーグルラヴィ…と同じく「case_MON_XXXX」を区切りとした箇条書きが3066行目まで続きます。
読解例
3006行目~『清蘭』、『鈴瑚』
※この2体はこれに加え、↑の処理の中で杵や団子を落とす処理が設定されている

特定ユニークによる特定★ドロップ

ファイル名
xtra2.c
記述箇所冒頭
さらに別の分岐でアイテムドロップ処理
解説
3114行目から、特定のモンスターが特定の★を落とす処理が書かれています。ここでは各モンスターの処理の中に「chance = 50」などと書かれており、乱数0~99 < chanceなら落とす、という処理がなされます(この場合は落とす確率50%)。『オベロン』が確定で★アンバー冠か★審判の宝石を落とす処理(case MON_OBERON)から始まり、以下3495行目まで続きます。この部分は特定ユニークによる特定★ドロップに相当します。
読解例
3251行目~ 『ブランド』


属性

「spells1.c」にモンスターが受けた場合と、プレイヤーが受けた場合について書かれています。それぞれ「case GF_XXXX(例えば火炎属性ならGF_FIRE)」を区切りとして箇条書き的に書かれています。複雑な処理も多いので、ここでは比較的簡単なものを例示するに留めます。

モンスターが受ける場合

ファイル名
spell1.c
記述箇所冒頭
Analyze the damage type
解説
2664行目から始まり、以下8975行目まで膨大な数の属性の処理内容が続きます。全耐性持ち(=はぐれメタル)、通常耐性持ち、弱点持ち、普通に効く場合、というように条件ごとに「if」で仕切られて書かれています。
読解例
3310行目からの水属性(GF_WATE)

プレイヤーが受ける場合

ファイル名
spell1.c
記述箇所冒頭
bool project_p(int who, cptr who_name, int r, int y, int x, int dam, int typ, int flg, int monspell)
解説
9797行目から記述が始まります。最初200行程度は烏天狗のボルト無効化のような特別な防御処理について書かれており、10050行目から属性の各論に入り、2000行あまり続きます。最初に攻撃を正しく視認していない場合のメッセージがあり、その後耐性がある場合、そうでない場合のダメージ、そして追加効果、のような流れで記載されています。
読解例
10156行目からの汚染属性(GF_POLLUTE)


モンスターの魔法など

「mspells1.c」の2720行目から記載されています。「case xxx(xxxは内部的な番号)」で仕切られて列記されています。多くのモンスターの攻撃魔法は変愚蛮怒と共通しているので、幻想蛮怒プレイヤーにとって重要と思われる箇所をピックアップしておきます。

幻想蛮怒新規追加の魔法

ファイル名
mspells1.c
記述箇所冒頭
case 192+0:
解説
6401行目から記載されています。なお、従来の内部番号を使い切ったために新たな番号を起こしたという感じのようで、これより前のところに書かれているものもいくらかあります(コズミックホラーなど)。
読解例
6499行目からの原子分解



「特別な行動をすることがある」の内容

ファイル名
mspells1.c
記述箇所冒頭
RF6_SPECIAL
解説
4811行目から記載されています。原作ネタをモンスターの技でどう表現するか、という点でなかなかの見どころだと思いますし、今後も追加が期待されるところでもあります。
読解例
5064行目~ 『奥野田 美宵』の酒を飲ましてくる特技


「救援召喚」の特殊処理

ファイル名
mspells1.c
記述箇所冒頭
RF6_S_KIN
解説
「救援召喚」は通常は使用者と同じシンボルのモンスターを召喚するものですが、特殊処理で特定のモンスターを呼ばせる設定が多数なされています。
 5477行目から記載されています。
 最初約100行は使用した時のメッセージが特別なものになるものが列記されています(例: 『アリス』が使用する場合の「『アリス』が人形達を呼び出した。」)。
 その後、5561行目から個別の召喚内容が書かれています。
読解例
5563行目~ 大鷲ユニークと『マミゾウ』
 ここだけでは少しわからないところが残りますね。大鷲ユニークの場合の「SUMMON_EAGLES」、『マミゾウ』の場合の「MON_TANUKI」、「MON_O_TANUKI」の中身が具体的には何なのか、です。こういう時に、最初に紹介した「grepツール」で検索すると答えが見つかります。前者は「monster2.c」の691行目からのデータ群の中の969行目で規定されていて、「Bシンボル 且つ 山 且つ 野外 のモンスター」となっています(結果的に、鷲、大鷲、自身より下位の大鷲ユニークが出てきます)。後者は「defines.h」内でモンスターのIDで規定されています。具体的には「No. 1228 妖怪狸」と「No. 1229 妖怪古狸」です。


出典(念のため)

 この記事は「Roguelike Advent Calendar 2023」向けに投稿された記事を、筆者本人がこのwiki向けに移植したものです。無断転載とかそういう問題はありませんのでその点安心してください。(リンクは張りません。PV稼ぎみたいにみえるのも嫌なので。)

タグ:

+ タグ編集
  • タグ:
最終更新:2024年02月10日 00:09