RBY Research Thread

Status
Not open for further replies.

rory

T^T
is a Site Content Manager Alumnusis a Battle Simulator Moderator Alumnus
In the (hopefully near) future, old generations will need to be implemented in a simulator. At the moment there is not enough information to simulate these generations with 100% accuracy. Formulas exist at upokecenter.com but they really need to be confirmed / corrected before we use them. Below are some formulas that I think we should tackle first. When proving a formula I'd like to see the data and math you used to prove it, so be sure to be organized when collecting data.

When I feel sufficient research has been done I'll be writing an article documenting all the information.

Calculated Stat Formula:
This formula is from the upokecenter GSC page, so we must confirm that it also applies to RBY.
Code:
Stat = int(((A+B)*2+C)*D/100)+E
 
[LIST]
[*]A = Pokémon's Base Stat.
[*]B = Pokémon's Deter Value (from 0 through 15)
[*]C = Number of Stat Points currently earned (from 0 through 63)
[*]D = Pokémon's level.
[*]E = Additive. When calculating a Pokémon's HP, use (Level + 10). For all other stats, use 5.
[/LIST]
Stat Point Formula:
Fixed
Code:
Stat Points = (SQRT(MAX(MIN(StatExp,32505),1)-1)+1)/44
HP DV Formula:
Also from the GSC page. I trust this formula; it doesn't really need to be tested
Code:
HP DV = A + B + C + D
 where:
 
[LIST]
[*]A=0. If Attack DV is odd, A=8.
[*]B=0. If Defense DV is odd, B=4.
[*]C=0. If Speed DV is odd, C=2.
[*]D=0. If Special DV is odd, D=1.
[/LIST]
Damage Formula:
Here is the damage formula from upokecenter. Even on the DP one from upokecenter, they don't include the mods so I'm entirely sure how accurate their damage formulas are. Everything on that page needs to be tested for accuracy.
Code:
int(int(int(2×L ÷ 5+2)×A×P ÷ D)/50)+2
 where:
 
[LIST]
[*]L = Attacker's Level
[*]A = Attacker's current Attack/Special Attack value
[*]P = Attack's base damage
[*]D = Defender's current Defense/Special Defense
[/LIST]
I'll be adding to this post with more things that need to be researched.
 
If required I could send you a copy of Jolt's PKUtility, which should have all the formulas in it somewhere. It's basically just an Excel spreadsheet. IIRC it has tools for the first 3 generations.

It used to be up on Geocities, so I'm probably one of the few that still has it.

He may also have the formulas in his FAQ on gameFAQs, but I've not checked it for years. It's the "Strategy guide" by "R Jones" if I mind right.
 

obi

formerly david stone
is a Site Content Manager Alumnusis a Programmer Alumnusis a Senior Staff Member Alumnusis a Smogon Discord Contributor Alumnusis a Researcher Alumnusis a Top Contributor Alumnusis a Battle Simulator Moderator Alumnus
The problem with relying on past research is that basically one site posts something and then all other sites copy it. We really need to confirm that this data is true independently, or else find somewhere that lists their tests / code from the game.
 

Sarenji

leaf-faced
is a Battle Simulator Admin Alumnusis a Programmer Alumnusis a Forum Moderator Alumnusis a Researcher Alumnusis a Contributor Alumnus
Status
  • How much does Burn reduce attack?
  • How much does paralysis reduce speed?
  • How long does Sleep last?
  • Other than being hit by a Fire-type move, and Haze, are there other ways to unfreeze a Pokemon?

Stats
  • If your stats go over 999, do they stay at 999, or are they looped back to 0?
    • On NetBattle, a Marowak with Thick Club would have its attack loop back to 0 when using Swords Dance unless it had a ~11 Attack DV.
  • Do stat up moves fail when you go past 999?

