User File #638800802897292523

Upload All User Files

#638800802897292523 - Famidash v1.2.1 Lucky Draw RNG analyzer

famidash_lucky_draw_analyze_starting_rng_value_121.lua
Game: Famidash ( NES, see all files )
276 downloads
Uploaded 4/12/2025 6:44 PM by FractalFusion (see all 98)
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
For Famidash v1.2.1+. Does not apply to v1.2 and earlier.
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)
--**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