Code is not running in the device as it does in the simulator

23 replies [Last post]
d3mac123
User is online Online
Joined: 12 Feb 2010

I have a function that randomly selects a picture from a table and display it. In the simulator the sample code below works perfectly, when I send it to device, only the first element from the table is selected. Any ideas? I can share the full app code if someone is interested in to take a look.

local temp = {"alex","john","josh"}
local tempNum = #temp

local function selectRandom(tName)
if (tName=="Random" or tName=="" or tName==nil) then
local randTemp = math.random(tempNum)
tempName = temp[randTemp]
local img=display.newImage(tempName..".jpg")
end

end

selectRandom()

Replies

MikeHart
User offline. Last seen 2 hours 46 min ago. Offline
Joined: 22 Mar 2010

do you seed the random number generator somewhere at first?

MikeHart
User offline. Last seen 2 hours 46 min ago. Offline
Joined: 22 Mar 2010

I do this at the beginning of my app

math.randomseed(os.time())
dummy = math.random(0,255)

this takes care that the random numbers are always different.

d3mac123
User is online Online
Joined: 12 Feb 2010

why do I have to use math.randomseed? considering my other languages experience, all I should do was to use the random function... I will try. thanks!

MikeHart
User offline. Last seen 2 hours 46 min ago. Offline
Joined: 22 Mar 2010

generally a random number generator take a certain time value into account. With Lua/Corona it is when an app starts the apps runtime. So you will usually get always the same numbers. I think I seen this behaviour with other programming languages too.

d3mac123
User is online Online
Joined: 12 Feb 2010

The simulator is working great with the seed (every time i run it it comes with another data) but, when I move it to the device, the same image appears all the time.

Any ideas on what I could do here?

s.w.powers
User offline. Last seen 1 year 4 weeks ago. Offline
Joined: 16 Mar 2010

Not without seeing the code for a working example of the problem.

MikeHart
User offline. Last seen 2 hours 46 min ago. Offline
Joined: 22 Mar 2010

Did you seed the random generator at the start of your app like I showed you? Plus that dummy call of math.random?

d3mac123
User is online Online
Joined: 12 Feb 2010

Here goes:

math.randomseed = ( os.time() )
local tNum = 150
local places = {"place1", "place2", "placeN"}

-- Select a place randomically
local function selectRandom(tName)
if (tName=="Random" or tName=="" or tName==nil) then
--pick a random place, otherwise get the tName informed
randT = math.random(tNum)
randT = math.random(tNum)
tFile = places[randT]
else
tFile = tName
end

end

--Pick a temple to display
local randT = 0
randT = math.random(tNum)
selectRandom()

MikeHart
User offline. Last seen 2 hours 46 min ago. Offline
Joined: 22 Mar 2010

So no dummy call. There is a topic here on the forum, that the the first math.random call is always the same. That is why I posted about the dummy call.

myfogview
User offline. Last seen 2 weeks 5 days ago. Offline
Joined: 14 Apr 2010

I just verified that the dummy call IS needed or your random number always starts out the same. I tested this in the Corona SDK 1.1 simulator.

I went to the Lua.org demo site, http://www.lua.org/cgi-bin/demo, and entered the same code and it worked without the dummy call. I thought the Corona build was based on Lua 5.1 so I'm not sure why the Corona build fails to work correctly.

Tom

myfogview
User offline. Last seen 2 weeks 5 days ago. Offline
Joined: 14 Apr 2010

Here is the code. With the second line commented out, it shows the same number every time in the Simulator/terminal (99).

1
2
3
4
math.randomseed(os.time())
--dummy = math.random(0,255)
a = math.random(150)
print(a)

Tom

Hasufel
User offline. Last seen 1 year 22 weeks ago. Offline
Joined: 12 Apr 2010

Seen while digging the random "problem" on mac osx:

"Lua's random uses C's rand and srand functions.
The C90 standard defines the precise implementation of rand and srand,
and this algorithm isn't the best.
It especially lacks randomness in the lower bits.

Some platforms like Linux changed the implementation of rand to an
intentionally non-conforming, and better, implementation (e.g. random(3)).
OS/X remains true to the standard rand implementation, and Lua inherits it."

