5.26. はなす

5.26.1. モデル
5.26.1.1. 構造体 $C808DA: 「はなす」対象
5.26.1.2. 構造体 $C893D4: 「はなす」対象分類
5.26.1.3. データ
5.26.2. 処理手順
5.26.2.1. 例:ルイーダ

まずは「はなす」コマンドの対象であるオブジェクトのすべてを表現する ROM データの構造について説明する。 また、それらの構造それぞれについて、その型のオブジェクトデータを解釈して得られるテキスト CSV ファイルを提示する。 それから「はなす」コマンドを実行するときのプログラムの手順を、可能な限りコードを引用した上で説明する。

5.26.1. モデル

移動モードではプレイヤーの操作するパーティーとは他に、人々や動物、ときには魔物のが画面内をフラフラとしている。 基本的にはパーティーの先頭者の正面にこれらのオブジェクトが存在すれば、コマンド「はなす」が成功することになっている。 これらの「はなす対象オブジェクト」のデータとして、いつものように配列の形式で定義されている。 以下、この「はなす対象オブジェクト」の構造を説明する。

5.26.1.1. 構造体 $C808DA: 「はなす」対象

ROM のアドレス $C808DA には次の表で示すような型の 12 バイト長オブジェクトが 0x056D 個配列されている:

表 5.52 構造体 $C808DA

オフセット 属性
#$00 #$003F (調査中)
#$00 #$3FC0 分類
#$01 #$00C0 向き
#$02 #$01FF MX
#$03 #$03FE MY
#$04 #$001C LV
#$04 #$07E0 領域
#$05 #$00F8 (未使用)
#$06 #$FFFF 歩行処理サブルーチン
#$08 #$00FF
#$09 #$FFFF はなす処理サブルーチン
#$0B #$00FF

属性の集合を見てわかるように、この構造体の役割は前作の 4.4.1.2 構造体 $FF243C: 「はなす」対象標準版 と同じだ。 以下、新たに加わった属性について説明を与える。

分類

分類とは、次節で説明する対象オブジェクトの ID を値とする属性だ。 前作ではスプライト ID を値とする属性があったのだが、本作ではこれに取って代わった。 詳しくは次節で説明する。

領域

領域とは、この対象オブジェクトが配置空間内のどの領域、言い換えると屋内・屋外に存在するのかを示す値の属性だ。 いわゆる屋内・屋外の切り替え時に、この値の更新が発生する。

プレイヤーキャラクターが領域 A にいて、「はなす」対象オブジェクトが領域 B にいるとする。 このとき、たとえ両者が隣り合う位置にいて、かつプレイヤーが対象オブジェクトのほうを向いていても、 コマンド結果は「その方向には~」となるはずだ。

5.26.1.2. 構造体 $C893D4: 「はなす」対象分類

ROM のアドレス $C893D4 には次の表で示すような型の 9 バイト長オブジェクトが 0x7D 個配列されている:

表 5.53 構造体 $C893D4

オフセット 属性
#$00 #$01FF スプライト
#$01 #$00FE 声色
#$02 #$00FF 透明時の代理オブジェクトの分類
#$03 #$FFFF 変身時の反応
#$05 #$00FF
#$06 #$FFFF 透明人間への反応
#$08 #$00FF

この構造体は、前作の「はなす」系構造体にあったスプライト属性を拡張して、新しく別の構造体に切り出したものとみなせる。 以下、新たに加わった属性について説明を与える。

声色

声色とは、ドラクエの台詞表示に伴うあの独特の音声を指定する値をとる属性だ。 実際に設定されている値は次に示すとおり:

表 5.54 声色

内容
#$00 (なし)
#$4B 中音
#$4C 高音
#$4D 低音

透明時の代理オブジェクトの分類

透明代理オブジェクトとは、パーティーがきえさりそうやレムオルの呪文で透明になるときに、 この分類オブジェクトの代わりを別の分類オブジェクトが果たすようになるのだが、 その別オブジェクトを指定する ID 値をとる属性だ。

変身時の対応

変身時の対応とは、パーティーがへんげのつえを使って変身している状態で話しかけられたときの、 この分類オブジェクトの振る舞いの処理を行うコードの開始アドレスの値をとる属性だ。

透明人間への反応

透明人間への反応とは、パーティーがきえさりそうやレムオルの呪文で透明になっている状態で話しかけられたときの、 この分類オブジェクトの振る舞いの処理を行うコードの開始アドレスの値をとる属性だ。

5.26.1.3. データ

付録 B データ で前述の二構造体オブジェクトデータを解釈して作成した CSV ファイルを提供する。

5.26.2. 処理手順

サブルーチン $C6769D が「はなす」処理の主要部だ。 処理手順の構造は前作の 4.4.2 処理手順 のマイナーチェンジ版であるので、 以下、変更部分しか説明しない:

特に意味はない

単に carry レジスターをオンにするだけのサブルーチンを呼び出す。

前作ではまずパーティーが「はなす」コマンドを実行可能かどうかをテストした。 しかし馬車のない今作ではこのテスト工程は論理的に不要だ。 ところが、前作で作成したコードはなるべくそのままコピーアンドペーストして流用したい。 そこでこのような処置を取ったと推察できる。

各種変数を設定・保存する Part 1

パーティーメンバーのうち生存状態の者と、 処理が「はなす」なのか「しらべる」なのかを区別する値を設定・保存する。 後者の値はメッセージ表示時の声色演出に影響する。

