Thinking of seriously rerouting GS2 any% next week and there's two things that will make that a lot easier.
1) Randomly Generated Stats on File Generation
When creating a new file, Felix's party's stats are generated upon loading the rename character box. Isaac's party's stats and djinn are generated upon confirming that no PW is required. It would be convenient to know how the game uses the GRN seed to do this, so that I can use external scripts to find the ideal stats/djinn combination.
For reference, me and Zetonegi both have 'good' setups as is. Mine is easier but generates worse stats for Jenna which ends up making a difference at Serpent. Zetonegi's is pretty good but takes a long time to set up. Finding a happy intermediate or a strict improvement would be desirable.
2) Attacks First/Caught By Surprise
Zetonegi wrote a script to dump the first 2000 or so BRN seeds that give attacks first or caught by surprise. I'd prefer to just read the BRN directly and determine if the next fight has either of these properties.
By cross checking his list of numbers, it looks like it is necessary (but not sufficient) for the last three hex digits of the BRN to be less than or equal to 0x0FF. While caught by surprise must be less than or equal to 0x00FF. But beyond this check I haven't been able to work out how to predict attacks first or caught by surprise.
I guess we can start with #2, since I kinda have it already...
Quote from: From my GS2 Documentation08119AD0 = if [0200048B]=00, it's checked randomly (below); if 06, your party is caught by surprise:
1/16 chance for your party to attack first.
1/32 chance for your party to be caught by surprise.
So that's generate number. (16-bit) & 0xF ; If that's 0, you attack first... if not.... then generate another number (16-bit) & 0x1F, if that's 0, your party is caught by surprise. (This second number is not generated if you are attacking first; and these checks are not made if [0200048B] is not 00.)
Pseudo-code: (To show similar formatting of GS's code.)
if ([0200048B] == 00)
{
if ((brn16() & 0xF) == 0)
{
You attack first.
}
else if ((brn16() & 0x1F) == 0)
{
You are caught by surprise.
}
}
else if ([0200048B] == 06)
{
You are caught by surprise.
}
And as always, where I say 16-bit just means the bytes on the left/right of the 32-bit are always ignored/removed for the actual calculations. (Except for calculating the seed, but anyway.)
@0200048B = This is also in my documentation:
Quote0200048B = Battle: Flee / Battle Type
00 = Normal
- 1/16 chance for your party to attack first.
- 1/32 chance for your party to be caught by surprise.
01 = ?
02 = No Flee option.
03/04 = "This is no time to be running away!"
06 = Your party is caught by surprise.
So it just goes to show you don't get the chance to attack first with bosses and stuff...
--
And #1... Hm...
Going to review code... some of which was doc'd in the image in this post:
http://forum.goldensunhacking.net/index.php?topic=2214.msg39054#msg39054(Except that I may have to follow the function calls.)
But otherwise will have to get back to you on that.
It does looks like Isaac's party stats are generated with Felix's as well. (At first?) ... Hm.... So I guess it's generated twice? (Probably the same calculations as normal when you level up? Will need to check.) (EDIT:
EDIT: I think I know now... ALL PCs have their stats generated at once.... but djinn have stats, so Party 1's team is updated again only by the djinn stats (And not PC levels)?
Rename Felix:
For each PC (all 8), level to (whatever level)
Rename Isaac:
For each Party 1 PC.... Hmm....
level up function... (psuedo)
level += 1
if (level == 1)
{
stats are the first values of stat growths....
}
level / 20 (Determines which value of stat growth to get)
current stat += ((upper stat growth - lower stat growth) + ((grn16 * 20) >> 16)) / 20
Note: (grn16 * 20) >> 16 basically means a random number from 0-19.
Note 2: / is supose to be integral division. (Remove decimal places.)
----
for each pc
{
for each level
{
for each stat
{
raise stat
}
}
}
080AF79C = PC Starting Data
PC * 0xB4
... and for the growths ( To calculate the address location of them.)
+0x50
+0x5C
+0x68
+0x74
+0x80
+0x8C
... and then for which in each..
+(level / 20) should get you the idea.
Alternately, you can make a table for them in the script.
(Would like to test to see if I missed something, though.)
How djinn are picked...
(Flint and Fizz are 100% obtained prior to checks.)
element = (grn16() * 4) >> 16
djinni (of element) = (grn16() * 7) >> 16
If we already have this djinni, do the above two again until we don't.
If the minimum and maximum between elements is greater than 1 (if this djinni were added), generate a new djinni.... (Go back up.)
(grn16() * 100) >> 16 ; Basically check against percents to add a djinni (Table at 080B1290) , If failed, go back up.)
Psuedo-code: (May not be exact, but should be enough... but this is mainly an example anyway, so...)
haveDjinni[0, 0] == 1; //add Flint
haveDjinni[1, 0] == 1; //add Fizz
int[] djinnCounts = {1, 1, 0, 0} //For each element: Venus, Mercury, Mars, Jupiter
int djinnToAdd = 0x10
while (djinnToAdd > 0)
{
int element = (grn16() * 4) >> 16;
int djinni = (grn16() * 7) >> 16;
if (haveDjinni[element, djinni] == 0)
{
djinnCounts[element] += 1;
int low = 9;
int high = 0;
//High/low calculations/checks
for (int e = 0; e < 4; e++)
{
if (djinnCounts[e] < low)
{
low = djinnCounts[e];
}
if (djinnCounts[e] > high)
{
high = djinnCounts[e];
}
}
djinnCounts[element] -= 1;
if ((high - low) < = 1)
{
//Percents calculations
if (((grn16() * 100) >> 16) < djinnPercents[element, djinni])
{
haveDjinni[element, djinni] = 1;
djinnCounts[element] += 1;
djinnToAdd -= 1;
}
}
}
}
---
Might see if I can put all this (Level up calculations and Djinn picker) in LUA soon? But I'm a bit rusty with LUA... so I don't even know if I'll go on with it.
It'll take me some time to implement something which is able to utilise the stat generation code. Probably will have to write a script to search for combinations which gives us what we want, or at worst an excel/google sheet to calculate arbitrary combinations.
The attacks first/caught by surprise stuff can be implemented immediately though.
Let me just check my understanding, if 0xNMOPWRST is a hex number, then BRN16 returns 0xWR? or 0xOPWR? (I suppose it doesn't matter if you are & with 0xF or 0x1F though)
It would return OPWR.
WR is 8-bit, OPWR is 16-bit...
By the way, the Djinn Picker's done. Still got to do stat regeneration, though... but if using this script, it'll draw 1's for the djinn you'll get on next reroll...
local grnseed = 0
local brnseed = 0
function reset()
grnseed = memory.readdword(0x030011BC)
brnseed = memory.readdword(0x020054C8)
end
function grn16()
g = grnseed
m1 = 0x4e6d
m2 = 0x41c6
g1 = g*m1
g2 = g*m2
g2 = bit.band(g2,0xFFFF)
g = g1 + g2*0x10000
c=0x3039
g = g+c
g = bit.band(g,0xFFFFFFFF)
grnseed = g
g = bit.lshift(g,8)
g = bit.rshift(g,16)
return g
end
function brn16()
g = brnseed
m1 = 0x4e6d
m2 = 0x41c6
g1 = g*m1
g2 = g*m2
g2 = bit.band(g2,0xFFFF)
g = g1 + g2*0x10000
c=0x3039
g = g+c
g = bit.band(g,0xFFFFFFFF)
brnseed = g
g = bit.lshift(g,8)
g = bit.rshift(g,16)
return g
end
function djinnPercents(element, djinni)
return memory.readword(0x080B1290 + ((element - 1) * 14) + ((djinni - 1) * 2))
end
function rollDjinn()
reset()
haveDjinni = {}
haveDjinni[1] = {1, 0, 0, 0, 0, 0, 0}
haveDjinni[2] = {1, 0, 0, 0, 0, 0, 0}
haveDjinni[3] = {0, 0, 0, 0, 0, 0, 0}
haveDjinni[4] = {0, 0, 0, 0, 0, 0, 0}
djinnCounts = {1, 1, 0, 0}
djinnToAdd = 16
while djinnToAdd > 0 do
element = 1 + bit.rshift(grn16() * 4, 16)
djinni = 1 + bit.rshift(grn16() * 7, 16)
if haveDjinni[element][djinni] == 0 then
djinnCounts[element] = djinnCounts[element] + 1
low = 9
high = 0
for i=1,4 do
if djinnCounts[i] < low then
low = djinnCounts[i]
end
if djinnCounts[i] > high then
high = djinnCounts[i]
end
end
djinnCounts[element] = djinnCounts[element] - 1
if (high - low) <= 1 then
if bit.rshift(grn16() * 100, 16) < djinnPercents(element, djinni) then
haveDjinni[element][djinni] = 1
djinnCounts[element] = djinnCounts[element] + 1
djinnToAdd = djinnToAdd - 1
end
end
end
end
for i=1,4 do
for j=1,7 do
gui.text(195 + j * 5 ,0 + i * 6,haveDjinni[i][j])
end
end
return
end
while true do
rollDjinn()
vba.frameadvance();
end
Yeah I was pretty sure that it was 0xOPWR, always good to get that confirmed!
Very nice of you to write out the code for determining djinn. Thanks!
Okay.
And you are welcome...
I've been working on the calculations for stats.... and I'm currently at this point.
The code's there, sort of, but I'm not getting the right results, so I shall look into this!
WIP code:
local grnseed = 0
local brnseed = 0
function reset()
grnseed = memory.readdword(0x030011BC)
brnseed = memory.readdword(0x020054C8)
end
function grn16()
g = grnseed
m1 = 0x4e6d
m2 = 0x41c6
g1 = g*m1
g2 = g*m2
g2 = bit.band(g2,0xFFFF)
g = g1 + g2*0x10000
c=0x3039
g = g+c
g = bit.band(g,0xFFFFFFFF)
grnseed = g
g = bit.lshift(g,8)
g = bit.rshift(g,16)
return g
end
function brn16()
g = brnseed
m1 = 0x4e6d
m2 = 0x41c6
g1 = g*m1
g2 = g*m2
g2 = bit.band(g2,0xFFFF)
g = g1 + g2*0x10000
c=0x3039
g = g+c
g = bit.band(g,0xFFFFFFFF)
brnseed = g
g = bit.lshift(g,8)
g = bit.rshift(g,16)
return g
end
function startingStats()
stat = {}
stat[1] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[2] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[3] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[4] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[5] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[6] = {0, 0, 0, 0, 0, 0, 0, 0}
for pc=0,7 do
dLv = memory.readbyte(0x080C0F4C + (pc * 0xB4) + 0x96)
lv = 0
while lv < dLv do
lv = lv + 1
if (lv == 1) then
stat[1][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x50)
stat[2][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x5C)
stat[3][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x68)
stat[4][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x74)
stat[5][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x80)
stat[6][pc + 1] = memory.readbyte(0x080C0F4C + (pc * 0xB4) + 0x8C)
end
statGrowthI = bit.band(lv / 20, 0xFF)
v = 0x080C0F4C + (pc * 0xB4) + 0x50 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[1][pc + 1] = stat[1][pc + 1] + bit.band(v / 20, 0xFFFF)
v = 0x080C0F4C + (pc * 0xB4) + 0x5C + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[2][pc + 1] = stat[2][pc + 1] + bit.band(v / 20, 0xFFFF)
v = 0x080C0F4C + (pc * 0xB4) + 0x68 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[3][pc + 1] = stat[3][pc + 1] + bit.band(v / 20, 0xFFFF)
v = 0x080C0F4C + (pc * 0xB4) + 0x74 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[4][pc + 1] = stat[4][pc + 1] + bit.band(v / 20, 0xFFFF)
v = 0x080C0F4C + (pc * 0xB4) + 0x80 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[5][pc + 1] = stat[5][pc + 1] + bit.band(v / 20, 0xFFFF)
v = 0x080C0F4C + (pc * 0xB4) + 0x8C + (statGrowthI)
v = memory.readbyte(v + 1) - memory.readbyte(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[6][pc + 1] = stat[6][pc + 1] + bit.band(v / 20, 0xFF)
-- current stat += ((upper stat growth - lower stat growth) + ((grn16 * 20) >> 16)) / 20
end
end
for i=1,6 do
for j=1,8 do
gui.text(100 + j * 20 ,0 + i * 6,stat[i][j])
end
end
end
function djinnPercents(element, djinni)
return memory.readword(0x080B1290 + ((element - 1) * 14) + ((djinni - 1) * 2))
end
function rollDjinn()
haveDjinni = {}
haveDjinni[1] = {1, 0, 0, 0, 0, 0, 0}
haveDjinni[2] = {1, 0, 0, 0, 0, 0, 0}
haveDjinni[3] = {0, 0, 0, 0, 0, 0, 0}
haveDjinni[4] = {0, 0, 0, 0, 0, 0, 0}
djinnCounts = {1, 1, 0, 0}
djinnToAdd = 16
while djinnToAdd > 0 do
element = 1 + bit.rshift(grn16() * 4, 16)
djinni = 1 + bit.rshift(grn16() * 7, 16)
if haveDjinni[element][djinni] == 0 then
djinnCounts[element] = djinnCounts[element] + 1
low = 9
high = 0
for i=1,4 do
if djinnCounts[i] < low then
low = djinnCounts[i]
end
if djinnCounts[i] > high then
high = djinnCounts[i]
end
end
djinnCounts[element] = djinnCounts[element] - 1
if (high - low) <= 1 then
if bit.rshift(grn16() * 100, 16) < djinnPercents(element, djinni) then
haveDjinni[element][djinni] = 1
djinnCounts[element] = djinnCounts[element] + 1
djinnToAdd = djinnToAdd - 1
end
end
end
end
for i=1,4 do
for j=1,7 do
gui.text(195 + j * 5 ,0 + i * 6,haveDjinni[i][j])
end
end
return
end
while true do
reset()
startingStats()
--rollDjinn()
vba.frameadvance();
end
LUA is hard to use. :/ It's like... even worse than assembly. :P (Assembly is cool, though... but it often looks bloated.)
Better yet, to the majority of programmers who are familiar with how bad VB sucks... I kinda want to say LUA is just as bad or worse. :P
Well, at least I learned something this pass week about LUA = Indexes (in lists/arrays) start at 1 instead of 0... So that also adds more unnecessary bloat to my code.
@Isaac's Luck = Hmm.. why does my script generate Luck at ~17, when it can only be 3... Huh. - Luck stats always stay the same for starting stats = I could possibly comment it out....
@ bit.band(v / 20, 0xFF)
I expected that to return a 0 when v is 19... but it can return a 1? Wha? ... Hmmmm...... Probably cuz nasty floats. :/ (I'm an integer type of guy. Which is good, b/c most of the time I don't need decimal places, and in some ways the rarity of it can make me think it shouldn't hurt to use a second integer as the denominator. :P But it depends.)... maybe math.floor(a/b) works.
local grnseed = 0
local brnseed = 0
function reset()
grnseed = memory.readdword(0x030011BC)
brnseed = memory.readdword(0x020054C8)
end
function grn16()
g = grnseed
m1 = 0x4e6d
m2 = 0x41c6
g1 = g*m1
g2 = g*m2
g2 = bit.band(g2,0xFFFF)
g = g1 + g2*0x10000
c=0x3039
g = g+c
g = bit.band(g,0xFFFFFFFF)
grnseed = g
g = bit.lshift(g,8)
g = bit.rshift(g,16)
--g = bit.band(g,0xFFFF)
return g
end
function brn16()
g = brnseed
m1 = 0x4e6d
m2 = 0x41c6
g1 = g*m1
g2 = g*m2
g2 = bit.band(g2,0xFFFF)
g = g1 + g2*0x10000
c=0x3039
g = g+c
g = bit.band(g,0xFFFFFFFF)
brnseed = g
g = bit.lshift(g,8)
g = bit.rshift(g,16)
return g
end
function startingStats()
stat = {}
stat[1] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[2] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[3] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[4] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[5] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[6] = {0, 0, 0, 0, 0, 0, 0, 0}
for pc=0,7 do
dLv = memory.readbyte(0x080C0F4C + (pc * 0xB4) + 0x96)
lv = 0
while lv < dLv do
lv = lv + 1
if (lv == 1) then
stat[1][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x50)
stat[2][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x5C)
stat[3][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x68)
stat[4][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x74)
stat[5][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x80)
stat[6][pc + 1] = memory.readbyte(0x080C0F4C + (pc * 0xB4) + 0x8C)
end
statGrowthI = math.floor(lv / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x50 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[1][pc + 1] = stat[1][pc + 1] + math.floor(v / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x5C + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[2][pc + 1] = stat[2][pc + 1] + math.floor(v / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x68 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[3][pc + 1] = stat[3][pc + 1] + math.floor(v / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x74 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[4][pc + 1] = stat[4][pc + 1] + math.floor(v / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x80 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[5][pc + 1] = stat[5][pc + 1] + math.floor(v / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x8C + (statGrowthI)
v = memory.readbyte(v + 1) - memory.readbyte(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[6][pc + 1] = stat[6][pc + 1] + math.floor(v / 20)
-- current stat += ((upper stat growth - lower stat growth) + ((grn16 * 20) >> 16)) / 20
end
end
for i=1,6 do
for j=1,8 do
gui.text(90 + j * 16 ,112 + i * 6,stat[i][j])
end
end
end
function djinnPercents(element, djinni)
return memory.readword(0x080B1290 + ((element - 1) * 14) + ((djinni - 1) * 2))
end
function rollDjinn()
haveDjinni = {}
haveDjinni[1] = {1, 0, 0, 0, 0, 0, 0}
haveDjinni[2] = {1, 0, 0, 0, 0, 0, 0}
haveDjinni[3] = {0, 0, 0, 0, 0, 0, 0}
haveDjinni[4] = {0, 0, 0, 0, 0, 0, 0}
djinnCounts = {1, 1, 0, 0}
djinnToAdd = 16
while djinnToAdd > 0 do
element = 1 + bit.rshift(grn16() * 4, 16)
djinni = 1 + bit.rshift(grn16() * 7, 16)
if haveDjinni[element][djinni] == 0 then
djinnCounts[element] = djinnCounts[element] + 1
low = 9
high = 0
for i=1,4 do
if djinnCounts[i] < low then
low = djinnCounts[i]
end
if djinnCounts[i] > high then
high = djinnCounts[i]
end
end
djinnCounts[element] = djinnCounts[element] - 1
if (high - low) <= 1 then
if bit.rshift(grn16() * 100, 16) < djinnPercents(element, djinni) then
haveDjinni[element][djinni] = 1
djinnCounts[element] = djinnCounts[element] + 1
djinnToAdd = djinnToAdd - 1
end
end
end
end
for i=1,4 do
for j=1,7 do
gui.text(195 + j * 5 ,0 + i * 6,haveDjinni[i][j])
end
end
return
end
while true do
reset()
startingStats()
reset()
rollDjinn()
vba.frameadvance();
end
^How does it look? I think the calculations looking better now. (Calculates base stats and not current stats, when comparing to memory viewer.)
Stat table's in a pretty bad spot = It's a bit big.... so not sure what to do with it. - I guess that's up to you.
Well I've been attempting to do this all night but am failing spectacularly at it. I'm trying to search through the different combinations of "Felix Cancelling" and "Isaac cancelling" that gets me my desired stats/djinn.
In particular, Isaac rolling 120+ atk, Jenna rolling high agility, djinn: kite, breeze, zephyr, flash ground, granite. bonus: mist/squall/hail
Best I could find (by brute force) is 9 Felix Cancels which gets everything except that Isaac rolls 117 attack. Jennas agility could be higher as well.
EDIT: FC FC IC IC FC FC IC also works, and gets a better agility roll for Jenna.
The frustrating thing is that FC IC =/= IC FC for some reason.
QuoteThe frustrating thing is that FC IC =/= IC FC for some reason.
It's probably because of the way the djinn picker code works. (Chance to fail at picking one, and pick another.)
So while it is possible Felix Cancels (Stat generation) might always generate the same number of random numbers, the Isaac Cancels (Djinn Picker) are variable based on (un)successful picks.
That'd be the cause.
Yes. So, have you changed my script to do anything, or are simply looking at the numbers I added?
Since if there's a priority for the stats/djinn... I suppose it could be possible to develope the script further...
And making a recursive function for this could be a perfect fit! (I think? Depends.)
I'm kind of thinking something like this:
findBestWhatever(0)
function findBestWhatever(depth)
if depth >= 10 then return --Important to avoid endless calls.
rng = grnseed --rng needs to be a function-level variable.
statregen()
findBestWhatever(depth + 1)
grnseed = rng
djinnpicker()
findBestWhatever(depth + 1)
end
Incomplete, ofcourse.... but I hope I did the base example correctly? Erm...
As you can see, it kind of mimics a data tree... and it's also easy to add more conditions if needed.
--
Going to see what I can do with putting in Isaac's Attack in a bit, but who knows if it'll work out/execute fast enough.
WIP code:
local grnseed = 0
local brnseed = 0
function reset()
grnseed = memory.readdword(0x030011BC)
brnseed = memory.readdword(0x020054C8)
end
function grn16()
g = grnseed
m1 = 0x4e6d
m2 = 0x41c6
g1 = g*m1
g2 = g*m2
g2 = bit.band(g2,0xFFFF)
g = g1 + g2*0x10000
c=0x3039
g = g+c
g = bit.band(g,0xFFFFFFFF)
grnseed = g
g = bit.lshift(g,8)
g = bit.rshift(g,16)
--g = bit.band(g,0xFFFF)
return g
end
function brn16()
g = brnseed
m1 = 0x4e6d
m2 = 0x41c6
g1 = g*m1
g2 = g*m2
g2 = bit.band(g2,0xFFFF)
g = g1 + g2*0x10000
c=0x3039
g = g+c
g = bit.band(g,0xFFFFFFFF)
brnseed = g
g = bit.lshift(g,8)
g = bit.rshift(g,16)
return g
end
stat = {}
stat[1] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[2] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[3] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[4] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[5] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[6] = {0, 0, 0, 0, 0, 0, 0, 0}
function startingStats()
stat[1] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[2] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[3] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[4] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[5] = {0, 0, 0, 0, 0, 0, 0, 0}
stat[6] = {0, 0, 0, 0, 0, 0, 0, 0}
for pc=0,7 do
dLv = memory.readbyte(0x080C0F4C + (pc * 0xB4) + 0x96)
lv = 0
while lv < dLv do
lv = lv + 1
if (lv == 1) then
stat[1][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x50)
stat[2][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x5C)
stat[3][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x68)
stat[4][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x74)
stat[5][pc + 1] = memory.readword(0x080C0F4C + (pc * 0xB4) + 0x80)
stat[6][pc + 1] = memory.readbyte(0x080C0F4C + (pc * 0xB4) + 0x8C)
end
statGrowthI = math.floor(lv / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x50 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[1][pc + 1] = stat[1][pc + 1] + math.floor(v / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x5C + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[2][pc + 1] = stat[2][pc + 1] + math.floor(v / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x68 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[3][pc + 1] = stat[3][pc + 1] + math.floor(v / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x74 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[4][pc + 1] = stat[4][pc + 1] + math.floor(v / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x80 + (statGrowthI * 2)
v = memory.readword(v + 2) - memory.readword(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[5][pc + 1] = stat[5][pc + 1] + math.floor(v / 20)
v = 0x080C0F4C + (pc * 0xB4) + 0x8C + (statGrowthI)
v = memory.readbyte(v + 1) - memory.readbyte(v)
v = v + bit.rshift(grn16() * 20, 16)
stat[6][pc + 1] = stat[6][pc + 1] + math.floor(v / 20)
-- current stat += ((upper stat growth - lower stat growth) + ((grn16 * 20) >> 16)) / 20
end
end
-- for i=1,6 do
-- for j=1,8 do
-- gui.text(90 + j * 16 ,112 + i * 6,stat[i][j])
-- end
-- end
end
function djinnPercents(element, djinni)
return memory.readword(0x080B1290 + ((element - 1) * 14) + ((djinni - 1) * 2))
end
function rollDjinn()
haveDjinni = {}
haveDjinni[1] = {1, 0, 0, 0, 0, 0, 0}
haveDjinni[2] = {1, 0, 0, 0, 0, 0, 0}
haveDjinni[3] = {0, 0, 0, 0, 0, 0, 0}
haveDjinni[4] = {0, 0, 0, 0, 0, 0, 0}
djinnCounts = {1, 1, 0, 0}
djinnToAdd = 16
while djinnToAdd > 0 do
element = 1 + bit.rshift(grn16() * 4, 16)
djinni = 1 + bit.rshift(grn16() * 7, 16)
if haveDjinni[element][djinni] == 0 then
djinnCounts[element] = djinnCounts[element] + 1
low = 9
high = 0
for i=1,4 do
if djinnCounts[i] < low then
low = djinnCounts[i]
end
if djinnCounts[i] > high then
high = djinnCounts[i]
end
end
djinnCounts[element] = djinnCounts[element] - 1
if (high - low) <= 1 then
if bit.rshift(grn16() * 100, 16) < djinnPercents(element, djinni) then
haveDjinni[element][djinni] = 1
djinnCounts[element] = djinnCounts[element] + 1
djinnToAdd = djinnToAdd - 1
end
end
end
end
-- for i=1,4 do
-- for j=1,7 do
-- gui.text(195 + j * 5 ,0 + i * 6,haveDjinni[i][j])
-- end
-- end
return
end
hAtk = 0
hAtk2 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} --0 --
atk = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} --0
tree = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
hTree = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
function savetree()
for i=1,10 do
hTree[i] = tree[i]
hAtk2[i] = atk[i]
end
return
end
function findBest(depth)
if depth >= 4 then return end --Important to avoid endless calls.
rng = grnseed --rng needs to be a function-level variable.
tree[depth] = 1
startingStats() --statregen()
atk[depth] = stat[3][1]
if hAtk < stat[3][1] then
hAtk = stat[3][1]
savetree()
end
findBest(depth + 1)
tree[depth] = 2
grnseed = rng
rollDjinn() --djinnpicker()
findBest(depth + 1)
tree[depth] = 0
--atk[depth] = 0;
return
end
while true do
reset()
hAtk = 0
--gui.text(200, 10, "!")
findBest(1)
for i=1,3 do --10 do
gui.text(150 + i * 20, 0, hTree[i])
gui.text(150 + i * 20, 10, hAtk2[i])
end
--startingStats()
--reset()
--rollDjinn()
vba.frameadvance();
end
Was not fully tested, so there may or may not be errors.
Here, shows 6 numbers... (Columns represent each cycle= 1st, 2nd, or 3rd action.)
The top row is:
0 = Nothing/Ignore
1 = Do a Felix Cancel
2 = Do an Isaac Cancel
The bottom row is Isaac's base attack at each stage. (So if the same column is switched to a 1/"Felix Cancel" in case of 2 (not tested, though.), you'd get this value.)
TODO = I want to add in a map/door check... as well as a check to a certain pointer in the stack. (So the info is only generated when necessary instead of every frame. = Would appear to increase the speed of searches of larger depths a great deal.
*Takes a look at your script at pastebin, and then becmes curous if something similar to "return (bit.band(g,0xF) == 0) or ((bit.band(g2,0x1F) ==0) * 2)" can be done. (All those if statements as a one liner.)
Except operationss as such can't be done on boolean values in LUA.... ... but one can still make a hack for that, and use a dictionary.
EX:
t = {}
t[true] = 1
t[false] = 0
gui.text(200, 20, t[0==0] * 2)
t = {[false]=0, [true]=1}
gui.text(200, 20, t[0==0] * 3)