Mordred Posted February 4, 2014 Share Posted February 4, 2014 Hello fellow Leadwerkers, I'm messing arround as usually. This time i'm trying to get a random function up n running. I did it the easy way for now, to know how it works, but it doesn't work as intended. I might want to say, that i do understand, that math.random is only pseudorandom, i have to shuffle the numbers before i really can use them with "math.randomseed ( os.time())" every time I need a new random seed. Thus no problem. I did use that in another script too and there it did work quite well, but now the following happens. I have a table, in this table several skillrelated items are stored (the table contains the skills "woodcutting" and quarrying, both values again contain several items (logs, bark, twigs....) with an initial value of 0. I now want to iterate this table, check if the "used skill" is within this table and, if it is, i want to increase each value of those items individually. So basically, i have 5 items stored, i want to add a random number to the first one and another random number to the 2nd one. But i always end up that all 5 items do get the exact same number. For a better understanding i gonna add the table and the loop in here. Hopefully, you do understand what i mean. It's sometimes hard to explain myself using english. Table: Script.xInventory = { woodcutting = { logs = 0, bark = 0, twigs = 0, leafs = 0, insects = 0 }, quarrying = { clay = 0, limestone = 0, granite = 0, basalt = 0, obsidian = 0, marble = 0, quartz = 0 } } Script: for a, b in pairs(self.target.script.inventory.script.xInventory) do -- check if the used skill does exists in our table if a == self.usedSkill then for x, y in pairs(B) do math.randomseed(os.time() + i) ammount = y + math.floor(math.random(0, 1 + (statvalue * (100 + skillvalue) / 1000))) i = i + 10 end end end As you can see, i added the math.randomseed(os.time() + i) into the loop. I did add +i (i is plus 10 every loop cycle) to avoid the script using the same time twice, since i already know that os.time() only counts within a second or so. I had the same problem using the "GetSpeed()" function though. Still the "random seed" seems to be always the same. Quote Link to comment Share on other sites More sharing options...
Rick Posted February 4, 2014 Share Posted February 4, 2014 You normally only want to seed once in your entire program. Move that seeding line into App.lua Start(). Quote Link to comment Share on other sites More sharing options...
Mordred Posted February 4, 2014 Author Share Posted February 4, 2014 Hello Rick, thanks for your reply (again ). But wouldn't be it so that if i do add the seeding into App.lua that there's a quite high chance to get 2 "math.random(1, 100) in a row generating the same result, or am i wrong? For e.g. to randomize "Skillgains" i actually HAD to use two different seeds to prevent the "Skillains" happen at the same time with the same increasevalue. Quote Link to comment Share on other sites More sharing options...
Rick Posted February 4, 2014 Share Posted February 4, 2014 hmm, every call to math.random() should produce a random number. Are you sure your example always gave the same number between 2 different calls, when you did a seed on it only 1 time in your app? I can't test that right now as I'm not at home, but I don't recall seeing that issue with other stuff I did with random. Can you produce a simple example that shows this possible issue? Quote Link to comment Share on other sites More sharing options...
Josh Posted February 4, 2014 Share Posted February 4, 2014 Hello Rick, thanks for your reply (again ). But wouldn't be it so that if i do add the seeding into App.lua that there's a quite high chance to get 2 "math.random(1, 100) in a row generating the same result, or am i wrong? For e.g. to randomize "Skillgains" i actually HAD to use two different seeds to prevent the "Skillains" happen at the same time with the same increasevalue. Random numbers can and will produce the same value twice in a row. The value of the last call has no bearing on the value of the next call...otherwise it wouldn't be random! Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Mordred Posted February 4, 2014 Author Share Posted February 4, 2014 @ Rick, i gonna try to set smth. up in a few minutes (if i manage to get it up 'n runnin, i'm still new to all that stuff ) @ Josh, i'm refering to this thread "A good* 'seed' is os.time(), but wait a second before calling the function to obtain another sequence! To get nice random numbers use:" http://lua-users.org/wiki/MathLibraryTutorial They mention that you should wait a second between two math.random calls due to the fact that the random seed will be the same within a second. Anyways, i just added a simple, plain, math.randomseed(os.time()) into my app.lua and fired up a simple System:Print(math.random(1, 10) onto the console and had no issues at all, they numbers def. were random, even though i generated them in a "for" loop 10 times in a row. So basically, that means i'm doing smth. wrong. And i'm so stupid....i know what's my problem. In case someone is interested in knowing. I did a loop iterating the table i mentioned before. I than stored the item's value (predefined as "0") into the variable "ammount". I than "end"ed the iteration and started a new one working with that "ammount". I think everybody now knows what my problem is. The vallue in ammount was only the last value i received from the first loop. Basically like this: for a, b in pairs(self.target.script.inventory.script.xInventory) do if a == self.usedSkill then for y, x in pairs (B) do [b]ammount[/b]= x end end end for a, b in pairs(self.target.script.inventory.script.xInventory) do -- check if the used skill does exists in our table if a == self.usedSkill then for x, y in pairs(B) do [b]ammount[/b]= y + math.floor(math.random(0, 1 + (statvalue * (100 + skillvalue) / 1000))) i = i + 10 end end end The solution would be like this: for a, b in pairs(self.target.script.inventory.script.xInventory) do -- check if the used skill does exists in our table if a == self.usedSkill then for x, y in pairs(B) do ammount = y + math.floor(math.random(0, 1 + (statvalue * (100 + skillvalue) / 1000))) self.target.script.inventory.script.xInventory[a][x] = ammount self.target.script.hud.script.xSkills[self.usedSkill] = skillvalue + self.target.script.hud.script.skillgain self.target.script.hud.script.xStats[self.usedStat] = statvalue + self.target.script.hud.script.statgain end end end Quote Link to comment Share on other sites More sharing options...
Marleys Ghost Posted February 4, 2014 Share Posted February 4, 2014 @Mordred: A pseudo-random number generator like math.random takes a starting number, in this case, (math.randomseed( os.time() ) ), performs mathematical operations on it, then continually applies the algorithm to the last generated number, however while each number in the sequence is seemingly random with regards to the previous ones, the entire sequence is not random at all. math.randomseed(999) for n = 0, 5 do num = math.random(9) Print (num) end 1,9,3,7,7,1 everytime. When you use math.random in a loop, you should always have (math.randomseed( os.time() ) ) outside of the loop, this is because the iterations are executed really fast and it nearly every time re-assigns the same "current time", that results in the same *random* starting number being generated. for n = 0, 5 do math.randomseed(os.time()) num = math.random(9) Print (num) end That gave me 7,7,7,7,7,7 You had: local i=0 for n = 0, 5 do math.randomseed(os.time() + i) num = math.random(9) Print (num) i = i + 10 end but again this produces the same first *random* starting number over and over, the article you link to explains why: This difference is lost when Lua converts the integer returned by rand() into a real number, effectively preserving only the high bits in the result. When you call math.random(1,100) from Lua, the low-bit difference vanishes and you see the same integer result So all you have to do is to take math.randomseed( os.time() ) out of loop and set it only once per application run, if you want to "mix up" the seed each time you run the application try: math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) ) 1 Quote AMD Bulldozer FX-4 Quad Core 4100 Black Edition 2 x 4GB DDR3 1333Mhz Memory Gigabyte GeForce GTX 550 Ti OC 1024MB GDDR5 Windows 7 Home 64 bit BlitzMax 1.50 • Lua 5.1 • MaxGUI 1.41 • UU3D Pro • MessiahStudio Pro • Silo Pro 3D Coat • ShaderMap Pro • Hexagon 2 • Photoshop, Gimp & Paint.NET LE 2.5/3.4 • Skyline • UE4 • CE3 SDK • Unity 5 • Esenthel Engine 2.0 Marleys Ghost's YouTube Channel • Marleys Ghost's Blog "I used to be alive like you .... then I took an arrow to the head" Link to comment Share on other sites More sharing options...
Mordred Posted February 4, 2014 Author Share Posted February 4, 2014 Hey Marleys Ghost, thanks for explaining it in such detail. I did missunderstood what was written in that wiki. Now that i did put the "randomseed" into app.lua i do not have any issues at all. Besides, i had a builtin error made by myself too (as stated before). Yet i'm quite sure that my "randomseed" within the loop would work since i changed the seed myself everytime by adding "+i" ontop of the initial value. Or am i wrong with that too? Basically i do understand it as: - - First run --> randomseed is os.time() - second run --> randomseed is os.time() + 10 - third run --> randomseed is os.time() + 20 and thus the seeds differ? Quote Link to comment Share on other sites More sharing options...
Marleys Ghost Posted February 4, 2014 Share Posted February 4, 2014 and thus the seeds differ? Not by enough: This difference is lost when Lua converts the integer returned by rand() into a real number, effectively preserving only the high bits in the result. When you call math.random(1,100) from Lua, the low-bit difference vanishes and you see the same integer result EDIT: Plus theres no real benefit to constantly altering the seed Quote AMD Bulldozer FX-4 Quad Core 4100 Black Edition 2 x 4GB DDR3 1333Mhz Memory Gigabyte GeForce GTX 550 Ti OC 1024MB GDDR5 Windows 7 Home 64 bit BlitzMax 1.50 • Lua 5.1 • MaxGUI 1.41 • UU3D Pro • MessiahStudio Pro • Silo Pro 3D Coat • ShaderMap Pro • Hexagon 2 • Photoshop, Gimp & Paint.NET LE 2.5/3.4 • Skyline • UE4 • CE3 SDK • Unity 5 • Esenthel Engine 2.0 Marleys Ghost's YouTube Channel • Marleys Ghost's Blog "I used to be alive like you .... then I took an arrow to the head" Link to comment Share on other sites More sharing options...
Mordred Posted February 4, 2014 Author Share Posted February 4, 2014 Yea, well, that there's no real benefit in doing so is clear now, thanks to your explanations. I actually saw that quote you postet before too but i didn't read it, because it was statet as "OsX and FreeBSD" and since i use windows i didn't bother reading it. Well, maybe i should change my behaviour a bit. Thank you again for pointing me to this Quote Link to comment Share on other sites More sharing options...
Rick Posted February 4, 2014 Share Posted February 4, 2014 @Mordred you should buy a lottery ticket. This is a rare Marley's Ghost sighting Quote Link to comment Share on other sites More sharing options...
Mordred Posted February 4, 2014 Author Share Posted February 4, 2014 Maybe my mistake/s was/were so big that he couldn't resists replying Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.