トレーナーAI

Last-modified: 2019-04-17 (水) 01:32:34

CPUトレーナーの挙動を求めるプログラムについての解析資料(FR)

CPUの技選択がスクリプト処理なのに対し交代処理は全てアセンブリコードで実行されています。
新規に交代処理を追加するにあたって最低限必要な情報を纏めています。
あくまで動作の再現ができるだけで正確には異なる用途の処理である可能性があります。

アセンブリ関数

0xe1fc:交代先のセット

引数
r00x01
r10x02
r20x00

引数の詳細不明。
この関数を呼ぶ際の事前処理として0x02023f48のポインタに0x92を加算したアドレスに交代先の手持ち番を代入する。

0x1e7dc:タイプ相性判定

引数
r0技ID
r1攻撃対象のポケモンID
r2攻撃対象の特性ID
返り値
r0相性判定結果

交代判定処理内で使われるタイプ相性判定関数。

0x37eb0:交代処理

トレーナーの交代動作が実行される際に呼び出されるプログラム。

0x391ec:交代判定根幹ルーチン

諸々の交代判定を呼び出す根幹ルーチン。
かげふみやじりょく等の交代不可効果を持った特性や技の分岐もここで行われている。

0x388f4:ほろびのうた判定

素FRのCPU交代条件であるほろびのうた判定を行っている。
交代する確率は100%で交代先はランダム(0x06固定)。

0x38958:ふしぎなまもり判定

素FRのCPU交代条件であるふしぎなまもりでの詰み判定を行っている。
交代する確率は66%で交代先はふしぎなまもりの相手に対して抜群の技を持つポケモン。

0x38ae8:もらいび、ちくでん、ちょすい判定

CPU側の控えにこれらの特性を持つポケモンがいて尚且つ対応タイプの技をプレイヤー側が使用した時に交代する。
交代する確率は33%で交代先は当該特性を持つポケモン。

0x38d04:しぜんかいふく判定

場に出ているポケモンがしぜんかいふくで尚且つ眠っており、HPが半分以上の場合に交代する。
交代する確率は50%で交代先は相手が使った技を半減以下にできるポケモン又はランダム。

0x38e04:受け出し判定1

場に出ているポケモンが相手ポケモンに対し弱点を突ける技を持っているか判定する。

0x38f4c:受け出し判定2

場に出ているポケモンの能力ランク上昇数の合計が+3以下か判定する。

0x38f94:受け出し判定3

受け出し判定1、受け出し判定2と合わせて実行される。
相手ポケモンに対し弱点を付けるポケモンがいた場合に交代する。
交代する確率は50%。

交代条件の新規追加方法

アセンブリコードを書けることが前提です。
0x391ecを逆アセンブルして新たにbl文を埋め込むか0x39372付近に割り込む方法で判定処理を追加できます。
このページでは割り込みについて紹介します。

例文:

.thumb
.org 0x39372
	ldr r0, =main+0x08000000+1
	bx r0
.ltorg
/*処理を追加する空き領域のアドレス-0x08000000を指定*/
.org 0xAAAAAA
main:
	push {r4}
	ldr r4, =0x080388f4+1
	bl linker
	cmp r0, #0x0
	bne end
	bl test
	cmp r0, #0x0
	bne end
/*更に交代処理を追加する場合はここにbl文を書き足してr0が0なら次の処理
それ以外ならendへジャンプする処理を追加する*/
end:
	pop {r4}
	cmp r0, #0x0
	bne s393cc
	ldr r0, =0x0803937c+1
	bx r0
s393cc:
	ldr r0, =0x080393cc+1
	bx r0
/*素早さランクが4以下の場合に交代する*/
test:
	push {r4-r7, lr}
	ldr r0, =0x02023b24
	ldrb r0, [r0, #0x0]
	ldr r4, =0x0807497c+1
	bl linker
	mov r5, r0
	mov r1, #0x58
	mul r0, r1
	ldr r1, =0x02023b44
	add r0, r1
/*素早さランクの取得*/
	ldrb r0, [r0, #0x1b]
/*4より大きな数だった場合はtest_failへジャンプ*/
	cmp r0, #0x4
	bhi test_fail
	lsr r0, r5, #0x1
	ldr r1, =0x02023f48
	ldr r1, [r1]
	add r1, #0x92
/*交代先をランダムにする場合には手持ち番を6に設定する*/
	mov r2, #0x6
	strb r2, [r1, r0]
	mov r0, #0x1
	mov r1, #0x2
	mov r2, #0x0
	ldr r4, =0x0800e1fc+1
	bl linker
/*交代する場合には0xe1fcで手持ち番をセットしr0に1を返す*/
	mov r0, #0x1
	b test_end
/*交代しない場合にはr0に0を返す*/
test_fail:
	mov r0, #0x0
test_end:
	pop {r4-r7, pc}
linker:
	bx r4
.ltorg