DQ6 AI処理の解析5

今回からは個別の戦闘行動の効果値の算出部分に移ります。算出用のSRは大きく分けて2種類あり、1つ目が「外枠のSR」、2つ目が「効果値算出の実体SR」です。外枠というのは「1体のみ」「グループ」「全体」で同じ外枠のSRを使います。対象が1体の戦闘行動は「モンスター1体毎に効果値を計算し、最大になるモンスターをターゲットにする」という処理自体は変わりません。グループ対象の場合はグループごとに効果値を合算し最大になるグループを、全体の場合は単に全てのモンスターの効果値を合算するだけです。モンスター側の耐性にもよりますが、基本的にはこの外枠は変わりません。従ってコード量を減らすために対象が同じ戦闘行動は同じ外枠を使い、効果値算出のところだけ個別のSRをコールすることで余計な重複をカットしています。

実装を見る前に、よく使われるメモリの意味を先に列挙しておきます。

アドレス ビット 意味
DP($00) テンポラリ計算領域
DP($02) テンポラリ計算領域
DP($04) テンポラリ計算領域
DP($0C) 01
02 マヌーサ中
04
08
10
20 山彦の帽子装備中
40
80
DP($0E) 作戦ID
DP($14) 現在評価中の戦闘行動の効果値の最大値
$7E25F3 グループ1効果値合計(グループ対象行動のみ)
$7E25F5 グループ2効果値合計(グループ対象行動のみ)
$7E25F7 グループ3効果値合計(グループ対象行動のみ)
$7E25F9 グループ4効果値合計(グループ対象行動のみ)
$7E2609 01 グループ1に実行すると反撃を食らうモンスターがいる
02 グループ2に実行すると反撃を食らうモンスターがいる
04 グループ3に実行すると反撃を食らうモンスターがいる
08 グループ4に実行すると反撃を食らうモンスターがいる
  • SR: $02D478 AI判断用_SR_0001
02D478 STZ $14 DP($14)=#$00
02D47A LDA #$0017 A=#$0017 戦闘参加キャラクターの最後のインデックス
02D47D STA $258B $258B=A
02D480 LDY #$04AC Y=#$04AC 戦闘参加キャラクターの最後の開始アドレスオフセット
02D483 LDA #$0001 A=#$0001
02D486 STA $254B $254B=A
02D489 STZ $2549 $2549=#$00
02D48C LDA $203E,Y A=$203E+Y
02D48F BEQ #$14 if(z==on) goto $02D4A5 HP0ならスキップ
02D491 JSR $D4B1 SR: $02D4B1 対象のステータスを調べる(無効c=on 反射v=on)
02D494 BCS #$0F if(c==on) goto $02D4A5
02D496 JSR $D4EB SR: $02D4EB 対象の戦闘行動の効果値取得(ダメージ系)
02D499 CMP $14 A>=DP($14)? 効果値の比較
02D49B BCC #$08 if(c==off) goto $02D4A5
02D49D STA $14 DP($14)=A 最大なら差し替え
02D49F LDA $258B A=$258B
02D4A2 STA $2591 $2591=A 対象インデックスも差し替え
02D4A5 TYA A=Y
02D4A6 SEC c=on
02D4A7 SBC #$0034 A-=(#$0034+!c) 1キャラクター分のアドレスを減らす
02D4AA TAY Y=A
02D4AB DEC $258B $258B–
02D4AE BPL #$DC if(n==off) goto $02D48C
02D4B0 RTS return

これは単体対象の戦闘行動のAIの「外枠」に相当するものです。単体行動対象の場合、マニュアルでのコマンド入力とは異なり、対象となるモンスターをインデックスベースで指定できるので、マニュアルより有利ということになります。

  • SR: $02D56C AI判断用_SR_0002
