Without delay cycle is endless, why?

In some function I have code:

while eNum \<= 5 do math.randomseed( os.time() )&nbsp; local i = math.random (1 , 10) local j = math.random (1 , 10) if not enemyTab[i][j].hasSph then enemyTab[i][j].hasSph = 1 local enemySph = display.newImageRect( mainGroup, objectSheet, 9, 50, 50 ) enemySph.x = enemyTab[i][j].x enemySph.y = enemyTab[i][j].y&nbsp;&nbsp; eNum = eNum + 1&nbsp;&nbsp; wait(3) else&nbsp; eNum = eNum - 1&nbsp; &nbsp;&nbsp; wait(3) end end

It works fine with wait function which is:

function wait(waitTime) &nbsp; &nbsp; timerOS = os.time() &nbsp; &nbsp; repeat&nbsp; &nbsp; &nbsp; until os.time() \> timerOS + waitTime end

But if I cooment line wait(3) cycle become endless and eNum is negative number (rising all the time).

Can’t understand where my mistake?

Loops run until they run their course or are cancelled. Since your condition is while eNum is less than or equal to 5 , your loop will run until that is no longer true.

This brings us to this line of code here:

if not enemyTab[i][j].hasSph then

If this condition is not true when the loop runs the first time, then your loop will jump to the else clause. Since the engine is single-threaded, it’ll keep running that loop until it is told to stop, but since the condition above can never become true and your condition for stopping the loop can never become true either as you only keep reducing the value of eNum, the loop will never stop.

If you need to run something like this every frame, and you don’t want to freeze everything else in case your condition isn’t met, then you can implement a timer that runs every frame, see https://docs.coronalabs.com/api/library/timer/performWithDelay.html

Loops run until they run their course or are cancelled. Since your condition is while eNum is less than or equal to 5 , your loop will run until that is no longer true.

This brings us to this line of code here:

if not enemyTab[i][j].hasSph then

If this condition is not true when the loop runs the first time, then your loop will jump to the else clause. Since the engine is single-threaded, it’ll keep running that loop until it is told to stop, but since the condition above can never become true and your condition for stopping the loop can never become true either as you only keep reducing the value of eNum, the loop will never stop.

If you need to run something like this every frame, and you don’t want to freeze everything else in case your condition isn’t met, then you can implement a timer that runs every frame, see https://docs.coronalabs.com/api/library/timer/performWithDelay.html

At the begining of function local eNum = 0 and all objects in enemyTab table haven’t key hasSph that’s why this is strange. With wait function code is working fine.

About function wait, I want some delay to make illusion that Ai is thinking. So I need some fixed delay (about 2-3 sec for whole cycle).

I tried to use this: 

nopTimer = timer.performWithDelay(1000, nopFunc, 1)

 instead of wait(3) and function nopFunc do nothing but the cycle is endless again. 

I think I understood the mistake when I use 

math.randomseed( os.time() )&nbsp;

there must be some delay for the randomseed initialized with a new number. Os.time should change otherwise 

math.random (1 , 10)&nbsp;

will give the same numbers (cycle is to quick) and eNum will decrease.

So, how can i get 6 random pairs numbers from 1 to 10? Can i use math.random in timer function?

In general, you don’t want to place math.randomseed in more places than one, like when the app first starts. All it does is set the value upon which all future (pseudo)random numbers are created. Since you have it within a loop, os.time won’t change much (if at all).

Still, I would look into reworking that entire loop as it seems problematic.

Also, if you want to fire up functions and pass parameters within timer calls, you can do:

timer.performWithDelay( 500, function() local i, j = math.random(10), math.random(10) myFunction( i, j ) end )

The essense of what you’re trying to do here is wrong:

while eNum \<= 5 do math.randomseed( os.time() ) local i = math.random (1 , 10) local j = math.random (1 , 10) if not enemyTab[i][j].hasSph then enemyTab[i][j].hasSph = 1 local enemySph = display.newImageRect( mainGroup, objectSheet, 9, 50, 50 ) enemySph.x = enemyTab[i][j].x enemySph.y = enemyTab[i][j].y eNum = eNum + 1 wait(3) else eNum = eNum - 1 wait(3) end end

You can’t write blocking code in Corona which is single threaded or your game will hang.

You need to use one of the following:

  • timer.performWithDelay()
  • enterFrame 

I would re-write your code something like this:

math.randomseed( os.time() ) local eNum = 0 local function work() if eNum \> 5 then return end local i = math.random (1 , 10) local j = math.random (1 , 10) if not enemyTab[i][j].hasSph then enemyTab[i][j].hasSph = 1 local enemySph = display.newImageRect( mainGroup, objectSheet, 9, 50, 50 ) enemySph.x = enemyTab[i][j].x enemySph.y = enemyTab[i][j].y eNum = eNum + 1 else eNum = eNum - 1 if(eNum \< 0) then eNum = 0 end end timer.performWithDelay( 3000, work ) end work()

This may not be exactly what you want, but it won’t hang.

Tip, there are better random options for better distributions.  

https://roaminggamer.github.io/RGDocs/pages/SSK2/external/#mersenne-twister

Lastly, if you absolutely insist on writing blocking code, there are ways (Co-routines), but this is really only for experts.  99.999% of the time you can achieve the same goal using other cleaner techniques.

Here is one wait solution:

https://roaminggamer.github.io/RGDocs/pages/SSK2/external/#wait-starcrunch

Thank you all.

This is what I want.

In my shooting function there is some brute force algorithm. I have global boolean variable (playerTurn) and in my game loop function cell property (.used) check occurs. If the cell has already been shelled set the variable (playerTurn) to false so the game loop function selects the next random cell. By the end of the game, when most cells are already fired, delays occur. 

I think to store all possible coordinates (pairs of numbers for matrix 10 x 10) of cells in a one-dimensional array, and randomly select a coordinate from there, and if the cell has already been shelled (has some property .used), delete this element of the array. Is this the right approach?

Yes,  You could use a one-dimensional array to store valid (remaining) entries.  That would be a fairly clean way to do it.