How to go about daily random numbers

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
Gunroar:Cannon()
Party member
Posts: 1143
Joined: Thu Dec 10, 2020 1:57 am

Re: How to go about daily random numbers

Post by Gunroar:Cannon() »

Wait, so I should use 13 instead of 16 :?
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
idbrii
Prole
Posts: 34
Joined: Sat Jun 12, 2021 5:07 am

Re: How to go about daily random numbers

Post by idbrii »

What about this:

Code: Select all

local d = os.date("!*t") -- utc date
local rng = love.math.newRandomGenerator(d.yday, d.year)
-- call rng for each random number when building a level:
local num = rng:random(1, 1000)
grump wrote: Sat Jan 08, 2022 5:15 pm It's not really random, because you easily generate numbers for any date in advance.
Why try to randomize your seed? It's love, so people can read all your code, right? Or change their system clock.
Gunroar:Cannon() wrote: Sat Jan 08, 2022 6:51 pm Hmmm... I guess I'll use the first method then. Just thought they might make similar maps :P ... for ... some reason :ehem:
If you put your date number into a random number generator like grump's second suggestion (or mine), then it won't generate similar maps. A good random number generator should create different sequences of numbers for different seeds. You could multiply yday by 100 to ensure very different seeds to the rng each day, but I found my levels very different each day.
pgimeno wrote: Sat Jan 08, 2022 6:25 pm ... The sha1 method does not have this problem, but it's a bit harder to handle, as you don't have functions to yield a range etc.
If building a level, I'd expect you need to make many random decisions. To generate multiple random numbers with the sha version without producing the same sequence at a later date, you'd have to concatenate a sequence number too as well as pad the numbers with 0 like grump said.
User avatar
Gunroar:Cannon()
Party member
Posts: 1143
Joined: Thu Dec 10, 2020 1:57 am

Re: How to go about daily random numbers

Post by Gunroar:Cannon() »

Oh, that also looks good. Though the problem of people being able change their system clock to get old levels :?
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: How to go about daily random numbers

Post by grump »

Gunroar:Cannon() wrote: Sun Jan 09, 2022 9:53 am Though the problem of people being able change their system clock to get old levels :?
Future levels, too. Is that really a problem? Or could you just not care? I can assure you: you will regret to have opened that can of worms.
MrFariator
Party member
Posts: 559
Joined: Wed Oct 05, 2016 11:53 am

Re: How to go about daily random numbers

Post by MrFariator »

Going back to new/old levels is kind of a moot point if you don't have online leaderboards or things where people will directly compare their results against one another. And if you go down that road to implement leaderboards, you might as well implement a central authoritative server that the game queries for the given daily seed - where you could do any number of things to make the seed generation harder to track or predict in advance.

Of course, with any kind of online leaderboard, the bigger concern is always going to be more traditional type of cheating (infinite health, lives, maxed out points, etc).
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to go about daily random numbers

Post by pgimeno »

Gunroar:Cannon() wrote: Sat Jan 08, 2022 10:29 pm Wait, so I should use 13 instead of 16 :?
Yes, inside hash:sub() only; the other 16 stays. It will then produce a number between 0 and 0xFFFFFFFFFFFFF (that's 13 F's) and then you can get a number in a certain range by using modulo (%). If you use 16, using modulo will produce zeros in the lowest bits > 99.9% of the time.

To leave no doubt, you need to change from this:

Code: Select all

local rand = tonumber(hash:sub(1, 16), 16)
to this:

Code: Select all

local rand = tonumber(hash:sub(1, 13), 16)
User avatar
Gunroar:Cannon()
Party member
Posts: 1143
Joined: Thu Dec 10, 2020 1:57 am

Re: How to go about daily random numbers

Post by Gunroar:Cannon() »

Thanks for the fix.

I guess it's not to much of problem. Just need a simple system for now, I don't even know anything about online leaderboards :?
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: How to go about daily random numbers

Post by grump »

It makes no sense to use the convoluted hash method to generate a number just because the RNG algorithm might change in the future, if you use that number to seed love's RNG anyway. It is only good for one high-quality number and would require work to generate more (look up sponge functions if you're interested). It is also very slow.
User avatar
slime
Solid Snayke
Posts: 3166
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: How to go about daily random numbers

Post by slime »

If you're going to be using love's RandomGenerator, its code applies a hash to the seed before generating the first random number already, so applying another hash to the seed before giving it to love shouldn't be needed.
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to go about daily random numbers

Post by pgimeno »

grump wrote: Sun Jan 09, 2022 1:11 pm It makes no sense to use the convoluted hash method to generate a number just because the RNG algorithm might change in the future, if you use that number to seed love's RNG anyway. It is only good for one high-quality number and would require work to generate more (look up sponge functions if you're interested). It is also very slow.
Yes it's slow, but you don't need to set up something as complex as a sponge function. You can hash a counter.

Code: Select all

local rand
do
  local prefix
  do
    local d = os.date('!*t')
    prefix = ("%d:%d:%d:"):format(d.year, d.month, d.day)
  end

  local ctr = 0
  local pool = love.data.hash('sha512', prefix .. tostring(ctr))
  local idx = 1

  function rand(lo, hi)
    assert(hi - lo >= 0 and hi - lo <= 0xFFFFFFFF, "rand: Invalid range for low and high values")
    if idx > #pool then
      ctr = ctr + 1
      pool = love.data.hash('sha512', prefix .. tostring(ctr))
    end
    idx = idx + 4
    return love.data.unpack("<i4", pool, idx - 4) % (hi - lo + 1) + lo
  end
end
For example, the output of the first 10 numbers between 1 and 5 on January 9 2022 is:
5
3
1
2
3
5
4
1
1
4
Post Reply

Who is online

Users browsing this forum: Google [Bot], slime and 6 guests