DeSmuME用デバッガと霊界の布ときのみスクラッチ
Pokémon RNG Advent Calendar 2017の12日目の記事です。
DeSmuME用デバッガ
DeSmuME用デバッガを作りました。
DeSmuMEはGDB Remote Stub Protocolを実装しています。これを使ってDeSmuMEとやり取りしデバッガの動作を行っています。
ARMとGDB StubであればDeSmuMEに限らずほかのエミュレータでも動くかもしれません。(未チェック)
というわけで、DS用ゲームを解析したい方、どうぞご利用ください。
TODOは以下の通り
と、これだけではRNGともPokémonとも関係ない記事になってしまうのでポケモンの乱数の話をします。
霊界の布
ダイヤモンドパールで霊界の布をゲットする乱数調整を行いました。
きのみスクラッチ
プラチナ、HGSSのバトルフロンティアにおけるきのみスクラッチを解析しました。
どういう仕組みできのみが決まっているのか日本語で解説するのは面倒なのでseedを入力したらそのときの結果を出力するプログラムを貼ります。Rubyで書いています。
# Pt, HGSSでのフロンティアのきのみスクラッチ class LCG def initialize(seed) @seed = seed end def clone LCG.new(@seed) end def rand() @seed = (@seed * 0x41c64e6d + 0x6073) % 2**32 @seed >> 16 end def rand_n(n) rand() % n end end ITEM_LIST = [0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8] ITEM_NAMES = { 0x005C => "きんのたま", 0x00A9 => "ザロクのみ", 0x00AA => "ネコブのみ", 0x00AB => "タボルのみ", 0x00AC => "ロメのみ", 0x00AD => "ウブのみ", 0x00AE => "マトマのみ", 0x00B8 => "オッカのみ", 0x00B9 => "イトケのみ", 0x00BA => "ソクノのみ", 0x00BB => "ソンドのみ", 0x00BC => "ヤチェのみ", 0x00BD => "ヨブのみ", 0x00BE => "ビアーのみ", 0x00BF => "シュカのみ", 0x00C0 => "バコウのみ", 0x00C1 => "ウタンのみ", 0x00C2 => "タンガのみ", 0x00C3 => "ヨロギのみ", 0x00C4 => "カシブのみ", 0x00C5 => "ハバンのみ", 0x00C6 => "ナモのみ", 0x00C7 => "リリバのみ", 0x00C8 => "ホズのみ", } def make_scratch(lcg) # メタモンの位置決め arrange = Array.new(9, nil) 2.times do |i| while true i = lcg.rand_n(9) if not arrange[i] arrange[i] = 4 break end end end #きのみの配置を決定 item = lcg.rand_n(4) count = 0 9.times do |i| x = lcg.rand_n(9) if not arrange[x] count = 0 arrange[x] = item if i == 2 or i == 4 or i == 6 item = (item + 1) % 4 end else count += 1 redo if count < 30 count = 0 9.times do |j| next if arrange[j] arrange[j] = item if i == 2 or i == 4 or i == 6 item = (item + 1) % 4 end break end end end # アイテムを決定 items = Array.new(4, nil) i0 = lcg.rand_n(4) 4.times do |i| if i == i0 items[i] = 0x5c else item = ITEM_LIST[lcg.rand_n(23)] redo if items.include?(item) items[i] = item end end [arrange, items.map{|x| ITEM_NAMES[x] }] end def main() print "seedを入力> 0x" seed = gets.to_i(16) print "最大消費数を入力> " max_f = gets.to_i lcg = LCG.new(seed) max_f.times do |f| puts "消費#{f}:" l = lcg.clone() 3.times { p make_scratch(l) } lcg.rand() end end main() if $0 == __FILE__