パーティー先頭のほぼ正面に「はなす」対象者がいるかどうかテストする

前作とほぼ同様の座標値比較アルゴリズムを適用する。 テストに失敗した場合は「はなす」実施済みマークをテストする工程までジャンプする。

各種変数を設定・保存する Part 2

「はなす」処理最中であることを示すフラグ、 「はなす」対象者の(話し始める直前の)向きの各値を設定・保存しておく。

「はなす」対象者の向きを変更するかテストする

前作と同様だ。

移動モードメッセージを出力するかテストする

前作と同様だが、無効なメッセージ ID として #$0000 を用いる。

「はなす」対象者に関連付けられている処理を実行する

ここは前作と大きく異なる。新規実装サブルーチンを実行することで対象者の振る舞いを指示している。

本来の振る舞いで初期化

「はなす」対象オブジェクトの「はなす処理サブルーチン」属性である完全アドレス値を変数 $001D9A に設定する。 この後の各テストにひっかからなければ、このサブルーチンがそのまま実行される。

透明テスト

変数 $7E353B のレムオル状態またはきえさりそう状態に対応するビットを見る。 つまり、パーティーが透明であるかどうかを試す。 もしどちらかの状態でもなければ、後述の工程「固有処理へジャンプして終了」にジャンプする。

透明であれば、「はなす」対象オブジェクトの「透明状態を考慮するか」フラグをテストする。 もし考慮するならば、A = 6 として、後述の工程「アドレスをロードする」にジャンプする。 考慮しないのであれば、後述の工程「固有処理へジャンプして終了」にジャンプする。

魔物テスト

変数 $7E353B のへんげのつえ状態に対応するビットを見て、 パーティーが現在へんげのつえを使用しているかどうかを試す。 使用中でないか、または「はなす」対象オブジェクトの「変身状態を考慮するか」フラグが 0 であれば、 後述の工程「固有処理へジャンプして終了」にジャンプする。

もし考慮するならば、A = 3 として、後述の工程「アドレスをロードする」にジャンプする。

アドレスをロード

「はなす」対象オブジェクトに対応する分類オブジェクトを配列 $C893D4 から参照し、 A の値に応じて「変身時の対応」属性値または「透明人間への反応」属性値である完全アドレス値を得る。 それから変数 $001D9A にこの値を上書きする。

固有処理へジャンプして終了

変数 $001D9A に設定されているアドレスにジャンプする。

「はなす」実施済みマークを更新する

変数 $7EC371 をインクリメントする。意味は前作と同様だ。

メッセージウィンドウを消去する

ユーザーのコントローラー入力を待ってメッセージウィンドウを消去する。コードは前作と同様だが、 今作の「はなす」オブジェクトのウィンドウ消去フラグ属性はどれも 1 なのでこうなる。

「はなす」対象者の向きを復元するかテストする

前作と同様。

「はなす」実施済みマークをテストする

前作と同様。

終了する

前作と同様。

こうしてみると、主人公パーティーの外見上の違いによる処理の分岐が際立っている。

5.26.2.1. 例:ルイーダ

ルイーダの処理がどのように指定されているのかを見てみよう。 本処理の方は 5.15 ルイーダの酒場 で述べるので、ここでは変身時の処理と透明人間の処理を見る。 配列 $C893D4 をダンプすることで、 それぞれのコードが $CDBC2B および $CDB6C0 に定義されていることがわかる。

パーティー変身時の処理は次のようなものだ。 ここで、サブルーチン $CDB4CE では変数 $001D9A に本来のはなす処理アドレス値をリロードして、 ジャンプするという内容だ。

CD/BC2B:    22D7B4CD    JSR $CDB4D7
CD/BC2F:    220EB5CD    JSR $CDB50E         ; へんげのつえで魔物に変身しているかテスト
CD/BC33:    B003        BCS $BC38           if(魔物でない){
CD/BC35:    4C42BC      JMP $BC42               goto スライムテスト
                                            }
CD/BC38:    008C0F      BRK #$0F8C          ; #$0F8C: なによ あんたたちっ![AD]ここには 強い人たちが[AD](...)
CD/BC3B:    22B0B4CD    JSR $CDB4B0
CD/BC3F:    4C59BC      JMP $BC59           goto 終了
                                            スライムテスト:
CD/BC42:    221FB5CD    JSR $CDB51F         ; へんげのつえでスライムに変身しているかテスト
CD/BC46:    B003        BCS $BC4B           if(スライムでない){
CD/BC48:    4C55BC      JMP $BC55               goto 通常処理
                                            }
CD/BC4B:    008D0F      BRK #$0F8D          ; #$0F8D: あらあら いらっしゃい。[AD]でも ゴメンね。スライムの(...)
CD/BC4E:    22B0B4CD    JSR $CDB4B0
CD/BC52:    4C59BC      JMP $BC59           goto 終了
                                            通常処理:
CD/BC55:    22CEB4CD    JSR $CDB4CE         ; はなす対象者既定の振る舞い
                                            終了:
CD/BC59:    6B          RTL

パーティーが透明である場合の処理は次のようになる:

CD/B6C0:    00550F      BRK #$0F55          ; #$0F55: ここは ルイーダの酒場。[AD]冒険者たちが……[AF][AD]……って なんだ。[AD]だれも いないじゃない。
CD/B6C3:    22B0B4CD    JSR $CDB4B0
CD/B6C7:    6B          RTL