Results 1 to 3 of 3

Thread: math.random

  1. #1
    Basic Member
    Join Date
    Mar 2012
    Posts
    2,017

    math.random

    Anyone having issues with this? I am testing some stuff in my bots and I am using the same session (starting a lobby, quitting a lobby, starting a lobby, quitting a lobby a.s.o) without quitting DOTA, but each match the randoms are the same.
    Here is an example:

    Code:
    local rand = math.random();
    
    		if (lane == Lanes.LANE_MID) then
    print(" 1 * " .. rand)
    			if (rand < 0.33) then
    				lane = Lanes.LANE_TOP;
    			elseif (rand < 0.66) then
    				lane = Lanes.LANE_BOT;
    			else
    				rand = math.random();
    print(" 2 * " .. rand)
    				if (rand < 0.50) then
    print("bot")
    				else
    print("top")
    				end
    			end
    		end
    1 and 2 will ALWAYS be "1 * 0.66110719599522" and "2 * 0.33933341140343" every match. Haven't tested after a restart, but I am afraid :P

    The problem is normally, in any language the seed would be the time, but the OS library is missing, so I can't use math.randomseed(os.time()).
    I can probably do a workaround using the Random* functions and a clever use of RealTime() but this is, a hack (which I hate a LOT).

    I recommend that each new match issues a new seed on the OS time by default. That is how it'd normally be anyway.
    Anyone else having issues with it?

    Side topic, but related: any chance we can get some exported PRNG functions ?
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

  2. #2
    Basic Member
    Join Date
    Dec 2016
    Posts
    731
    is the Random API functions provided suffer from the same issue?

  3. #3
    Basic Member
    Join Date
    Mar 2012
    Posts
    2,017
    No. Those either use a diff library or do a proper seed.

    I am gonna use this until it gets fixed

    Code:
    function randseed () 
    	local v = RandomVector(DotaTime() * RandomFloat(RandomFloat(0.45, 0.85), RandomFloat(0.75, DotaTime())));
    	local abs = math.abs;
    	local x = v.x;
    	local y = v.y;
    	local z;
    
    	if (abs(x) == 0) then
    		x = abs(x) + DotaTime();
    	end
    
    	if (abs(y) == 0) then
    		y = abs(y) + DotaTime();
    	end
    
    	if (RandomFloat(0.30, 0.70) < 0.50) then
    		z = abs(x / y);
    	else
    		z = abs(y / x);
    	end
    
    	local w;
    	
    	if (RandomFloat(0.20, 0.85) < 0.45) then
    		w = abs(DotaTime() / z * RandomFloat(x, y));
    	else
    		w = abs(z / DotaTime() * RandomFloat(x, y));
    	end
    
    	math.randomseed(w);
    	return nil;
    end
    
    local seed = randseed();
    It's obviously not guaranteed to ALWAYS be unique. But I didn't make it for security, just to get around the issue and simulate as much "randomness" as it can... I placed this in my global utility package to make the static variable call the function once after the VM is initialized and before all scripts. This is a hack so I feel very dirty for using it...
    Last edited by The Nomad; 02-11-2017 at 01:46 PM.
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •