異やけき木

異やけき木

気が向いたら。たぶん遊んでるゲームに関係することだけ。

IDとSV

 IDはID、SVはSVとして別々に認識してる人が多いので、SVはIDから計算できるよ、ってことを書きます。すでに仕組みを知っている人には大したことはないです。

 

 IDは色違い判定に使われています。TIDを前回の記事で説明に使った0xC9E184C0、PIDを0x00004E86として説明します。

 

計算が面倒なら関数電卓に10進数と16進数の切り替えやXORがあるので、それでも求まります。その際はわざわざ2進数に直す必要もないです。

C9E184C0(16進数)

=11001001111000011000010011000000(2進数)

内部的なTIDがこのように記録されているとして、

1100100111100001 | 1000010011000000

と半分に分けます。

さらに、上位と下位の16bitでXOR(排他的論理和)をとります。XORとは、

0+0=0

0+1=1

1+0=1

1+1=0

と、双方が一致するなら0、異なるなら1となる計算です。上位と下位の同じ位同士でそれぞれこの計算を行うと、

1100100111100001⊕1000010011000000

=0100110100100001 ...①

が求まります。(⊕はXORの演算子です。)

同様にして、PIDも計算します。

00004E86(16進数)

=00000000000000000100111010000110(2進数)

0000000000000000⊕0100111010000110

=0100111010000110 ...②

さらに、TIDとPIDから求めた値でXORをとります。

①⊕②

=0000001110100111(2進数)

=935(10進数)

計算結果の16bitの数が、第5世代までは8未満(⇒上位13bitが0)、第6世代以降では16未満(⇒上位12bitが0)になると、そのポケモンは色違いであるとされます。今回は935なのでどちらであっても色違いにはなりません。

 

 

 これらの計算を色違い判定の都度計算し直すのは面倒です。そのため、わかりやすく表現するのにSVと呼ばれる値が利用されます。

ビット毎のXORが0になることは、その桁の値が一致しているということのため、TID、PIDから得られる値の上位12(あるいは13)bitが一致すれば色違いになる、と言い換えられます。そこで、IDから計算できる16bitの値からそれらを取り出し、10進数に直したものがSVと呼ばれるものになります。

 今回のTIDから求まった①でいえば

0100110100100001

⇒010011010010

=1234(10進数)

となり、SVは1234です。(12bitを取り出したので、第6世代以降の場合。)

 

 SVもIDのように、トレーナーのものをTSV、ポケモンのものをPSVと言うことが多いです。TSVと一致するPSVを持ったポケモンが出現や孵化することで、色違いが入手できます。

 

なお、剣盾で★ではなく◇のエフェクトが出るには、先ほどのTID⊕PIDが完全に0となる必要があります。この場合SVには使わなかった下位4(または3)bitを16進数にしたものがRVと呼ばれ、SVと共にRVも一致することで◇であるという扱い方をするようです。

 

 計算自体は大したことはないですが、わかりやすい形にするのは大事ですね。

ID,SID

 ID(表ID)、SID(裏ID)(※この記事ではそれぞれこうおきますが、表記揺れがあります。)といったとき、どのような表記を示すでしょうか。第7世代ではトレーナーパスやポケモンの親情報にあるIDが6桁となり、第6世代までのものとは少し異なります。

 初代からXY、ORASまでは、表示されているIDは0~65535までだったのに対し、SMからは0~999999までと、数字の幅が大きく広がっています。SM発売当初にTwitterでは「ID厳選」がトレンド入りするなど、桁が増えたことによる厳選難度や、語呂合わせの自由度の増加の影響は大きかったようです。

 一方で、内部的なIDは変化しておらず、32bitで記録されています。第7世代とそれ以外の世代のIDの計算について、例を挙げて説明してみようと思います。

 

 さて、次のような32bitの数が内部IDとして記録されていたとします。

  11001001111000011000010011000000

 まず第6世代までは、これを上位16bitと下位16bitに分けます。

  1100100111100001 | 1000010011000000

それぞれ10進数に直すと、上位51681、下位33984となります。このうち下位の33984が表示され、上位の51681は見えません。ここから、下位が表ID、上位が裏IDと呼ばれます。

 対して第7世代は、32bitの数をそのまま10進数に直します。すると3387000000となります。これを1000000で割ったあまりがIDとして表示されるので、この場合は000000になります。(きりがいいのはわざとです。)

 

 3387000000は第6世代までの ID、SIDを使って51681×65536+33984 としても得られるので、世代間で相互に変換することができます。計算式から言い換えれば、第6世代までは第7世代の1000000で割るところを65536で割り、商をSID、余りをIDとしているとも見えます。よって第7世代以降で32bitの内部IDが先ほどの例のものであるときは、IDは000000、SIDは3387である、とすれば表IDという語の意味を崩さないと思います。しかし、過去作との兼ね合いがあるので浸透はしなさそうです。

 

 IDはポケモンもそれぞれ個別に保有しているため、トレーナーのIDと区別するためにTID(トレーナーのID)、PID(ポケモンのID)と呼ばれるときがあります。PIDは性格値とも言われます。TIDという名称を使うと、表IDだけを指すのか32bitすべてを指すのか、5桁なのか6桁なのかが定義されてるわけではないのでなかなか難しいところです。