I ran into the "problem" too. The simulator on lua.org executes the code you type on a linux machine, hence bypassing our osx platform behavior.

"Lua on mac osx 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 on mac osx,
the low-bit difference vanishes and you see the same integer result."

Here is what I am using to bypass the "same number always" oddity (works ok but not the best):

1
2
3
4
5
6
7
8
9
10
11
local _seed = os.time()
local function getRandom(f,c)
        _seed = _seed + 1
        math.randomseed(_seed)
        math.random()
        local a = math.random(f,c)
        _seed = _seed + a
        return (a)      
end
--get a random integer between 1 and 10
print (getRandom(1,10))

Maybe Ansca would work on that ? Quite annoying, indeed :)

s.w.powers
User offline. Last seen 1 year 4 weeks ago. Offline
Joined: 16 Mar 2010

Hasufel,

There is absolutely no need to re-seed like that. It actually makes your random numbers *less* random. I posted about this in a different thread when we were discussing the original issue a while back, but here's the short version:

1) Rand is an algorithm. It generates pseudo random numbers based on the seed given it.
2) Each time you feed it a different seed, you restart the random algorithm itself, in effect, you are taking the first number in a random sequence each time you call your "getRandom" function. This is not how the algorithm is intended to work and by doing it this way you actually make things less random.
3) The workaround is exactly as Mike posted. You seed once at the start of your app (with os.time()), then you immediately follow that with a dummy call to math.random(). From that point forward, you will get the correct random numbers.

The only time you should want to "re-seed" is if you are wanting to run the same sequence. This is often desirable to reproduce the same path previously. For instance, if you had a game where the setup was based on random numbers (like a sudoko or something), if you save the seed you use to create the board, then you can regenerate that board again just by setting the seed to the same number. The only gotcha is if you change any of the code so you don't utilize the random numbers in the same way.

At any rate, the point is, don't re-seed, that's a bad practice and totally unnecessary. Seed once, make a dummy math.random call, and you're good to go.

Scott

Hasufel
User offline. Last seen 1 year 22 weeks ago. Offline
Joined: 12 Apr 2010

Thanks Scott for helping out.
I knew my trick was awful: I found it odd.
It works like a charm as Mike posted.
My bad !
Thank you :)

MikeHart
User offline. Last seen 2 hours 46 min ago. Offline
Joined: 22 Mar 2010

No problem. This oddity about math.random should be mentioned inside the App Programming Guide in big bold letters :-)

d3mac123
User is online Online
Joined: 12 Feb 2010

My friends, fact is, no matter I call the dummy or not (and I am calling), first number in the device is always the same. do you have any tested code showing how to get a new number in the device?
thanks!

s.w.powers
User offline. Last seen 1 year 4 weeks ago. Offline
Joined: 16 Mar 2010

1
2
3
4
5
6
math.randomseed(os.time());
math.random();
 
for i = 1, 10 do
    print(i..") "..math.random());
end

Every time I reload I get different numbers for all 10.

Simple tests like this put at the top of your main.lua can easily show you if you are making a mistake in your code or if it's an issue with lua.

Scott

d3mac123
User is online Online
Joined: 12 Feb 2010

Just tried your code. When you replace your code limiting the numbers in the random function, you will always get 1 as first number:

math.randomseed(os.time());
math.random(10); --considering the final table will have 10 elements

for i = 1, 10 do
print(i..") "..math.random(i));
end

s.w.powers
User offline. Last seen 1 year 4 weeks ago. Offline
Joined: 16 Mar 2010

Trying not to smile too much. :)

That's not how random works.

From lua.org Reference document:
----
math.random ([m [, n]])

This function is an interface to the simple pseudo-random generator function rand provided by ANSI C. (No guarantees can be given for its statistical properties.)

When called without arguments, returns a uniform pseudo-random real number in the range [0,1). When called with an integer number m, math.random returns a uniform pseudo-random integer in the range [1, m]. When called with two integer numbers m and n, math.random returns a uniform pseudo-random integer in the range [m, n].
----

First off, the dummy call is a dummy call. No need to pass anything to it.

Second, here's the loop you ran through:

