Page 1 of 1

Trouble generating string-based seeds

Posted: Tue Oct 31, 2017 9:40 pm
by leNoah
Hello everyone,
I've been experimenting with random generation, and seed-based stuff. I'm not really sure of the best way to do this, previously I just called love.math.setRandomSeed(seed) in love.load.
What I want to do is let the user input a string that can be used for a string. Currently, I have this function:

Code: Select all

function generateSeed(seed)
  seedStringOfNumbers = ""
  
  for i = 1, string.len(seed) do
    seedStringOfNumbers = seedStringOfNumbers .. tostring(string.byte(string.sub(seed, i, i)))
  end
  print(seedStringOfNumbers)

  return(seedStringOfNumbers)
  --love.math.setRandomSeed(tonumber(seedStringOfNumbers))
end
The problem is, almost any seed i put in is too big, and just sets the seed to 0!
I'm really not sure how to fix this, I'd be really grateful for any help.

Thanks in advance,
Noah :)

Re: Trouble generating string-based seeds

Posted: Wed Nov 01, 2017 12:13 am
by Azhukar
Repeated string concatenation produces a lot of garbage for the garbage collector, work with bytes or use table.concat

Here's a very bad string hashing function

Code: Select all

local maxSeed = 2^30
local function stringToSeed(s)
	local seed = 1
	for i=1,s:len() do
		seed = (seed*31337 + s:byte(i))%maxSeed
	end
	return seed
end

Re: Trouble generating string-based seeds

Posted: Wed Nov 01, 2017 8:34 am
by zorg
The problem is that the way you're doing it, each character will take up either 2 or 3 digits, and the numbers in lua have ~15 decimal digit precision at the very least. That means your strings will have to be limited to 15/2 or 15/3, or 4-5 characters.

That's not how seed strings work, usually.

As Azhukar said above me, people need to use a hash function, that converts an any-sized string into a constant-sized number (or array of bits, whichever you prefer to call it); in our case, löve's random generators can either use one number, or two 32-bit integers (i'm assuming, the wiki doesn't say but it is kinda self-evident) for a 64-bit seed value. The hash function could go for the latter.

A good hash function mixes all bits of the input into all bits of the output, and the next löve version will include a few types:
* Added love.data module. It includes hex/base64 encoding functions, MD5 and SHA hashing, string packing, and more.
For now, you can use Azhukar's, though i do suggest an edited version:

Code: Select all

local maxSeed = 2^32
local function stringToSeed(s)
	local seedlo, seedhi = 1, 1
	for i=1,s:len() do
		seedlo = (seedhi * 31337 + s:byte(            i)) % maxSeed
		seedhi = (seedlo * 31337 - s:byte((s:len()+1)-i)) % maxSeed
	end
	return seedlo, seedhi
end
And you just pass the function into the setRandomSeed function, and it'll use both numbers to set the seed.