--**NOTE: THE SCRIPT IS NOT VERY FAST, IT MAY TAKE UP TO FIVE MINUTES (at max_attempt=999999) TO FINISH. IT WILL FREEZE BIZHAWK IN THE MEANTIME**
--famidash v1.2.1
--This script tells you, starting with an RNG value either specified or read from memory, whether Lucky Draw will eventually be successful within "max_attempt" loops (modes 1&2), or alternatively whether the first attempt is successful or fails a particular check (modes 3&4).
--mode 1: Starting with initial RNG given below, determine whether Lucky Draw will eventually be successful within "max_attempt" loops, and how many attempts it takes.
--mode 2: Same as mode 1, but with RNG value read from memory address 0x1B (4-byte little-endian)
--mode 3: Starting with initial RNG given below, determine whether the first attempt is successful, and if not, which of the 788 checks it fails, and the final RNG value upon death (this RNG value is the value for the next attempt).
--mode 4: Same as mode 3, but with RNG value read from memory address 0x1B (4-byte little-endian)
console.clear()
local mode=2
local max_attempt=999999 --As a sanity check to restrict execution to ~5 minutes. You can make it bigger if necessary.
local initial_rng_value=0xBAD4A72C --Only applicable if mode is 1 or 3. Modes 2 and 4 get RNG value from memory address 0x1B.
--this RNG is a 32-bit linear feedback shift register (LFSR)
--also called "newrand" in the source
local function rand32(thisrng, numtimes)
local rng=thisrng
for i=1,(8*numtimes) do
if rng>=0x80000000 then rng = ((rng*2)&0xFFFFFFFF)~0xC5 else rng = rng*2 end
end
return rng
end
--check whether player survives in Lucky Draw - there are 800 such checks
local function check(rng1,rng2)
return ((rng1&0x3F)~=(rng2&0x3F))
end
local crng_temp=0
local check_count=1
local dist=0
local crng=0
if mode==1 or mode==3 then
crng=initial_rng_value
else
crng=mainmemory.read_u32_le(0x1B)
end
local prev_values={}
local exitvalue=-1
local successflag=false
local i=0
console.write(string.format("Testing RNG value %08X:\n", crng))
--this is the main loop
--limited to "max_attempt" loops
for i=1,max_attempt do
if i==max_attempt then
exitvalue=max_attempt
break
end
for fakeloop=1,1 do
--check #1
crng_temp=rand32(crng,50)
crng=rand32(crng_temp,1)
if check(crng,crng_temp) then check_count=check_count+1 else
break
end
crng=rand32(crng,1)
--the following is responsible for checks #2-#800
dist=13504
local nextcheckdist=16640
local get_out=false
while dist<3286588 do
if dist>=nextcheckdist then
--check
crng_temp=rand32(crng,1)
crng=rand32(crng_temp,1)
if check(crng,crng_temp) then
check_count=check_count+1
nextcheckdist=nextcheckdist+4096
else
get_out=true
dist=dist+708
break
end
end
dist=dist+708
crng=rand32(crng,1)
end
if get_out then break end
successflag=true
exit_flag=i
end
if successflag or mode>=3 then break end
end
if successflag then
if mode==1 or mode==2 then
console.write(string.format("Success after %d attempts", exit_flag))
else
console.write("Attempt is successful")
end
else
if mode==1 or mode==2 then
if exitvalue~=max_attempt then
--nothing
else
console.write(string.format("Exited after max attempts (%d)",max_attempt))
end
else
console.write(string.format("Failed at check #%d with final RNG value: %08X", check_count, crng))
end
end