Status/Stats
RBY has strange relationships between status and Pokemon stats. For example, if you Agility while Thunder Waved, the Speed loss you suffered is negated.
  • In the aforementioned example, is your Speed back to normal, or double the normal?
  • With a stat-lowering status, how is the stat further affected when a Pokemon uses a stat-lowering move on you?
    • Corollary: how is the stat affected when a burned Pokemon uses Swords Dance, once or multiple times, after which the opponent uses Growl?
  • If you have 999 in Speed, then Thunder Waved, can you use Agility again to nullify the Speed loss?

Counter
  • Is Struggle countered?
  • Can confusion damage be countered?

Bide
  • How does Bide work?

I will add further research questions as this goes on.
 
Something that applies to both RBY and GSC. I already mentioned it in the Celebi thread. Correct me if I am wrong.

Because in RBY and GSC you can neither trade Pokemon between different languages, nor battle between different languages, there are in fact different languages' rules. The differences will relate to event moves. An event move that was only available in Japan cannot be in the same battle as one only available in an Anglophone nation, not even if they're on different teams.

I'm not actually sure to what extent this applies, or whether it will actually be bothered with. Strict adherence to cartridge behaviour demands we either include this, or pick a single language to go by. On the other hand splitting the metagame is probably undesirable.
 
In the calculated stat formula what does the "int" stand for, the actual stat of your pokemon?


Edit:

I can confirm that the calculated stats formula does work for R/B/Y:

Data Collected:

Test Pokemon: Level 5 Bulbasaur (Just picked starter)

Hp Stat Calculated 4 times (DVs=0-4) using the formula:


HP Stat= (((45 + 0) x 2 + 0) x 5/100) +15 = ~19 (actual--19.5)

As the DVs increase from 0-4 the results are 19.5 (DV 3), 19.6 (DV 1), 19.7 (DV 2), 19.8 (DV 3), and 19.9 (DV 4).

Compare to the actual stats of a level 5 just captured Bulbasaur with an HP DV of 0-4:


DV HP ATK DEF SPD SpA SpD
0 19 9 9 9 11 11
1 19 10 10 9 11 11
2 19 10 10 9 11 11
3 19 10 10 9 11 11
4 19 10 10 9 11 11
5 20 10 10 10 12 12
6 20 10 10 10 12 12
7 20 10 10 10 12 12
8 20 10 10 10 12 12
9 20 10 10 10 12 12
10 20 10 10 10 12 12
11 20 11 11 10 12 12
12 20 11 11 10 12 12
13 20 11 11 10 12 12
14 20 11 11 10 12 12
15 21 11 11 11 13 13


If you guys want me to test the other stats I can but, it seems that the results will be the same.
 
Oh well that makes more sense now, because I was asking if in pokemon if when you got a decimal answer if it's rounded down or up and received the answer that it's always rounded down, thanks.
 

Hipmonlee

Have a nice day
is a Community Contributoris a Senior Staff Member Alumnusis a Smogon Discord Contributor Alumnusis a Tiering Contributor Alumnusis a Top Contributor Alumnusis a Battle Simulator Moderator Alumnusis a Four-Time Past WCoP Champion
Struggle is countered. It's just a normal normal attack. It also doesnt affect ghosts.

[edit] - honestly some of the stuff you are asking to test here is kinda ridiculous to doubt..

Also the dude you want to talk to is Kamex. He hasnt been around for a few years but he did a lot of rby testing for smogon.. Unfortunately most of his posts are archived now, but this thread has some things in it.

Oh his sig has a link to a .wri file with his rby research in it. I'd use that as your starting point. But he tested this stuff while at smogon. I for one trust it.

Have a nice day.
 
I wonder if you guys could contact people who make tool-assisted speed runs, given their RNG-abuse you could try to get some info of them.

I'm not an expert by any means but thought it could come handy.
 
Low Kick causes flinch, so fix the movedex. Someone's probably figured this out already, but the dex is still wrong. I haven't tested for a percentage yet.
 

Majorbling

(ゞ๑⚈ ˳̫⚈๑)
is a Battle Simulator Moderator Alumnus
I assume the PRNG is fairly limited for the GB, do you think it'd be important to figure out the algorithm?