NN変更について

 ポケモンにはニックネーム(以下NNと略)をつけることができます。NNは"自分だけの"を追加できる要素でもあるので、特に過去世代から運んでくる場合や混合NNなどはよく目にします。

 NN変更するには「おや」である必要があり、各世代によってその判定が異なります。まとめてあるサイトや記事などは探せばあるのですが、第7世代に関するものがない、一部誤りがあるといった点が気になったので改めてまとめておきます。なお、各条件について実機で確認したわけではないのでご了承ください。(一応、他の人がやっている様子、詳しい人から聞くなどで複数の情報源を参照しています。)

NN変更条件
世代 TID SID OT(TN) Gender Ver
3    
4        
5
6  
7

 

 

  Genderはトレーナーの性別です。過去の世代では親情報のOTに性別によって色が付いていたのですが、今は見た目から判断する方法がありません。第5世代のみ一致させる必要があるVerはB、W、B2、W2の区別のことで、同世代の同種のROMで入手したポケモンでないとNN変更ができません。

 乱数調整を用いて他世代でNN変更する目的がほとんどなので、初代と第2世代については情報がありませんでした。持ち込むことができないからですね。第3世代は配信類があるので稀に使う人がいます。

 

 表を見ての通り、第4世代だけ異様に緩く、第5世代だけ厳しくなっています。ID/SIDは第7世代では両方見えなくなりました。OTの全半角が区別されることには注意です。

 

 言うことをきく、経験値ボーナスがかかるといった条件はまた少し違うらしいので、興味があれば調べてみてはどうでしょうか。

 

第7世代のID/SIDはそのうち記事にするかも

第7世代の性別閾値

この記事はPokémon RNG Advent Calendar 2018 3日目の記事です。

adventar.org

 

「需要がある」と言われたので書いてみます。よければ読んでいって下さい。

 

 

ポケモン第7世代のさまざまな乱数調整の手法が確立されて結構経ちます。それらを補助するツールもいくつか作成され、利用している人もそれなりにいると思います。

私は孵化乱数をするとき、PokemonSunMoonRNGToolというツールを使うのですが...

f:id:kykk:20181202224628p:plain

性別比の選択欄は、♂1:♀7とされているシシコに対応していませんでした。そこで、全ての性別比にちゃんと対応できるよう、ツールを少し改良しよう!と思い立ちました。

 

 

性別の決定は、乱数を1つ取得し、それを252で割ったあまりが使われます。ここで得られる数値は0から251までになります。

PokemonSunMoonRNGToolのソースコードを少し覗いてみると、各性別比の閾値は以下のように設定されていて、先ほど求めた値がその数値以上なら♂、未満なら♀が孵化します。

♂:♀=

 1:1 126
 7:1 30
 3:1 63
 1:3 189

この閾値を求めることができれば、♂1:♀7にも同じ処理が適用できるわけです。

本来であれば、このツールで孵化する個体を検索すると

f:id:kykk:20181203000211p:plain

このような結果になります。0消費の個体の性別決定には1消費の行にある乱数列が使われます。ためしに計算してみると、

 0xB0FE335D % 252 = 1

となり、♂1:♀1 であれば 1 < 126 なので♀、といった具合です。

しかし、性別の閾値がわからないので、"乱数列"から計算した値が、シシコを実際に孵化してみて♂になるか♀になるかを確認していきました。

 

 

この作業当時は手作業で計算してそれらしい値であれば孵化する、という面倒なことをしていましたが、少しソースコードを改変すると

f:id:kykk:20181203001738p:plain

"性別"の列に直接数値を表示させることもできますね。(以前こうしてれば楽だったのに...)

 

 

10体ほど異なる性別値で孵化をすることで、シシコの性別を決定する閾値は224だと特定することができました。

 そして、それをツール内で指定できるようにしました。

f:id:kykk:20181203003546p:plain

 (252 - 224) : 224 = 1 : 8 なので、正確な性別比はちょうど♂1:♀8ということになりますが、一般に♂1:♀7で知られていると思うので表示上は♂1:♀7です。

こうして、PokemonSunMoonRNGToolを全ての性別比に対応させることができました。めでたしめでたし。

 

 ___________________________________

実際のソースコードを載せてどこをどうすれば画像のように変わるのか、なども書きたかったのですが、HTMLの書き方がわからずぐちゃぐちゃになってしまうので文章のみとなってしまいました。それらしくなるように練習しないと。