Author Topic: FF7 - World Map Encounters / Mystery Ninja Encounter Mechanics  (Read 8412 times)

NxK

  • *
  • Posts: 130
  • In AI I Trust
    • View Profile
    • YT
Hello,

I am wondering if there is a complete understanding of how world map random encounters are handled, i.e. how it is determined which encounter one will get and when a random battle will start.
In particular, I am interested in learning more about how the Mystery Ninja encounter is worked out. More importantly, I wonder if there is a way to manipulate the probability of getting that encounter (in the Junon Area).

I have done some testing myself and here are my findings:
I used a save file from just after the Mythril Mines in terms of game progression, adjusted my world map camera so that I would be able to walk perfectly horizontally by tapping Left/Right, went back into the Mythril Mines and saved just outside of the Mythril Mines without changing my world map location or camera angle once outside.
Afterwards, I used a save editor to alter my game time, loaded my save file and started running immediately upon loading the file. I only moved horizontally and never stopped moving (I held Left and/or Right all the time) until the first battle would occur. By pressing Left/Right, I always found a pattern to arrive in the forest closest to the exit of the Mythril Mines without getting a random battle beforehand.
Now, for certain game time values, I could get the Mystery Ninja encounter regardless of my exact movement (as long as I only moved horizontally and never stopped running). For instance, 00:00:03 and 259 seconds (but not 515 seconds) allowed me to get a Mystery Ninja encounter all the time.

In case anyone has more information on how world map encounters and the Mystery Ninja encounter in particular are determined, it would be very helpful if you could provide them.

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
I found part of the answer once. However, as per my modus operandi I'm not in front of it right now. I'll try to remember to look through my notes in the morning.

Some of the encounter mechanics ought to be in TFergusson's Enemy Mechanics guide on GFAQs. It has a section on MK, but not detailed info on how to manipulate an encounter, though he does provide chances of such encounter based on where you are. Rocket Town apparently has the highest encounter rate. If you want more detail I might be able to help.

NxK

  • *
  • Posts: 130
  • In AI I Trust
    • View Profile
    • YT
Thank you, any help on this matter is extremely useful.

Yes, the basics, like the respective encounter rates for the different world map regions, are in TF's guides.
However, even though I already know that the Junon Area has a 1/8 Mystery Ninja encounter rate, I feel this number does not mean anything at all.

As you probably know, field encounters are not random in the least (neither the "when" nor the "which" part), making it very easy to manipulate them.
Obviously, it would be great if one were able to manipulate world map encounters as well.

From the tests I have done using the same save file, editing different things via a save game editor, it seems to me that upon loading a world map save file, if one's movement on the world map is the same, only one's game time has an impact on when and which random battles take place. Interestingly, even altering one's world map location (while staying in the same world map region and not changing the types of terrain one will touch when moving) has no impact on when and which random battles occur.

Also, I have looked into trying to manipulate the Mystery Ninja encounter and have found some more game time values which allow me to get one all the time as long as I move only horizontally, never stop running or change the camera angle and end up getting the first encounter in a forest. Strangely enough, as long as I just hold Left, I can even deviate from the "only move horizontally restriction" and still get the Mystery Ninja encounter much more frequently than I should (35 out of 38 times using several different save files) as long as I don't touch the camera angle or stop moving.

Obviously, there must be some kind of "hidden" mechanics to this.
I know this may sound esoteric but, so far, I have found the following second counts that guarantee a Mystery Ninja encounter when abiding by the aforementioned restrictions:
3, 55, 59, 60, 259
I have not tried all the other values in between. More interestingly, I wonder if they loop. I would assume so, and 3 and 259 would suggest a modulo 256 repeating but 515 does not work. All the other modulo tests I have done did not yield any positive result either.

I have actually come up with this preliminary theory:

On field maps, the danger value is increased by a fixed amount per step (depending on the specific encounter rate of the respective field, and running increases it by four times as much as walking does). In order not to get a random battle on a given step, one has to pass a battle check on that step, i.e. one's danger value has to be <= (or is it < (?)) a certain not-so-random value that is taken from a look-up table and is determined by one's step count (mod 65536 (?)).