02D56C STZ $258B $258B=#$00
02D56F LDY #$0000 Y=#$0000
02D572 STZ $25F3 $25F3=#$00
02D575 STZ $25F5 $25F5=#$00
02D578 STZ $25F7 $25F7=#$00
02D57B STZ $25F9 $25F9=#$00
02D57E STZ $25FB $25FB=#$00
02D581 STZ $25FD $25FD=#$00
02D584 STZ $25FF $25FF=#$00
02D587 STZ $2601 $2601=#$00
02D58A STZ $2603 $2603=#$00
02D58D STZ $2605 $2605=#$00
02D590 STZ $2549 $2549=#$00
02D593 STZ $2609 $2609=#$00
02D596 LDA $203E,Y A=$203E+Y
02D599 BEQ #$3A if(z==on) goto $02D5D5 HP0ならスキップ
02D59B LDA $204E,Y A=$204E+Y
02D59E AND #$0007 A&=#$0007 グループ番号を取得
02D5A1 ASL A<<1
02D5A2 STA $2607 $2607=A
02D5A5 TAX X=A
02D5A6 LDA $C2D5F9,X A=$02D5F9+X
02D5AA AND $2609 A&=$2609
02D5AD BNE #$26 if(z==off) goto $02D5D5 反射状態の敵がいるグループはスキップ
02D5AF JSR $D4B1 SR: $02D4B1 対象のステータスを調べる(無効c=on 反射v=on)
02D5B2 BVS #$33 if(v==on) goto $02D5E7
02D5B4 BCS #$1F if(c==on) goto $02D5D5
02D5B6 LDX $2607 X=$2607
02D5B9 LDA $25FD,X A=$25FD+X
02D5BC INC A++
02D5BD STA $25FD,X $25FD+X=A
02D5C0 STA $254B $254B=A
02D5C3 JSR $D4EB SR: $02D4EB 対象の戦闘行動の効果値取得(ダメージ系)
02D5C6 LDX $2607 X=$2607
02D5C9 CLC c=off
02D5CA ADC $25F3,X A+=($25F3+X+c)
02D5CD BCC #$03 if(c==off) goto $02D5D2
02D5CF LDA #$FFFF A=#$FFFF
02D5D2 STA $25F3,X $25F3+X=A
02D5D5 INC $258B $258B++
02D5D8 TYA A=Y
02D5D9 CLC c=off
02D5DA ADC #$0034 A+=(#$0034+c) 1キャラクター分のアドレスを増やす
02D5DD TAY Y=A
02D5DE CMP #$04AD A>=#$04AD?
02D5E1 BCC #$B3 if(c==off) goto $02D596
02D5E3 JSR $D603 SR: $02D603 グループ対象戦闘行動対象決定
02D5E6 RTS return
02D5E7 LDX $2607 X=$2607 反射する敵がいるのでこのグループは対象外にする
02D5EA LDA $C2D5F9,X A=$02D5F9+X
02D5EE ORA $2609 Aor=$2609
02D5F1 STA $2609 $2609=A
02D5F4 STZ $25F3,X $25F3+X=#$00
02D5F7 BRA #$DC goto $02D5D5

これはグループ対象の戦闘行動のAIの「外枠」に相当するものです。マホカンタやマホターン受け流しなど、実行すると自分がダメージを受けるような状態になってるモンスターがグループ中に存在する場合は実行をスキップするようにそのグループの値を0にして、以降そのグループに対しては評価を行わない、という点が単体とは異なります。あとは基本的にはグループごとに効果値を合算していき、その合計値の一番高いグループに対して行動する、となっています。

  • SR: $02D633 AI判断用_SR_0003
02D633 STZ $14 DP($14)=#$00
02D635 STZ $258B $258B=#$00
02D638 LDY #$0000 Y=#$0000
02D63B STZ $254B $254B=#$00
02D63E STZ $2549 $2549=#$00
02D641 LDA $203E,Y A=$203E+Y
02D644 BEQ #$17 if(z==on) goto $02D65D HP0ならスキップ
02D646 JSR $D4B1 SR: $02D4B1 対象のステータスを調べる(無効c=on 反射v=on)
02D649 BVS #$27 if(v==on) goto $02D672 反射するモンスターが居るなら実行しない
02D64B BCS #$10 if(c==on) goto $02D65D
02D64D INC $254B $254B++
02D650 JSR $D4EB SR: $02D4EB 対象の戦闘行動の効果値取得(ダメージ系)
02D653 CLC c=off
02D654 ADC $14 A+=(DP($14)+c)
02D656 BCC #$03 if(c==off) goto $02D65B
02D658 LDA #$FFFF A=#$FFFF 合計が#$FFFFを超えていたら#$FFFFでクリップする
02D65B STA $14 DP($14)=A
02D65D INC $258B $258B++
02D660 TYA A=Y
02D661 CLC c=off
02D662 ADC #$0034 A+=(#$0034+c) 1キャラクター分のアドレスを増やす
02D665 TAY Y=A
02D666 CMP #$04AD A>=#$04AD?
02D669 BCC #$D6 if(c==off) goto $02D641
02D66B LDA #$0041 A=#$0041 ターゲット情報は全体
02D66E STA $2591 $2591=A
02D671 RTS return
02D672 STZ $14 DP($14)=#$00
02D674 RTS return

これは全体対象の戦闘行動のAIの「外枠」に相当するものです。これも反射するモンスターがいた場合は即座に評価を中止しています。こうした枠組みは各戦闘行動の属性などとは異なり、どれも同じ仕組みで評価をすることができるため、対象毎に同じ外枠を使うことでコード量を節約することができます。とりあえず今回はこのへんで。