今回からは個別の戦闘行動の効果値の算出部分に移ります。算出用の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の「外枠」に相当するものです。これも反射するモンスターがいた場合は即座に評価を中止しています。こうした枠組みは各戦闘行動の属性などとは異なり、どれも同じ仕組みで評価をすることができるため、対象毎に同じ外枠を使うことでコード量を節約することができます。とりあえず今回はこのへんで。
コメント