I think Joim said they'd look into the disassembled code of RBY to find out exactly what's happening.(?)

Edit: apologies for the awful bump, came here from a sticky and didn't check timestamps :(
 
Last edited:
lol this bump

Basically 10 seeds are (pseudo) randomly generated prior to the battle, and then one is picked (in order) whenever a random number is required during the battle (e.g. will move crit, will ice beam freeze, damage random factor, etc). When the 10 seeds are used, apply n = n*5+1 mod 256 to each and repeat. This is just for link battles obviously, where the rng has to be synced in both linked games.
 
The divider register in GB (8-byte) increments at a rate of 2^14 Hz (every ~61 us). The seeds are generated by substracting the divider register to the previous random number generated (that is, the previous seed). I don't know exactly how much time it takes the game to generate a new seed, but most likely, not much longer than (or around) 61 us (that's around 20 machine instructions). So the seeds you are going to get are going to follow a predictable pattern because of this, where seed n+1 is close to seed n - (seed n-1 - seed n). (underflowing/overflowing when 0 or 255 is reached).
 
Nah, I wouldn't bother. It would be pointless without making sure every single rng call occurs exactly like in the games. For example, wrap duration. You're doing it 1/8 chance for each of 2,2,2,3,3,3,4,5. The game generates a random number (next seed for link battles), ands it with 3, then if the result is 0 or 1, generates another random number, ands it with 3 and adds both, and finally adds 1 regardless. Just having to match how this stuff is handled for every single move effect and everything is some insane work.
 
Last edited:
I've made a few observations on the RBY battle PRNG as well for link battles. As Crystal_ pointed out above, in-game, the battle PRNG is equal to the normal PRNG. Its initialization goes as follows (kudos to the pokered disassembly effort):

Code:
   ; hl is $d148 at this point
   ld b, $a
.asm_535d
   call Random
   cp $fd
   jr nc, .asm_535d
   ld [hli], a
   dec b
   jr nz, .asm_535d
Or translated to C:

Code:
uint8_t wd148[10];
uint8_t a, i;
i = 0;
while (i < 10) {
   a = Random();
   if (a >= 0xFD)
     break;
   wd148[i++] = a;
}
This means that, for the first ten random numbers, any numbers greater than 0xFC (252) are impossible, so that the results of the battle RNG will only be 0-252, or chances as n/253.

