多少間があいてしまいましたが、徐々に通常モードに復帰します。今回はまだリハビリ中ということで軽めに。
- SR: $025BA3 AI行動決定
025BA3 | LDX $2555 | X=$2555 | |
---|---|---|---|
025BA6 | STX $258B | $258B=X | |
025BA9 | JSL $C2C197 | SR: $02C197 | 行動主体がAI行動決定の必要があるか(ないc=on) |
025BAD | BCS #$5B | if(c==on) goto $025C0A | |
025BAF | PEA #$2515 | Push #$2515 | |
025BB2 | PEA #$0080 | Push #$0080 | |
025BB5 | PEA #$7E00 | Push #$7E00 | まねまね発動中 |
025BB8 | JSL $C92965 | SR: $092965 | |
025BBC | BNE #$4C | if(z==off) goto $025C0A | |
025BBE | PEA #$2516 | Push #$2516 | |
025BC1 | PEA #$0001 | Push #$0001 | |
025BC4 | PEA #$7E00 | Push #$7E00 | 腕輪発動中 |
025BC7 | JSL $C92965 | SR: $092965 | |
025BCB | BNE #$3D | if(z==off) goto $025C0A | |
025BCD | JSL $C2590F | SR: $02590F | AI対象外戦闘行動か(該当c=on) |
025BD1 | BCS #$A3 | if(c==on) goto $025B76 | |
025BD3 | JSL $C2EFA7 | SR: $02EFA7 引数:1#$204F 引数:2#$01FF | |
025BDB | AND #$00FF | A&=#$00FF | |
025BDE | CMP #$0001 | A==#$0001? | 主人公ならAI対象外 |
025BE1 | BEQ #$27 | if(z==on) goto $025C0A | |
025BE3 | JSL $C43488 | SR: $043488 引数:1#$FF | 作戦取得 |
025BE8 | CMP #$0005 | A==#$0005? | めいれいさせろならスキップ |
025BEB | BEQ #$1D | if(z==on) goto $025C0A | |
025BED | JSL $C2EFA7 | SR: $02EFA7 引数:1#$2054 引数:2#$000F | |
025BF5 | CMP #$0000 | A==#$0000? | 受け身中ならスキップ |
025BF8 | BNE #$10 | if(z==off) goto $025C0A | |
025BFA | JSL $C2CF63 | SR: $02CF63 | AI行動決定コア |
025BFE | LDA $258D | A=$258D | |
025C01 | STA $255F | $255F=A | |
025C04 | LDA $2591 | A=$2591 | |
025C07 | STA $2557 | $2557=A | |
025C0A | RTS | return |
このSRがAI行動決定の一番トップのSRです。この中で全てAIに関する行動が決まります。条件に応じてAI行動決定コアSRを飛ばすようになっているだけで、特筆する点はありません。
- SR: $02CF63 AI行動決定コア
02CF63 | PHP | Push P Flag | |
---|---|---|---|
02CF64 | REP #$30 | m=off(A/M:16b) x=off(X/Y:16b) | |
02CF66 | PHA | Push A | |
02CF67 | PHX | Push X | |
02CF68 | PHY | Push Y | |
02CF69 | PHB | Push DB | |
02CF6A | PEA #$7E7E | Push #$7E7E | |
02CF6D | PLB | Pull DB | |
02CF6E | PLB | Pull DB | |
02CF6F | JSR $CF86 | SR: $02CF86 | AI行動決定用RAM領域初期化 |
02CF72 | JSR $CF9B | SR: $02CF9B | AI判断用情報をメモリにセット |
02CF75 | JSR $D01B | SR: $02D01B | 各キャラクター用AI判断用情報セット |
02CF78 | JSR $D15E | SR: $02D15E | モンスター特別種族情報セット |
02CF7B | JSR $D191 | SR: $02D191 | AI行動決定 |
02CF7E | PLB | Pull DB | |
02CF7F | REP #$30 | m=off(A/M:16b) x=off(X/Y:16b) | |
02CF81 | PLY | Pull Y | |
02CF82 | PLX | Pull X | |
02CF83 | PLA | Pull A | |
02CF84 | PLP | Pull P Flag | |
02CF85 | RTL | return |
ここもまだ大きなSRの段階なのでこのSR自体も「まあそんなもん」という感じでしかありません。次回からよく使われるRAMの意味を説明してから更に掘り進んでいきます。
例のAI実装についてはほぼ終わったので、まずは学習機能をOFFにしておかしな行動を取らないかの確認をするべく0からテストプレイをしています(ちんたらやっているのでまだダーマ近辺)。やはりというべきか、ポツポツと期待した通りの動作をしていないのを見つけてデバッグをしながら進めているので進行度合いはかなり遅いです。自動SS採取機能付きのSnes9Xでプレイしているので、再現に手間がかからないのがいいです。現状気になる点として「行動決定までに一瞬間があるキャラクターがいる」という点です。行動可能な戦闘行動についてすべてシミュレーションをする必要がある以上、レベルが上がるほど(行動の選択肢が増えれば増えるほど)トータルの計算量が増え、人間が違和感を感じるレベルまでの遅延が発生する可能性はどうしても防げないのですが、選択肢の少ない序盤にもかかわらず違和感を感じるキャラクターが出てきてしまったのでこれからデバッグをするところです。明らかにバグっていて処理が遅いというのであればバグを直せばいいだけなのですが、問題は「正しい処理をしているが、プログラムの書き方が悪くて遅い」場合の対処法です。理想を言えば「とある箇所でブレークポイントを張り、その次に止まったところまでのサイクル数のカウント及びどのSRでサイクル数を食っているかを表示するプロファイラーのような機能」があれば少なくとも遅い箇所を特定することはできます。実際その箇所の処理を早くできるかどうかは別として、時間のかかっている場所を特定できなければ適切な対処もできないということで、一番近いところにいそうなGeiger’s Snes9x Debuggerにその機能がないかざっくり見てみたのですが、なさそうです。ソースも公開されていなそうなので機能追加するというわけにもいかなそうなので、プレーンなSnes9Xに機能を付けるとしたら結構面倒くさそうです。
コメント
AI行動の計算に入る前に「○○はかんがえている」のようなメッセージを表示すれば遅延によるプレイヤーのストレスを軽減できるかもしれません。
根本的な解決ではありませんが・・・。
そのうちモノを出すので見てもらえばわかりますが、そこまで遅くはないんですよね…。DQ3はDQ6に比べて特技がないぶん選択肢はかなり少ないですが、現状魔法使いと僧侶の呪文を全て覚えたときのみ若干の引っ掛かりを感じるレベルです。
対処法としてはAIなしの場合も若干のウェイトを入れるというのも考えられなくはないですが、AIの遅さをごまかすためにほかも遅くするというのはどうにもすっきりしないのでとりあえず最初の段階では何も対処はしないままリリースすると思います。現在初回クリアまでテストプレイしましたが、初回クリアまでは特に引っ掛かりを感じることはありませんでした。