I assume the world map uses the same system. One's danger value is probably increased by a fixed amount per step (depending on the specific encounter rate of the respective region and terrain type, and one's camera angle might influence the increase as well). In order not to get a random battle on a given step, one probably has to pass a battle check on that step, i.e. one's danger value probably has to be <= / < a certain not-so-random value that is taken from a look-up table and is determined by one's seconds count (maybe mod 65536).
So, stopping one's movement changes what values are used as thresholds in the future battle checks.
Additionally, one never seems to be able to get world map encounters before either a certain amount of time has passed or a certain amount of steps have been taken (I haven't tested yet which of these it is).

On field maps, which encounters one gets is pre-determined as well.

On the world map, which encounter one gets seems to be worked out in a different way.
« Last Edit: 2013-08-26 05:17:36 by NxK »

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Are you playing PC or PSX? That's important to the information I'm about to present.

So there are the obvious checks going on first:

Will there be a battle?
Are you in a forest/jungle?
Have you recruited Yuffie yet?

Those are obvious. What it boils down to now is the encounter seed. This is the check to see if there will be an encounter and what it will be.

There's a large table at 0xE2B550 that will be the deciding factor. This is what I'm going to call the Encounter Seed (or ESeed). This is what is going to determine if the Mystery Ninja (why did I call this MK in that previous post?) is going to be encountered. If this ESeed is less than the encounter rate for the current area (and the terrain is either forest or jungle) then MN will be the formation. FYI - This is actually checked BEFORE the "Have you recruited Yuffie" check. That's not important, however.

The trick with this ESeed is its generation. It is pseudo-random and pretty complicated. It's seeded every time the world loads (from field to world and battle to world at least) and gets repopulated based on itself. The driving seed is:

Code: [Select]
seed = Game Timer
for( i = 0; i <= 16; i++)
{
   for( j = 0; j < 32; j++ )
   {
      seed = seed * 5D588B65h + 1;
      kernel = seed AND 80000000 OR (kernel >> 1);
   }
   ESeed[i] = kernel;
}
ESeed[16] = (ESeed[16] << 23) XOR (ESeed[0] >> 9) XOR ESeed[15]
for( i = 17; i <= 520; i++ )
{
   ESeed[i] = (ESeed[i-17] << 23) XOR (ESeed[i-16] >> 9) XOR ESeed[i-1]
}
for( i = 0; i < 521; i ++
{
   byte_ptr[0xE2B550 + i] = ESeed[i] AND 255;
}

After that is created, it calls the "shuffle" method three times.

Code: [Select]
for( i = 0; i < 32; i++ )
{
   byte_ptr[0xE2B550 + i] = byte_ptr[0xE2B550 + i] XOR byte_ptr[0xE2B550 + 489 + i]
}
for( i = 32; i < 521; i++ )
{
   byte_ptr[0xE2B550 + i] = byte_ptr[0xE2B550 + i] XOR byte_ptr[0xE2B550 + i - 32]
}

A little wild that the first 32 bytes are XORd with the last 32 and then it just goes from there.

Anyway, there is a pointer that the game uses to check against this table at 0xE2A138. Starts at 0 and goes up by one every time the table is checked against. Once it gets to 521 the shuffling method is called again and the pointer is reset to 0. So it is likely just coincidence that 3 and 259 work.

The method that returns the value of this ESeed is 0x753BE8. If the return value of this when called at 0x7677A1 is less than the encounter rate for the area then MN will be encountered if the other checks pass.
This method is called 22 times in 8 methods. It's called about twice a second when still, several times when motion STARTS, and about four or more times a second during motion.
« Last Edit: 2013-08-26 17:32:09 by NFITC1 »

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Talk about over complicating something...  A lot of things in FF seem to over complicate way too much.  Yojimbo's "Zanmato" attack in X.  Cait's reels.

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Most of this is actually formation selection and the MN check is incidental by comparison.
Yes, the seed generation is ridiculous, but at least it's consistent. This is what makes TASes possible. :D

Erzfreund

  • *
  • Posts: 26
    • View Profile
I had the same problem once. Here are my results (even it is ps1 pal German):

http://forums.qhimm.com/index.php?topic=12688.msg179887#msg179887
« Last Edit: 2013-08-26 20:58:07 by Erzfreund »

NxK

  • *
  • Posts: 130
  • In AI I Trust
    • View Profile
    • YT
I am using the PC version by the way.

Hmm, this is much more interesting than I assumed it would turn out to be. Thank you everybody for the extremely useful information you have provided so far.

Still, after reading through this and the topic of Erzfreund, it seems to me that it is close to impossible to manipulate a MN encounter outside of a TAS.

Say I wanted to get a MN encounter in the Junon Area as the first random battle after loading a world map save file there. Is there anything I could do to still increase the odds of that happening, provided I could save anywhere in that area and at several different game times?

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Best you could do is brute force it based on times around your saved game's timer. I'm fairly confident that the generation and shuffling methods I provided are accurate. It's pretty sure it can be predicted via LUA script, but it's more than that because it requires a specific timing.

NxK

  • *
  • Posts: 130
  • In AI I Trust
    • View Profile
    • YT
I think I am going to do just that. Testing 120 values, which is enough for what I need them for, also only takes around 60-80 minutes, so that's perfectly feasible.

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
If you use Otyugh from tools you can speed the game up... that would help I guess? make sure vsync is off in aalis config file though.

NxK

  • *
  • Posts: 130
  • In AI I Trust
    • View Profile
    • YT
Thanks for the suggestion.
But I only really spend time on the world map (I reset as soon as I note the opening camera angle of the first encounter) and isn't the world map framerate hardcoded?

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Yeah, but I've sorted that.  Otyugh allows changing of fps on wm, battle and field.  It also comes with option to increase battles to max and thus bypass the random chance encounter altogether (which you won't need for this test, I gather). Have a look. It will automatically save and inject the information on game load or Otyugh load.  So you won't need to keep messing about.
« Last Edit: 2013-08-27 12:28:59 by DLPB »

NxK

  • *
  • Posts: 130
  • In AI I Trust
    • View Profile
    • YT
Thanks, I will try that.

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Also, you could use the savestate feature.  Save in a field location and continually load the same state and resume.  That might end the need for continually reloading the game.