5.8. ダメージ

5.8.1. 構造に関する構成要素
5.8.1.1. 構造体 $C23BB4: ダメージ
5.8.1.2. 構造体の属性へのアクセス
5.8.2. 振る舞いに関する構成要素
5.8.2.1. サブルーチン $C90AF7: ダメージ決定サブルーチン
5.8.2.2. サブルーチン $C90B3A: ダメージ決定サブルーチン

本節ではダメージ構造体を説明する。 ここで議論するのはダメージのいわば基本量についてであり、 コマンドとキャラクターの状態から決定する、ダメージの計算処理過程の全てを網羅するものではないことを断っておく。

また、ダメージ構造体関連の議論に出てくる「ダメージ」という用語だが、 本書で言うダメージとは、通常の意味に加えて、回復量や永続的な属性値をも含むものとする。 抽象的に表現すると「キャラクターの属性値であり、数量的に表現されているものに対する変化量」ということになるだろうか。

5.8.1. 構造に関する構成要素

5.8.1.1. 構造体 $C23BB4: ダメージ

アドレス $C23BB4 から 50 個、ダメージパターンが定義されている。 各要素のサイズは 5 バイトで、メモリレイアウトは次に示すとおりだ:

表 5.26 構造体 $C23BB4

オフセット 属性
#$00 #$03FF 自陣側実行時の下限値
#$01 #$0FFC 敵陣側実行時の下限値
#$02 #$3FF0 自陣側実行時の上限値
#$03 #$FFC0 敵陣側実行時の上限値

各属性の意味を以下に記す:

自陣側実行時の下限値, 敵陣側実行時の下限値

それぞれ自陣側戦闘員と敵陣側戦闘員が実行するコマンドから決まるダメージの下限値を表す属性だ。 値が 1,023 のときはマジックナンバーとして取り扱う。 このときは後述の抽選を適用せず、値を 65,535 とする。

自陣側実行時の上限値, 敵陣側実行時の上限値

それぞれ自陣側戦闘員と敵陣側戦闘員が実行するコマンドから決まるダメージの上限値を表す属性だ。

ROM データをダンプして属性値を検討すると、自陣と敵陣とで威力が異なるコマンドはそれほど多くないことがわかる。 一部の攻撃コマンドしか該当しない。 そのようなダメージについては、いずれも自陣実行時のほうが敵陣のそれよりも大きい値が設定されている。

5.8.1.2. 構造体の属性へのアクセス

ダメージ構造体のフィールドにアクセスする専用サブルーチンはいくつかあるのだが、 実際にプログラムから参照されているものは $C2CCF8 サブルーチンだけであるようだ。 このサブルーチンは 4 byte のパラメータをとり、 その意味はいつもと同じようなものなので、説明を省く。

表 5.27 ダメージ構造体の属性にアクセスするサブルーチン

サブルーチン 固定引数長 入力 機能
$C2CCCF 2 x 2 バイト長の属性値を取得する(未使用)
$C2CCD6 2 y 2 バイト長の属性値を取得する(未使用)
$C2CCF1 4 x ビットフィールド属性値を取得する(未使用)
$C2CCF8 4 y ビットフィールド属性値を取得する
$C2CD13 4 x ビットフィールド属性値をテストする(未使用)
$C2CD1A 4 y ビットフィールド属性値をテストする(未使用)

5.8.2. 振る舞いに関する構成要素

5.8.2.1. サブルーチン $C90AF7: ダメージ決定サブルーチン

コマンドのダメージ(基本量)を決定するのはサブルーチン $C90AF7 だ。 コマンド実行者とコマンドを入力とし、ダメージ量を出力とする関数とみなすのが理解しやすい。 コードの概要を以下に示す。

C9/0AF7:    08          PHP
C9/0AF8:    8B          PHB
C9/0AF9:    C230        REP #$30
C9/0AFB:    F47E7E      PEA $7E7E
C9/0AFE:    AB          PLB
C9/0AFF:    AB          PLB
C9/0B00:    DA          PHX
C9/0B01:    5A          PHY
C9/0B02:    AEEE23      LDX $23EE
C9/0B05:    ACE423      LDY $23E4
C9/0B08:    22E0CAC2    JSR $C2CAE0    1
C9/0B0C:    3C20
C9/0B0E:    FF00
C9/0B10:    C90500      CMP #$0005
C9/0B13:    9030        BCC $0B45      if(a < 5) goto 実行者が敵陣戦闘員

