Random numbers in FF12

Abstract

I've done some research on how FF12 handles random numbers internally, and I'll tell you what I found.

Contents

Abstract
Notations
Disclaimer
Introduction
Overview on the generator A
Common usage patterns of the sequence A
Actions depending on the sequence A
Actions that do not consume the sequence A
Application examples
Unknown things

Notations

In this document I use the following notations.

Disclaimer

This documents describes how to observe patterns of, and control, random numbers in FF12. These kinds of play is probably not what the authors intend, and may destroy good balance of game difficulty if you use it carelessly. I will not be responsible if your fun of playing FF12 is damaged by reading this document.

Overall, the contents of this document is not tested enough. So note that it may contain wrong information.

Introduction

In general, when a computer game needs random numbers to process something, it instead uses algorithmically calculated values. Such values are called pseudorandom numbers. Pseudorandom numbers are not true random numbers because they are produced by an algorithm. However, they are designed to have less recognizable patterns as possible, so that it is ok to treat them as random in practice. Google it for more details.

FF12 has at least 3 pseudorandom number generators, each working independently. One of these is particularly important, because it dominates many player-visible random selections, such as damage calculations, hit tests on attack, and contents of chests. Lets call it the generator A. The rest of this document is almost solely about the generator A.

Overview on the generator A

The generator A is capable of producing an (almost) random integer between 0 and 232-1, one at a time. Each time it generates an integer, it internal state changes. However, immediately after turning on the PS2, or after a hardware reset, its internal state is fixed to one particular value. Because of this, A produces the same sequence of numbers each time. This sequence can be concretely calculated; the first term is 1820836235, and the second is 1372235862. That means, when it produces a number for the first time after the PS2 powers on, it will always generate 1820836235.

Terefore, to predict the future outputs of `A', it is enough to know how many numbers it has produced so far. In other words, `A' behaves as if it has a fixed random number table (of infinite length) internally, and sequentially outputs the contents of the table, one by one. Let me call it the sequence A.

Next, assume that `A' produced n random numbers so far. Then, next `A' will produce the (n+1)th number in the sequence. I will describe this situation as "we are at the RNG position n (with respect to the generator A)." Also, if doing something causes the RNG position to move ahead by k, I will say "the process consumes k random numbers."

The rest of the document does not require you to understand the details of how the sequence A is calculated. But for those interested, it uses Mersenne Twister(MT19937). Note that its initialization routine is not the latest 2002 one, but the older 1998 version. The seed is 4537 (not 4357!)

Common usage patterns of the sequence A

The sequence A consists of numbers between 0 and 232-1, but many tasks need smaller values. For example, the game may need to randomly choose one from n candidates. FF12 usually do this using a residue. That is, it generates one random number, divide it by n, and take the remainder. Then it will get a number between 0 and n-1, with almost uniform randomness.

As an application of this scheme, "do something at k% probability" tasks are similarly handled. To do that, the game first generates a random number, calls it v, and compares v % 100 with k. The condition v % 100 < k holds approximately k% of the time, because the value of v % 100 distributs almost uniformly between 0 and 99. This scheme is used extensively in the game, so let me name it "ptest" (against k).

ptest(against k):
  Take one random number from the series A, and call it v.
  The test succeeds if v % 10 < k. Otherwise, it fails.

Actions depending on the sequence A

The below describes how the series A is used in the process of performing actions, such as attacking or casting a Magick. When I gathered these infrmation, I let a character perform actions against a member of his own party, with no surrounding enemies, and with no irrelevant status effects. So the results may not be directly applicable to real combats.

Guns

When a character attacks with a gun and it's going to hit, 8 random numers are consumed. They consists of:

Calculating the knock back chance(2)

Generate two random numbers, and call them v0 and v1. The knock back chance is defained as follows.

