SFC版ドラゴンクエスト3の行動順と素早さの関係
DQ3乱数を使って先攻率を求めるページ
SFC版DQ3先攻率のシミュレーターターンごとの素早さの計算式は
(素早さ+20)*(0~255)/256 [端数切り捨て]
だけど、0~255の部分は一様分布乱数ではない。
説明はリンク先に。ブログには解析関係のことを書いてみる。
どんな分布なのか想像・・・
割合vs乱数 のグラフ(Xが0~16*31)をA,B,C,Dの4つに分割(136から632をほぼ等分)。AとC、BとDをそれぞれ足しあわせた感じの分布だと思われる
ROM解析
サブルーチン
- サブルーチン(SR) $0014D4
$00~$FFの一様分布乱数rndとXレジスタとの論理積AND(rnd,X)を16個合計しAレジスタに加算した値をXXとする。XXを256で割った余り(XX%256)をAレジスタの値として返す。(SR呼び出し時のXレジスタはビットマスクなので(2^n - 1)を使う?)
- SR $001457
ターン中の素早さの計算で利用。A=136, X=31にして$0014D4を呼び出す
- SR $025D56
メインのSR。行動可能か判定するSR、生存判定、素早さの取得などのSRを呼び出す。 上の2つのSRを利用しながらそのターン中の素早さを計算する。この値はメモリに書き込まれるが直後にSR $025DACによりキャラクターの位置(番号)を行動順に並べる処理でターン中の素早さの値は失われる(*)。
(*サイズは2バイトで一時的に7e2484以降に12キャラ分書き込まれる(プレイヤーキャラ4人と敵8体)。その後、SR $025DACを呼び出してこれらのメモリを参照して最大値を探し、そのキャラの位置を7E23B8以降に書き込んだらその素早さを0に書き換えてゆく。7E23B8以降に行動順にキャラクターの位置(番号0~11)が並ぶことになる。そのターンの素早さは1フレーム経過する間もなく0で上書きされるので、確認するにはレジスタの値を取得するとか乱数計算をシミュレーションするなどしないといけない)
- SR $025DAC
ターン中の行動順序設定。ターン中の素早さが高い順にキャラクターの位置を7E23B8以降に書き込む
ターン中の素早さが被った場合を調査
レジスタ上でターン中の素早さを同じ値に書き換えて行動順を確認。
(以下、需要があるかわからないがなんとなく調査でやったことを記述)
Geiger's Snes9x DebuggerでROMを読み込んで[run]を押して戦闘をする。[breakpoints]を押してターン中の素早さをRAMに書き込む瞬間(C25D98<snes address>)にbreakpointを設定して[run]を押す。
C25D98 STA $2484 "Y" (2バイトデータ、Y=0,2,4,...22)
生存かつ行動可能な場合、1+((素早さ+20)*(XX%256)/256)が格納される。
Aレジスタが0ではないものをDebug Consoleウィンドウの[Edit Register]ボタンを押してダイアログを開きAレジスタを1以上の適当な値に設定。
メニューのFileからPauseをチェック。[Run]をおしてフレームアドバンスなりスロー再生して行動順を確認。
結果はプレイヤーが先頭から順に行動し、次にモンスターが左から順に行動した。
10 | 2024/11 | 12 |
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
どちらかというとゲームはプレイするものじゃなくてプレイを"みる"ものだと思っている。
逆アセンブル解析というのをかじったものの放置していたが、某放送の影響で解析を再開。
2を初クリアしたのは2011.3.10。ブログの内容はSFC版ドラクエ1・2の解析がメイン。最近はjavascriptとかluaをある程度扱えるようになったので、botでルート検証とかできたらと思いつつも進んでいない。
要点をまとめたり文章書くのが苦手なので記事が長ったらしかったり、日本語のようで日本語でなかったりする。プログラム用語が使えるようになりたいかも。
ツイッター: https://twitter.com/bamb00h
ブログに公開せずツイートのみの情報もあり(twilog)