C9/0B15:    A9FFFF      LDA #$FFFF     ; 65,535
C9/0B18:    48          PHA
C9/0B19:    2225CCC2    JSR $C2CC25    2
C9/0B1D:    7218
C9/0B1F:    FF00
C9/0B21:    A8          TAY
C9/0B22:    22F8CCC2    JSR $C2CCF8    3
C9/0B26:    443B
C9/0B28:    FF03
C9/0B2A:    C9FF03      CMP #$03FF
C9/0B2D:    F03E        BEQ $0B6D      if(属性値 == 1023) goto 終了
C9/0B2F:    AA          TAX
C9/0B30:    22F8CCC2    JSR $C2CCF8    4
C9/0B34:    463B
C9/0B36:    F03F
C9/0B38:    802E        BRA $0B68      goto 抽選

.label 実行者が敵陣戦闘員
C9/0B45:    A9FFFF      LDA #$FFFF     ; 65,535
C9/0B48:    48          PHA
C9/0B49:    2225CCC2    JSR $C2CC25    5
C9/0B4D:    7218
C9/0B4F:    FF00
C9/0B51:    A8          TAY
C9/0B52:    22F8CCC2    JSR $C2CCF8    6
C9/0B56:    453B
C9/0B58:    FC0F
C9/0B5A:    C9FF03      CMP #$03FF
C9/0B5D:    F00E        BEQ $0B6D      if(属性値 == 1023) goto 終了
C9/0B5F:    AA          TAX
C9/0B60:    22F8CCC2    JSR $C2CCF8    7
C9/0B64:    473B
C9/0B66:    C0FF
.label 抽選
C9/0B68:    20750B      JSR $0B75      8
C9/0B6B:    8301        STA $01,S
.label 終了
C9/0B6D:    68          PLA
C9/0B6E:    7A          PLY
C9/0B6F:    FA          PLX
C9/0B70:    AB          PLB
C9/0B71:    28          PLP
C9/0B72:    48          PHA
C9/0B73:    68          PLA
C9/0B74:    6B          RTL

1

5.3.2 戦闘員構造体メソッド で述べるように、 サブルーチン $C2CAE0 の呼び出しは、 戦闘キャラクター Y の各種状態を表す構造体オブジェクトから、 指定の状態を取得することを意味する。

2 5

サブルーチン $C2CC25 を呼び出し、 戦闘コマンドの属性値を取得する。 ここでは引数として #$1872#$00FF を渡して、 この戦闘コマンド X に関連付けられているダメージオブジェクトの ID を取得する。

3 4 6 7

サブルーチン $C2CCF8 を呼び出し、 ダメージオブジェクトから指定の属性値を取得する。 ここで与えている引数と、取得するメンバーの対応は 表 5.26 構造体 $C23BB4 を参照。 オフセットについては #$3BB4#$00 と解釈し、 以下同様とする。

8

同バンクサブルーチン $0B75 を呼び出すことで、 範囲 [X, A] に含まれる値を抽選する。 この乱数を A に入れた状態でサブルーチンを終了する。

このサブルーチンは戦闘中に呼び出される。

5.8.2.2. サブルーチン $C90B3A: ダメージ決定サブルーチン

こちらのサブルーチンもコマンドのダメージ(基本量)を決定する。 先ほどのものとは、入力が X レジスターであることしか違わない。コマンド ID からだけでダメージ値を決定する。 実行者は敵陣側に決め打ちとなる。

このサブルーチンは移動モードのじゅもんまたはどうぐコマンドから利用されている。 だから実行者を敵陣側ではなく自陣側に決め打ったほうが論理的だと思われるのに、そうなっていない。 しかし、データ上は戦闘時と移動時の両方で実行できるコマンドについては、 陣営によらずダメージ量が同じなので問題は起こらない。