knock back chance = weapon's knock back value (guns:10) + v0 % (attacker's level) - v1 % (target's level)
(If this formula yields a negative number, the chance is 0)

This is subtly different from the formula described in Battle Ultimania, and I think this is more accurate.

Knock back test(1)

Perform ptest against the calculated knock back chance. When attacking oneself, knock back never happens, but this test is still performed.

Non-miss test(1)

Perform ptest against the non-miss chance. Usually the non-miss chance is 100 and the test succeeds unconditionally, but a random number is still consumed. If this test fails, skip the following tests. In that case, the overall consumption becomes 4.

Critical hit test(1)

Perform ptest against the critical hit chance (which is 5 for guns).

Damage calculation(2)

First I define a procedure named rand98, which takes an integer base value, and yields a random value in the range [base, (9/8)base).

rand98(base):
  If base = 0, return 0 without consuming any random numbers.
  Otherwise, generate one random number and call it v. Define the result as follows:
  result = base + (v % ⌊base * 12.5⌋) / 100

Essentially, this procedure randomly chooses one number, from the set of multiples of 0.01 within the range.

Using rand98, a damage by a gun is calculated as follows:

Perform rand98(base = weapon's Attack), let r0 be the result.
Perform rand98(base = weapon's Attack) again, let r1 be the result.
The damage is calculated:
damage = ⌊r0 * r1 * ratio⌋

where "ratio" is the product of all the modifiers applied, such as elemental weakness, weather conditions and augments like Adrenaline.

Added-effect test

Perform ptest against the added-effect trigger chance. A random number is consumed even when using bullets without an added effect.

If you direct a character to attack with a gun, and then cancel it after he/she begins the motion of attacking, 4 random numbers will be consumed.

Unarmed

Attacking unarmed consumes 10 random numbers in the most typical case. When an n-hit combo happens and all of them hit successfully, (9n + 12) random numbers will be consumed.

The 10 consumptions can be divided into two groups. The first 5 are consumed only once even if a combo happens. The other 5 are consumed once per combo. The first 5 consist of:

Calculating the knock back chance(2)
Knock back test(1)

These two are same as with guns.

Unknown(1)

Consume one random number, but its usage is unknown.

Combo test(1)

Perform ptest against the combo chance. The combo chance is defined by the following formula.

Combo-chance = ⌊Weapon's combo * 0.7⌋ (Without Genji Gloves)
Combo-chance = ⌊Weapon's combo * 1.8⌋ (With Genji Gloves)

If this test succeeds, perform 11 additional ptests against M. Let s be the number of successes among them. The resulting combo will be of (s+2) hits. As an exception, when s = 11, there will be only 12 hits. M is defined as:

M = 8 (⌊maxHP/4⌋ <= HP)
M = 16 (⌊maxHP/8⌋ <= HP < ⌊maxHP/4⌋)
M = 32 (⌊maxHP/16⌋ <= HP < ⌊maxHP/8⌋)
M = 64 (HP < ⌊maxHP/16⌋)

In case of an n hit combo, repeat the per-hit tests (described below) n times. Additionally, before each hit except the first one, consume 4 random numbers, whose use is not known. This means there will be 4(n-1) unknown consumptions in total.

The below are the remaining 5 tests, executed once per hit.

Blocking-by-shield test(1)

Perform ptest against the shield's Evasion. If this test succeeds, skip the rest.

Blocking-by-weapon test(1)

Perform ptest against the weapon's Evasion. If this test succeeds, skip the rest.

Parry test(1)

Perform ptest against the parry chance. If this test succeeds, skip the rest.

Non-miss test(1)

Perform ptest against the non-miss chance. If this test fails, skip the rest.

Damage calculation(1)

The damage is calculated as follows:

Perform rand98(base = weapon's Attack), and let v be the result.
Define the damage as:
damage = ⌊(v - Defence) * ratio⌋

where ratio means the basic ratio (Strength * (Strength + Level) / 256) multiplied by various modifiers.

Damage calculation when attacking with axes, hammers, or hand-bombs

First, I define a procedure named rand11, which takes a positive real number x, and returns a random number in the range [0, x).

rand11(x):
  If x < 0.01, the result is 0, stop without consuming any random number.
  Otherwise, generate one random number, call it v, and define the result as follows:
  result = (v % ⌊x * 100⌋) / 100

Using this definition, damages by these weapons is calculated with the following process.

Perform rand98(with base = Attack), let a be the result.
let c = (a - target's Defence). If c < 0, the damage is 0, stop without consuming random numbers any further.
Otherwise perform rand11(with x = ratio), let r be the result. The damage is given as follows:
damage = ⌊c * r⌋

where "ratio" means the basic ratio (Strength * (Vitality + Level) / 128) multiplied by various modifiers.

Cure and Curaga

They consume just one random number for healing calculation. The formula is same as for the unarmed damage, except that Defence is considered to be 0 and the basic ratio is defined by (Magic Power * (Magic Power + Level) / 256 + 1).

Potion, Hi-Potion, X-Potion, Ether and Hi-Ether

They consume exactly one random number. Its usage is not known.

Opening a chest

If you open a chest, the game first performs a Gil test against a chest-dependent Gil chance. Then it continues as follows:

When the Gil test succeeds:
If that chest is assigned a fixed amount of money, you receive it without consuming any random numbers. Otherwise, the game generates a random number v, and give you (1 + v % max-amount) Gils.
When the Gil test fails:
The game performs a non-rare-item test. It is against 90 with Diamond Armlet, and 50 otherwise.

Loading data

By definition, the RNG position right after powering on the PS2 is always 0. However, before you get control of your characters, hundreds of random numbers are consumed during data load. The number of this consumption is not always same, even if you load the same data. I tested using a data at "Cerobi Steppe/Journey's Rest", and the initial RNG position was about 570 +/- 10. Although unconfirmed, this may depend on the model number of your PS2. I used SCPH-70000 for the test.

Actions that do not consume the sequence A

For those interested, I write down what I know about the two other pseudo random number generators found in the game. Both of them are linear congruential generators. Let me formalize the recurrence equations of linear congruential generators as "xn = (xn-1 * a + b) % m". Then one of the generators is specified by the equation (a, b, m) = (6364136223846793005, 1, 264). It outputs ⌊xn / 232⌋ % 231 for each term xn. Its initial value is probably 1. The other is specified by (a, b, m) = (75, 0, 231-1), and it outputs terms without modification. Its initial value is probably 305420679.

Application examples

Identifying RNG position

If you can identify the current RNG position during a play, you will be able to control the game's subsequent random choices to some degree, by adjusting the RNG position adequately. For example, to move the position ahead by 100, shoot yourself 12 times with a gun (when doing this, elemental absorption may keep you alive), then cast Cure 4 times.

An easy way to deduce the current position is to observe damage or healing values. The sequence A can be completely known by calculation, so you can calculate the amount of healing by Curaga for each position in the sequence and put them in a table, for example. Of cource it is not possible to enumerate "all" the RNG positions, but it is usually sufficient to cover the positions below 100,000.

This process is conceptually simple, but doing it by hand is not realistic because it requires a vast amount of calculation. I included a simple JavaScript tool to help this.

Mechanism behind the 5 hit method

The 5 hit method is a reproducible way to obtain rare items from chests, originally found for the IZJS version. The steps are roughly as follows:

  1. Save near the chest of interest. Reset by hardware.
  2. Load, and repeat zoning until the chest spawns. If it does not spawn within some repetitions (for example 10), then restart from the beginning.
  3. Hit yourself repeatedly, with bare hand. Make sure that attacks are never blocked, by either removing a shield or wearing Cameo Belt.
  4. When a 5 hit combo happens, open the chest, with Diamond Armlet.
  5. As an additional condition, you may not be attacked by enemies until you open the chest.

This essence of this method is that at the point of opening a chest, the generator A is guranteed to be at the position 1445. The sequence A around 1445 looks like the following.

1444: 2510889783
1445: 1861786791
1446: 1379767799
1447:   80686868

The last two digits of the values at 1445 and 1446 are 91 and 99 respectively, both of which are large. This means that a relatively easy ptest may fail there. Indeed, if you open a chest at the position 1445, both the gil-test and the non-rare test surely fail, because these tests are against at most 90. Consequently you will get a rare item. For your information, in the IZJS version the non-rare test may be against 95, but it still fails because it's compared with 99.

The 5 hit combo itself happens if an unarmed character attacks at the RNG position 1388.

1387:  382760416
1388: 2267807233 Attack here; Knock back chance calculation 1.
1389: 1886692943 Knock back chance calculation 2.
1390: 2131861130 Knock back test
1391: 2952945076 (unknown)
1392: 2341692401 Combo test(against 3) -> Success
1393: 3404601602 Increment-the-number-of-hits test(against 8) -> Success
1394: 2203834536 Increment-the-number-of-hits test(against 8) -> Failure
1395:  961042754 Increment-the-number-of-hits test(against 8) -> Failure
1396: 2005317402 Increment-the-number-of-hits test(against 8) -> Success
1397: 2981387111 Increment-the-number-of-hits test(against 8) -> Failure
1398: 2833431843 Increment-the-number-of-hits test(against 8) -> Failure
1399: 3060953428 Increment-the-number-of-hits test(against 8) -> Failure
1400: 3953158966 Increment-the-number-of-hits test(against 8) -> Failure
1401: 3263761202 Increment-the-number-of-hits test(against 8) -> Success
1402:  161153939 Increment-the-number-of-hits test(against 8) -> Failure
1403: 1977869617 Increment-the-number-of-hits test(against 8) -> Failure; 5 hit Combo
1404: 3808337799 Block-by-shield test(against 0) -> Failure
1405: 3799551709 ...(and so on)...

Since a 5 hit combo consumes 57 random numbers, the position will be 1445 after the combo.

The RNG position moves ahead by 10 each time a character hits herself, if the attack does not combo. Basically this means that in order to reach the position 1388, you must start hitting at a position whose last digit is 8. However, there are two other ways to reach 1388. First, a 4 hit combo happens at 1070, and the position after that combo is 1118, from which you can reach 1388. Similarly, the position 751 causes a 3 hit combo, resulting in the position 790, which leads to 1070. Thanks to these combos, you have a chance to reach 1388 if you start hitting at a position whose last digit is 0, 1 or 8.

As shown above, the RNG position 1388 is relatively easy to reach by repeating hits, causes a infrequent 5 hit combo, and leads to the very good position for opening chests. It is a rare position with this many good properties, and the 5 hit method cleverly uses its speciel characteristic.

Chest spawning laws at "Cerobi Steppe/Crossfield"

In this section I will demonstrate how to investigate individual game processes that involves randomness. As an example, I'll show how I found out the rules that determine whether chests at "Cerobi Steppe/Crossfield" spawn.

According to Scenario Ultimania, p.122, whether a chest spawns or not is determined when you visit the zone. So, as a first step I tried to find out how many random numbers are consumed when entering Crossfield.

First, after a reset, I loaded a data at Journey's Rest, and identified the RNG position using gun damages. Then I entered Crossfield, identified the position again, and calculated the position at the point immedeately after entering the zone. Taking the difference, I saw that 16 random numbers are consumed when I entered Crossfield.

Then I returned to Journey's Rest, reentered Crossfield, and measured the consumption again. This time it consumed only 6 random numbers. This can be understood if we assume that spawning tests of the chests are omitted for this time, because the respawn condition is not met. There are 10 chest positions in Crossfield according to Ultimania, so it makes sense to think that 10 of the first 16 consumptions were for spawning tests.

Now, which of the 16 consumed random numbers were used for spawning tests? According to Ultimania, all the 10 chest positions have spawn rate of 50%. For now let's assume that these spawning tests are actually ptests against 50. The list below shows for each of the 16 consumed numbers, whether ptest against 50 at the position would have succeeded.

n y n n n n n y n y y n n y y n (y means success, n failure)

Next I walked around in Crossfield to check whether individual chests had spawned. There were 4 chests spawned. Using the numbers given by Ultimania, they were 55, 57, 59 and 60.

Let's assume that a contiguous range of the 16 consumption are used for the spawn tests. That is, there should never be a unrelated consumption between two spawn tests. Among the contiguous sublists of the success list above, there are just 2 sublists which have length 10 and contain 4 successes.

n[y n n n n n y n y y]n n y y n and
n y n n[n n n y n y y n n y]y n

If the assumptions we have made so far are valid, one of the two sublist represents the range of the RNG table that was used for spawning tests.

It seems that I did't have any more things to say from the data currently available, so I reset the game and collected similar data for another case. I repeated this until I had data for 5 cases.

0: n y n n n n n y n y y n n y y n    Appeared: 55, 57, 59, 60 (This is the data discussed above)
1: n y n y n y n y n n n y n y y n y  Appeared: 52, 53, 58, 59
2: y n y n y n n n y n y y n y n n y  Appeared: 51, 55, 57, 59, 60
3: n y n n y y n n y n y n y n y n n  Appeared: 51, 52, 57, 60
4: y n y y n n n n y y n y n n y y    Appeared: 51, 53, 56, 60

First, unexpectedly, there were cases where it consumed 17 random numbers (rather than 16) when entering Crossfield. Let's assume there was an extra consumption before or after the chest spawn tests.

I found that under above consumptions, there is only one usage pattern of random numbers. [I used computer to check this, but human calculation could be possible.] It is as follows:

  1. Consume 1 or 2 random numbers (The usage is not known. It is also not known when it consumes 2.
  2. Consume a number for each of spawning tests for 10 chest positions. They are tested in order: 55, 53, 51, 52, 54, 58, 57, 56, 60, 59.
  3. Consume 5 random numbers. According to rémy lachaud, these are used to choose types for traps in the map, one for each.

In total, it consumes 16 or 17 random numbers.

Now we have an idea on how chests in Crossfield spawns. Next we want to test the hypothesis. I restarted the game and tried again. The result was that I was able to successfully predict which chest spawns and which not, for some chest positions. (Yes, I sould have done more thorough test, but I was bored at the work). As a final proof of effectivity, I ensured that I can actually get Ribbon from a chest, by adjusting RNG position to make the chest spawn.

The below is a map of Crossfield, with numbers indicating the order of spawning tests of corresponding chest positions.

A map of Crossfield; test order, from west to east, is: 9, 10, 6, 7, 8, 1, 5, 2, 4, 3

Things that is not known

Currently there are more unknown things than known. They include: