I've done some research on how FF12 handles random numbers internally, and I'll tell you what I found.
In this document I use the following notations.
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.
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.
The generator A is capable of producing an (almost) random integer between 0 and 2^{32}-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!)
The sequence A consists of numbers between 0 and 2^{32}-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.
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.
When a character attacks with a gun and it's going to hit, 8 random numers are consumed. They consists of:
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.
Perform ptest against the calculated knock back chance. When attacking oneself, knock back never happens, but this test is still performed.
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.
Perform ptest against the critical hit chance (which is 5 for guns).
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.
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.
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:
These two are same as with guns.
Consume one random number, but its usage is unknown.
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.
Perform ptest against the shield's Evasion. If this test succeeds, skip the rest.
Perform ptest against the weapon's Evasion. If this test succeeds, skip the rest.
Perform ptest against the parry chance. If this test succeeds, skip the rest.
Perform ptest against the non-miss chance. If this test fails, skip the rest.
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.
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.
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).
They consume exactly one random number. Its usage is not known.
If you open a chest, the game first performs a Gil test against a chest-dependent Gil chance. Then it continues as follows:
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.
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 "x_{n} = (x_{n-1} * a + b) % m". Then one of the generators is specified by the equation (a, b, m) = (6364136223846793005, 1, 2^{64}). It outputs ⌊x_{n} / 2^{32}⌋ % 2^{31} for each term x_{n}. Its initial value is probably 1. The other is specified by (a, b, m) = (7^{5}, 0, 2^{31}-1), and it outputs terms without modification. Its initial value is probably 305420679.
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.
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:
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.
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:
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.
Currently there are more unknown things than known. They include: