+cmadruga Posted March 14, 2020 Share Posted March 14, 2020 Quick question... having a GOTO jump to a label outside a procedure creates a stack disruption error on Intybasic. What is the best way to avoid this situation if the jump is really needed? I tend to use variables that get flagged inside the procedure... so once I'm back to the main loop the variable will trigger the GOTO I need. Are there better ways to deal with this? I'm sure there are. Please enlighten me. Quote Link to comment Share on other sites More sharing options...
artrag Posted March 14, 2020 Share Posted March 14, 2020 This can happen for a bad design choice in the flow of your program Probably you should use a return instruction or not have a subroutine for that code Quote Link to comment Share on other sites More sharing options...
+nanochess Posted March 15, 2020 Share Posted March 15, 2020 The easiest way is to use a flag variable. The error message comes from the fact that jumping to a PROCEDURE (subroutine) inserts extra information into the stack, so on return it would crash. Quote Link to comment Share on other sites More sharing options...
+cmadruga Posted March 15, 2020 Author Share Posted March 15, 2020 (edited) Flag variable? Ok I guess I’m already doing that, thanks for confirming. To Artrag’s comments, yes sometimes it is better not to use subroutines... but I have this impulse to leave the main loop as clean as possible... don’t know where that comes from, probably the way I was taught structured/procedural programming decades ago. Edited March 15, 2020 by cmadruga Quote Link to comment Share on other sites More sharing options...
artrag Posted March 15, 2020 Share Posted March 15, 2020 If the goto jumps outside the subroutine you could have to change the structure of your program Quote Link to comment Share on other sites More sharing options...
+Tarzilla Posted March 15, 2020 Share Posted March 15, 2020 On 3/14/2020 at 8:58 AM, cmadruga said: Quick question... having a GOTO jump to a label outside a procedure creates a stack disruption error on Intybasic. What is the best way to avoid this situation if the jump is really needed? I tend to use variables that get flagged inside the procedure... so once I'm back to the main loop the variable will trigger the GOTO I need. Are there better ways to deal with this? I'm sure there are. Please enlighten me. Some Structured Programmers would say GOTOs are forbidden, I rarely use them in IntyBasic but I use a lot of GOSUBs (which made me chuckle way too much while I was writing the SuperPro Gosub game ) Your "yes sometimes it is better not to use subroutines" doesn't make sense to me as it isn't the subroutines that are the issue, it is you GOTOing into one instead of GOSUBing. If your subroutine has a lot of labels that you are jumping to, then make the parts of the subroutine small PROCEDUREs and GOSUB to them, a RETURN (or END of the PROCEDURE) will clear the stack properly on exit from the PROCEDURE I use variations of this: WhichCritter=0 MainLoop: MovePlayer MoveCritters WhichCritter=WhichCritter+1:If WhichCritter>2 then WhichCritter=0 Goto MainLoop MoveCritters: Procedure On WhichCritter Gosub MoveSnake,MovePig,MoveBird End MoveSnake:Procedure Rem Do something End MovePig:Procedure Rem Do something End MoveBird:Procedure Rem Do something End Alternate with GOTO inside the Procedure instead of Gosubs MoveCritters: Procedure On WhichCritter Goto MoveSnake,MovePig,MoveBird MoveSnake: rem do something Return MovePig: rem do something Return MoveBird: rem do something Return End Quote Link to comment Share on other sites More sharing options...
+cmadruga Posted March 15, 2020 Author Share Posted March 15, 2020 (edited) I think my comment was misunderstood. I don't use a lot of GOTOs and I'm not generally replacing GOSUBs by them. The type of situation I'm talking about is this... how would you trigger a new level to be restarted? Suppose any "dead" condition should decrement LIFE immediately and restart the level. Start_level: CLS <initialize variables, etc> main_loop: <do a lot of stuff> IF (FRAME AND 3)=0 THEN GOSUB check_sprite_and_tile_collision <do more stuff> IF (FRAME AND 7)=0 THEN GOSUB check_for_other_death_situations <do a lot more stuff> GOTO main_loop Check_sprite_and_tile_collision: PROCEDURE <if sprite touched a particular tile: dead> END Check_for_other_death_situations: PROCEDURE <if condition: dead> END Edited March 15, 2020 by cmadruga Quote Link to comment Share on other sites More sharing options...
Kiwi Posted March 15, 2020 Share Posted March 15, 2020 For Coleco stuff, I use while(game==1){} Then event to occur below it if(game==2){...;} or/and while(game==2){} if I need an animation to play like death animation. additional cases like if(game==3){if you won etc.} So I use goto to send the pointer up to resetgame or resetlevel labels. I probably should do the same with my Inty stuff. I use goto and use flags if I'm using subroutines in Mad Bomer. I used to do the same with my older Coleco project before I figured out how to use arguments properly. Mad Bomber exempt: gameloop1: ... gosub dropbombs if droptimer=0 then droptimer=bombrate:gosub spawnbombs if bomberbombs=0 and game=1 then game=0:bomberpause=100 if hitflflag=1 then goto bombhitfloor ... goto gameloop1 dropbombs:procedure for i=0 to 4 if bomba(i)=1 then if dropspeed<>0 then ... if bomby(i)>100 then hitflflag=1 if bomby(i)<5 then bomby(i)=6 next i return end At late development point, Mad Bomber was going to have stack overflow if I haven't noticed that I was jumping out of the lives procedure into the game over sequence. Quote Link to comment Share on other sites More sharing options...
+Tarzilla Posted March 15, 2020 Share Posted March 15, 2020 (edited) 6 hours ago, cmadruga said: I think my comment was misunderstood. I don't use a lot of GOTOs and I'm not generally replacing GOSUBs by them. The type of situation I'm talking about is this... how would you trigger a new level to be restarted? Suppose any "dead" condition should decrement LIFE immediately and restart the level. Start_level: CLS <initialize variables, etc> main_loop: <do a lot of stuff> IF (FRAME AND 3)=0 THEN GOSUB check_sprite_and_tile_collision <do more stuff> IF (FRAME AND 7)=0 THEN GOSUB check_for_other_death_situations <do a lot more stuff> GOTO main_loop Check_sprite_and_tile_collision: PROCEDURE <if sprite touched a particular tile: dead> END Check_for_other_death_situations: PROCEDURE <if condition: dead> END I actually do something more like below You could also use the DO WHILE PlayerDead=0 construct instead of a Main_Loop: CartLoop: Gosub MainMenu Gosub MainGame Goto CartLoop MainGame: Start_level: CLS <initialize variables, etc> Restart_Level: Gosub DrawLevelScreen PlayerDead=0 main_loop: <do a lot of stuff> IF (FRAME AND 3)=0 THEN GOSUB check_sprite_and_tile_collision <do more stuff> IF (FRAME AND 7)=0 THEN GOSUB check_for_other_death_situations <do a lot more stuff> If Lives<=0 then Gosub GameOverScreen:Return Rem Exits MainGame Procedure gracefully back to cartloop If PlayerDead=1 then GOTO RestartLevel GOTO main_loop End Rem End of MainGame Procedures Check_sprite_and_tile_collision: PROCEDURE <if sprite touched a particular tile then PlayerDead=1:Lives=Lives-1> END Edited March 16, 2020 by Tarzilla Fixed Lives <=0 Quote Link to comment Share on other sites More sharing options...
+cmadruga Posted March 16, 2020 Author Share Posted March 16, 2020 5 hours ago, Tarzilla said: I actually do something more like below You could also use the DO WHILE PlayerDead=0 construct instead of a Main_Loop: CartLoop: Gosub MainMenu Gosub MainGame Goto CartLoop MainGame: Start_level: CLS <initialize variables, etc> Restart_Level: Gosub DrawLevelScreen PlayerDead=0 main_loop: <do a lot of stuff> IF (FRAME AND 3)=0 THEN GOSUB check_sprite_and_tile_collision <do more stuff> IF (FRAME AND 7)=0 THEN GOSUB check_for_other_death_situations <do a lot more stuff> If Lives<=0 then Gosub GameOverScreen:Return Rem Exits MainGame Procedure gracefully back to cartloop If PlayerDead=1 then GOTO RestartLevel GOTO main_loop End Rem End of MainGame Procedures Check_sprite_and_tile_collision: PROCEDURE <if sprite touched a particular tile then PlayerDead=1:Lives=Lives-1> END Yep, that's what I do too. Like I said on my first post: "I tend to use variables that get flagged inside the procedure... so once I'm back to the main loop the variable will trigger the GOTO I need." And like nanochess said: "The easiest way is to use a flag variable." ... Which you did as well with the variable PlayerDead. Thanks for confirming... was just trying to see if there were other ways to deal with it. ? Quote Link to comment Share on other sites More sharing options...
+cmadruga Posted March 16, 2020 Author Share Posted March 16, 2020 5 hours ago, Kiwi said: For Coleco stuff, I use while(game==1){} Then event to occur below it if(game==2){...;} or/and while(game==2){} if I need an animation to play like death animation. additional cases like if(game==3){if you won etc.} So I use goto to send the pointer up to resetgame or resetlevel labels. I probably should do the same with my Inty stuff. I use goto and use flags if I'm using subroutines in Mad Bomer. I used to do the same with my older Coleco project before I figured out how to use arguments properly. Mad Bomber exempt: gameloop1: ... gosub dropbombs if droptimer=0 then droptimer=bombrate:gosub spawnbombs if bomberbombs=0 and game=1 then game=0:bomberpause=100 if hitflflag=1 then goto bombhitfloor ... goto gameloop1 dropbombs:procedure for i=0 to 4 if bomba(i)=1 then if dropspeed<>0 then ... if bomby(i)>100 then hitflflag=1 if bomby(i)<5 then bomby(i)=6 next i return end At late development point, Mad Bomber was going to have stack overflow if I haven't noticed that I was jumping out of the lives procedure into the game over sequence. Yep, similar to Tarzilla, you are using a flag variable ("hitflflag") to do the GOTO from the main loop versus inside the procedure ("dropbombs"). (I didn't quite get the use of "game=1" and "game=0", but probably because I would need to read a little more of your code.) Thanks guys! 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.