A turn goes roughly like this (skipping anything that does not involve random numbers; greater detail can be found in Crystal_'s post on the matter):

  1. Compare speed. If speed is equal, check with a random number compared against 0x80 who goes first. This does not happen with priority moves (Quick Attack or Counter), unless both are in the same priority bracket. Then all actions/results for the move of the faster Pokémon are calculated in order, which we'll assume here.
  2. Check for full paralysis or confusion. One random number for each status.
  3. Calculate critical hit chance if the Pokémon uses a damaging attack. One random number.
  4. Calculate damage if the Pokémon uses a damaging attack. This does not randomize the damage yet.
  5. If no damaging attack is used: Skip to move hit check.
  6. Modify calculated damage with type effectiveness.
  7. Modify calculated damage with a random number. This can possibly generate many random numbers, as the number is always regenerated if it's lower than 217.
  8. Hit check: If not using Swift or some other special constellation, calculate one random number and compare it to the (scaled) accuracy. In case of no evasion/accuracy modifiers, that means comparing against the base power of the move. Here is where the 1/256 uncertainty comes in, as the move misses if the random number is greater or equal to the accuracy.
  9. Apply move effect. Depending on the attack, its side effect may consume one or more random numbers (e.g. burn chance from flamethrower or random move selection from Metronome).
  10. Repeat from 2. for the slower Pokémon.

In other words, the accuracy of attacks during the first few turns (or just the first turn for the fastest Pokémon, depending on how badly the damage randomization or move effect goes; Metronome can be a particularly bad offender here) is boosted by a bit. Normally 99.8% accurate moves scale up.

Meaning that a fast turn-one sleeper like Gengar has a boosted Hypnosis accuracy of not 153/256 (59.77%) but instead of 153/253 (60.47%). Even worse if Gengar misses anyway and Exeggutor gets its Sleep Powder in with not 191/256 (74.61%) but instead 191/253 (75.75%). In a metagame where sleep is devastating and effectively a requirement and where the 1/256 uncertainty is a very real fear that can decide a match, this is a definitel, albeit small, improvement for the first turn.

Anything that attempts to inflict damage on Exeggutor on turn 1 is welcome to do so -- it's more likely to hit as long as its faster, after all. In particular, Jynx will appreciate both the boosted Blizzard accuracy (89.45% vs. 90.51%) and the boosted freeze chance (10.16% vs. 10.28%). However, if the damage randomization goes awry, both the accuracy and the freeze chance will already be the usual.

Furthermore, this also means the damage randomization itself cannot generate the maximum factor of 255 while the battle state is still in its first 10 random numbers, so hoping for minmax just became a bit more hopeless.

There is a chance I simplified the battle logic too much, so that the first ten random numbers may never affect anything actually important on the first turn, however.
 
Last edited:

Disaster Area

formerly Piexplode
I'm pretty sure that's important. Even though the boosts are miniscule.. higher chances of sh*t in this game is important!_! where'd u get jynx's previous chance of freezing as 10.16% from? [I'm not super clued up on the mechanics, I thought it was 10% but I didn't know)
also a boost in blizzard's accuracy by 1.3% is pretty huge.. as well as I guess 100% accurate moves are actually accurate 100% of the time in the first turn or few..
 
See FreezeBurnParalyzeEffect in the pokered assembly at src/engine/battle/core.asm.

Code:
   cp a, PARALYZE_SIDE_EFFECT1 + 1 ; 10% status effects are 04, 05, 06 so 07 will set carry for those
   ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance
   jr c, .next1 ; branch ahead if this is a 10% chance effect..
   ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance
   sub a, $1e ; subtract $1E to map to equivalent 10% chance effects
.next1
   push af
   call BattleRandom ; get random 8bit value for probability test
   cp b
   pop bc
   ret nc ; do nothing if random value is >= 1A or 4D [no status applied]
   ld a, b ; what type of effect is this?
   cp a, BURN_SIDE_EFFECT1
   jr z, .burn
   cp a, FREEZE_SIDE_EFFECT
   jr z, .freeze
0x1A (26) gets compared to the result of BattleRandom, which, as said above, is 0-255 normally, and 0-252 during these conditions. I'll recalculate the chances in the post above with n/253, since I forgot to include 0 in the probabilities, actually.
 
Last edited:

froggy25

Bye RNGmon
is a Researcher Alumnus
So, if the calls to the PRNG from 1:535b are used, that would mean that -at least- on the first turn:
More chances of winning speed tie for the host (128/253)
More chances of being fully paralyzed (64/253)
More chances of Critical Hit (at least for the faster Pokémon)
More precise moves (Accuracy/253)
Less chances of hitting itself in confusion (125/253)
Less damage on average (217~252 instead of 217~255, if one of the remaining numbers from the first batch is ≥ 217)

Is it correct ?

Also, are the 9 first PRNG calls at Link Battle initialization the only ones to use the value at hFFD3? I found this on the disassembly, this does n×5+1 to the pseudo-random values at wD148:
https://github.com/iimarckus/pokered/blob/master/engine/battle/core.asm#L6728
Edit: confirmed, when we miss a 255/256 move we know what will be the 9th / 18th / 27th... pseudo-random numbers after the miss: 0xFC, 0xED, 0xA2...
It's probably not usable though as any damage roll can use several numbers.
 
Last edited:
Status
Not open for further replies.

Users Who Are Viewing This Thread (Users: 1, Guests: 0)

Top