Loop 1: Give me a random number between 1 and 1.
Loop 2: Give me a random number between 1 and 2.
Loop 3: Give me a random number between 1 and 3.
Loop 4: Give me a random number between 1 and 4.
Loop 5: Give me a random number between 1 and 5.
Loop 6: Give me a random number between 1 and 6.
Loop 7: Give me a random number between 1 and 7.
Loop 8: Give me a random number between 1 and 8.
Loop 9: Give me a random number between 1 and 9.
Loop 10: Give me a random number between 1 and 10.

Take the "i" out of the math.random call and replace it with the range you want. It sounds like you want a number between 1 and 10, so that would be math.random(10).

Scott

d3mac123
User is online Online
Joined: 12 Feb 2010

Scott my friend, this thing is driving me crazy!

I am doing exactly what you are suggested but my list in the device comes always the same.

math.randomseed = ( os.time() )
math.random()
myList = { "alex.jpg","eric.jpg","marina.jpg"}

function selectRandom()
local rand=math.random(#myList)
local tFile = myList[rand]
local background = display.newImage(tFile, 0, 0)
table.remove(myList,rand)
end

selectRandom()

everything works fine in the simulator but, when I run it in the device for the first time, it keeps showing the same list. For example, if the first time it built the random list as {1,2,1}, meaning {alex, marina, eric}, if i leave the app and run it again, "alex" will appear first, then "marina", then "Eric" - it never refresh the random list.

Alex

s.w.powers
User offline. Last seen 1 year 4 weeks ago. Offline
Joined: 16 Mar 2010

Well, there's a syntax error in the code you put here, but here's what I ran... it differs only in that it displays a text string instead of your image:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
math.randomseed(os.time());
math.random();
 
myList = {
        "alex.jpg",
        "eric.jpg",
        "marina.jpg",
};
textY = 20;
 
function selectRandom()
        local rand = math.random(#myList);
        local tFile = myList[rand];
        local nt = display.newText(tFile, 20, textY, nil, 12);
        textY = textY + 20;
        nt:setTextColor(255, 255, 255);
        table.remove(myList, rand);
end
 
selectRandom();
selectRandom();
selectRandom();

You must remember, this is a very small sample of images. Your chances are 1 in 3 of always getting 1. That never changes no matter how many times you run this app. You always have a 33% chance to get 1 as you first number.

I did want to complement you on your method for not getting a recurring image. :)

At any rate, the code works. You will get different starting numbers. But you'll also get repeats.

Yes, the results were from running it on my iPhone as well as on the simulator.

Scott

d3mac123
User is online Online
Joined: 12 Feb 2010

Scott,

1) thanks for spending time here trying to help me;
2) i couldn't find the sintax error in the code I posted, as you mentioned. what have i missed?
3) my original table has more than 130 images. even with 130 elements in the table, the same list returns all the time;
5) to avoid this problem (which seems unsolved to me), I move my data to SQLite (thanks Asca for that!) and I am getting the Random() directly from SQL. Problem now is the code works perfect in the simulator but in the device, it is only returning the first record. Am I paying my sins with random functions? :)

I will try to solve both scenarios again.
Lastly, how can you format your code in these forums?

Thanks again,
Alex

s.w.powers
User offline. Last seen 1 year 4 weeks ago. Offline
Joined: 16 Mar 2010

No problem, Alex. I've no problem helping folks who are honestly giving it a good try before just coming here and asking for folks to write it for them. :)

1
math.randomseed = ( os.time() )

Should be:

1
math.randomseed( os.time() )

You use <code> and </code> around your code block.

If you really do have the above error in your code, then it could be the culprit.

With a sample set of 130 elements, something else is wrong.

Did you run my code above? If I had to guess, you've got a logic error somewhere in how you're getting your random element.

Bottom line, if you take the code I posted previously and run it (simulator and on your iphone) you'll see the random functionality working. With only 3 elements you *do* get the same list sometimes, but if you run it 5-10 times you'll see you get different lists.

Just like if you take the code I posted previously which generates 10 random numbers you'll see that works exactly as it's supposed to.

I advise you take the code posted here and try it out in a separate project, then go back and look at your code again and figure out what you're doing wrong.

Scott

Viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.