Jump to content
IGNORED

Best way to break out of a For/Next loop?


Recommended Posts

Is this the best way to exit a loop since there is no way to break out?

Some pseudocode:
 

for i = 0 to num_shots

     for j= 0 to num_enemies

          if j collides with i then j = num_enemies

     next

next

 

It appears to work, and save me a ton of cycles (removed a messy stutter), but not sire it' the best way.

Link to comment
Share on other sites

6 minutes ago, fultonbot said:

Is this the best way to exit a loop since there is no way to break out?

Some pseudocode:
 

for i = 0 to num_shots

     for j= 0 to num_enemies

          if j collides with i then j = num_enemies

     next

next

 

It appears to work, and save me a ton of cycles (removed a messy stutter), but not sire it' the best way.

if there's no "break" command, this is the next best way

  • Like 1
Link to comment
Share on other sites

25 minutes ago, Karl G said:

If you don't need to preserve the value of j, then that would work fine for breaking out of the inner for loop. Doing a goto to label after the first "next" would work fine, too. 

 

for i = 0 to num_shots

     for j= 0 to num_enemies

          if j collides with I then goto break_inner_loop

     next

_break_inner_loop

next



With nested loops, will the next after the jump label affect the inner loop or the outer loop if I jump out of the inner loop?

Edited by fultonbot
  • Like 1
Link to comment
Share on other sites

9 hours ago, fultonbot said:

for i = 0 to num_shots

     for j= 0 to num_enemies

          if j collides with I then goto break_inner_loop

     next

_break_inner_loop

next


With nested loops, will the next after the jump label affect the inner loop or the outer loop if I jump out of the inner loop?

Karl is correct. You can just break out of the inner loop with a goto, as you have here. The outer loop "next" won't get confused with the inner loop one.

  • Like 3
Link to comment
Share on other sites

If it works like M$ BASIC does, when the interpreter/compiler encounters the first FOR, it searches forward for the matching NEXT.  That means it also accounts for inner-loop FORs in its search.  Then it notes the location of the FOR and its NEXT as part of an internal state.  This is important to note, because it shows that 1) the NEXT must be "near" the FOR.  You can't have it in a GOSUB routine or behind the FOR.  Also, you can only have one NEXT per FOR.  So you can't have multiple cases that might NEXT themselves back to the FOR.  You just have to GOTO the correct one.

Link to comment
Share on other sites

9 hours ago, ChildOfCv said:

If it works like M$ BASIC does, when the interpreter/compiler encounters the first FOR, it searches forward for the matching NEXT.  That means it also accounts for inner-loop FORs in its search.  Then it notes the location of the FOR and its NEXT as part of an internal state.  This is important to note, because it shows that 1) the NEXT must be "near" the FOR.  You can't have it in a GOSUB routine or behind the FOR.  Also, you can only have one NEXT per FOR.  So you can't have multiple cases that might NEXT themselves back to the FOR.  You just have to GOTO the correct one.

 

Okay, this is good news.  I think it will save my games tons of unused cycles with for/next loops running that are unnecessary.
I already saw a frame-loss "stutter" go away by using this method in a collision loop.  

Link to comment
Share on other sites

If "while" is available, but not "break", (which to my displeasure was the situation in a Pascal class I took only a few years ago) you could do:

for i = 1 to num_shots
    j = 0
    while j <= num_enemies
        if j collides with i then j = num_enemies
        j = j + 1
next i
Edited by Pokeypy
  • Like 1
Link to comment
Share on other sites

Once you're ready to get more advanced, you could also keep the list of shots and enemies sorted by x or y, so that you can do a single-pass loop between the two where shot index and enemy index are advanced only as needed during the compare, so that you reduce the number of comparisons.  Something like:

x010 enemy = 1: enemy2 = 2
x020 if enemy > num_enemies then return
x030 for shot = 1 to num_shots
x040   if shotx(shot) < enemyx(enemy) then x120
x050   if shotx(shot) = enemyx(enemy) then x080
x060   enemy = enemy2
x070   while enemy <= num_enemies and enemyx(enemy) < shotx(shot): enemy = enemy + 1: wend: if enemy > num_enemies then return
x080   for enemy2 = enemy to num_enemies
x090     if enemyx(enemy2) <> shotx(shot) then x120
x100     if enemyy(enemy2) = shoty(shot) then <do collision stuff>
x110   next enemy2
x120 next shot
x130 return

So the idea is that if all the shots are left of the leftmost enemy, you only end up going through one loop.

 

If a shot is in the same horizontal plane with an enemy, compare all enemies in that plane.  If a shot is to the right of the current leftmost enemy, choose the first enemy to the right of that one which is in the same plane or to the right.

 

This (minus any bugs this back of the napkin loop might have) would reduce the number of comparisons from strict n^2 order to smaller pockets of n^2, but trending toward single pass.

  • Like 2
Link to comment
Share on other sites

On 6/7/2021 at 1:03 PM, ChildOfCv said:

Once you're ready to get more advanced, you could also keep the list of shots and enemies sorted by x or y, so that you can do a single-pass loop between the two where shot index and enemy index are advanced only as needed during the compare, so that you reduce the number of comparisons.  Something like:


x010 enemy = 1: enemy2 = 2
x020 if enemy > num_enemies then return
x030 for shot = 1 to num_shots
x040   if shotx(shot) < enemyx(enemy) then x120
x050   if shotx(shot) = enemyx(enemy) then x080
x060   enemy = enemy2
x070   while enemy <= num_enemies and enemyx(enemy) < shotx(shot): enemy = enemy + 1: wend: if enemy > num_enemies then return
x080   for enemy2 = enemy to num_enemies
x090     if enemyx(enemy2) <> shotx(shot) then x120
x100     if enemyy(enemy2) = shoty(shot) then <do collision stuff>
x110   next enemy2
x120 next shot
x130 return

So the idea is that if all the shots are left of the leftmost enemy, you only end up going through one loop.

 

If a shot is in the same horizontal plane with an enemy, compare all enemies in that plane.  If a shot is to the right of the current leftmost enemy, choose the first enemy to the right of that one which is in the same plane or to the right.

 

This (minus any bugs this back of the napkin loop might have) would reduce the number of comparisons from strict n^2 order to smaller pockets of n^2, but trending toward single pass.

Oh, I like this!
I do some Y locations checks right now to only do collisions is they could possibly be in the same zone (it's a vertical shooter), but I do not resort the objects in a single display list.  I will need to take a look a this closer.

Link to comment
Share on other sites

On 6/7/2021 at 7:35 AM, Pokeypy said:

If "while" is available, but not "break", (which to my displeasure was the situation in a Pascal class I took only a few years ago) you could do:


for i = 1 to num_shots
    j = 0
    while j <= num_enemies
        if j collides with i then j = num_enemies
        j = j + 1
next i

There is no while loop in 7800 Basic.  You must simulate it with goto, or just use for/next.

  • Like 1
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...