Yep, that's right. It's the random encounter problem again.
The issue at hand is how to best avoid random encounters:
1. Menu Glitch (83 frames): Opening the menu at the same time as a battle. Does not reset the danger value.
2. Accept a Battle (685 frames): Accept a battle and escape. Resets the danger value.
3. Stutter (x frames): Amazing, almost free. Can only avoid 'close encounters'. Does not reset the danger value
A combination of these will be used.
Here's an example segment:
We want to find the most efficient path through here; using the 3 options given above.
If you touch a blue line you get a battle. The red dots show the character's steps. In this case, the default route shown here is simply running through the segment and accepting every battle.
Stuttering has the effect of making the danger value increase by 1/4 compared to that of running. Thus, it makes the red line less steep, it flattens the line out more.
As you can see, using the menu glitch too many times will put you further into the blue-line jungle.
I've reverse engineered the important random encounter routines from the disassembly:
The script I wrote generates the graph above showing the random encounter pattern of any segment. Simply modify the global values at the top of the script for where you are in the game (leave at default to generate the above graph).
My programming skills are still new (aka poor); only 4 days learning Python :P So, I have no clue how I can optimize this whole thing (or even 1 segment at a time).
You can see the battle routine in the script.
Here's the Python script:
Language: Python
## Random Encalculator v0.2 by antd ##
import numpy as np
import pylab as pl
# random number table:
rnlist = [0xB1, 0xCA, 0xEE, 0x6C, 0x5A, 0x71, 0x2E, 0x55, 0xD6, 0x00, 0xCC, 0x99, 0x90, 0x6B, 0x7D, 0xEB, 0x4F, 0xA0, 0x07, 0xAC, 0xDF, 0x8A, 0x56, 0x9E, 0xF1, 0x9A, 0x63, 0x75, 0x11, 0x91, 0xA3, 0xB8, 0x94, 0x73, 0xF7, 0x54, 0xD9, 0x6E, 0x72, 0xC0, 0xF4, 0x80, 0xDE, 0xB9, 0xBB, 0x8D, 0x66, 0x26, 0xD0, 0x36, 0xE1, 0xE9, 0x70, 0xDC, 0xCD, 0x2F, 0x4A, 0x67, 0x5D, 0xD2, 0x60, 0xB5, 0x9D, 0x7F, 0x45, 0x37, 0x50, 0x44, 0x78, 0x04, 0x19, 0x2C, 0xEF, 0xFD, 0x64, 0x81, 0x03, 0xDA, 0x95, 0x4C, 0x7A, 0x0B, 0xAD, 0x1F, 0xBA, 0xDD, 0x3E, 0xF9, 0xD7, 0x1A, 0x29, 0xF8, 0x18, 0xB3, 0x20, 0xF6, 0xD1, 0x5E, 0x34, 0x92, 0x7B, 0x24, 0x43, 0x88, 0x97, 0xD4, 0x0F, 0x35, 0xAA, 0x83, 0x68, 0x27, 0xA8, 0xD5, 0xBE, 0xFA, 0x14, 0x31, 0xAF, 0x10, 0x0D, 0xD8, 0x6A, 0xCE, 0x23, 0x61, 0xF3, 0x3D, 0xA4, 0x08, 0x33, 0xE3, 0xA9, 0x38, 0xE6, 0x93, 0x1D, 0x1C, 0xF0, 0x0E, 0x87, 0x59, 0x65, 0x82, 0xBC, 0xFF, 0xFE, 0x7E, 0x8F, 0xC1, 0x1E, 0xF5, 0xCB, 0x49, 0x02, 0x32, 0x09, 0xC4, 0x8E, 0xC6, 0x2B, 0x40, 0xA7, 0x17, 0x76, 0x3B, 0x16, 0x2A, 0xC8, 0xFB, 0xB2, 0x58, 0xA5, 0x15, 0xAE, 0x25, 0xCF, 0x46, 0xC7, 0x48, 0xB4, 0x0A, 0x3F, 0xC9, 0x06, 0x85, 0x51, 0x89, 0x62, 0x4D, 0x12, 0x8C, 0xEA, 0xA2, 0x98, 0x4B, 0x79, 0x6F, 0x5C, 0x47, 0x30, 0x1B, 0xE7, 0xC5, 0x22, 0x9C, 0xE8, 0x96, 0x3A, 0xE4, 0x7C, 0xE0, 0x69, 0xA1, 0xB7, 0x05, 0x39, 0x74, 0x01, 0x9F, 0xBD, 0xC3, 0x84, 0xFC, 0x77, 0x86, 0x13, 0x4E, 0xBF, 0xF2, 0x53, 0x5B, 0xED, 0x21, 0x8B, 0x6D, 0xC2, 0x41, 0xB6, 0xDB, 0x3C, 0xD3, 0x28, 0xEC, 0x2D, 0xE2, 0x9B, 0xA6, 0x42, 0x52, 0x57, 0x5F, 0xE5, 0xAB, 0xB0, 0x0C]
### change some of these:
stepid = 24 # set current stepid in field
bloop = 13 # set current battle loop in field
danger = 0 # set current danger value in field
distance = 128 # set field distance in steps
run = 113 # set danger increment for running
walk = run/4 # danger increment for walking
runwalk = run # set whether to 'run' or 'walk' through the field
dlimit = 0
total_steps = 0
## graph stuff:
x1 = []
y1 = []
x2 = []
y2 = []
x3 = []
y3 = []
def ShowMyGraph():
plot1, = pl.plot(x1,y1,'r.')
plot2, = pl.plot(x2,y2,'b_')
plot3, = pl.plot(x3,y3,'-')
pl.title('Random Encounter Pattern')
pl.xlabel('Step')
pl.ylabel('Danger Value')
pl.xlim(0.0,150.0) # change x-axis range if needed
pl.ylim(0.0,10000) # change y-axis range if needed
pl.legend([plot1,plot2], ('Route', 'Battles'), 'best', numpoints=1)
#pl.xticks(arange(201, step=50)) # change amount of x-axis numbers
pl.show()
def PlotSteps():
x1.append(total_steps)
y1.append(danger)
x2.append(total_steps)
y2.append(dlimit)
x3.append(total_steps)
y3.append(dlimit)
### random encounter stuff:
# increment StepID and grab rnd number:
def GoStepID():
global stepid, bloop, rnd
stepid = (stepid + 1) & 0xFF # increment stepid + reset if > 255
if stepid == 0: # increment battle loop by 13 if 0
bloop = (bloop + 13) & 0xFF
rnd = (rnlist[stepid] - bloop) & 0xFF # grab a rnd byte from rnlist
# call this function to take *1* step:
def BattleCheck():
global dinc, danger, rnd, dlimit, walk, total_steps
if runwalk == walk: # let's see if we are running or walking
dinc = walk # set the danger increment accordingly
else:
dinc = run
danger = (danger + dinc) & 0xFFFF # increment danger value + reset if > 65535
GoStepID() # this is for preemptive rnd
GoStepID() # this is for battle; +2 stepID = 1 step
dlimit = ((rnd +1) *256) & 0xFFFF # calc danger limit for battle
total_steps += 1 # calculate total steps (for graph only)
PlotSteps() # just plots the graph
if danger <= dlimit: # if danger is over limit it's battle time
print "Next step is SAFE!\n"
print "rnd: %d danger: %d, dlimit %d, stepid : %d total: %d\n" % (rnd, danger, dlimit, stepid, total_steps)
else:
print "Random Encounter on next stepid: %d!\n" % (stepid)
print "rnd: %d danger: %d, dlimit %d, stepid : %d total: %d\n" % (rnd, danger, dlimit, stepid, total_steps)
danger = 0 # danger is reset in battle
while distance > 0: # travel through the whole field
BattleCheck()
distance = distance - 1
ShowMyGraph()
Please install Python (2.7.x) if you would like to run the script:
https://code.google.com/p/winpython/downloads/list
Any help or advice on a possible algorithm would be appreciated :D