Skip to content

Commit bef50ba

Browse files
committed
fix(shooter): replace early-exit GOTOs with sentinel flags
rgc-basic's GOTO doesn't unwind FOR / IF / WHILE stacks when jumping out of a block. Each GOTO from inside a nested IF leaked if_depth + for_top counters; after ~16 frames the inner enemy / bullet spawn loops tripped MAX_IF_DEPTH and the program halted with "IF nesting too deep". Replaces all four early-exit GOTOs (BulletSpawned, EnemySpawned, HitDone, PlayerHitDone) with PB_DONE / EN_DONE / HIT_DONE / P_HIT_DONE sentinel flags that gate the remaining loop iterations without bypassing END IF / NEXT. Underlying basic.c GOTO bug remains — file separately. Sentinel flags are the recommended idiom for now.
1 parent c167ba9 commit bef50ba

1 file changed

Lines changed: 31 additions & 31 deletions

File tree

examples/shooter/shooter.bas

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,18 @@ DO
9292

9393
FIRE = KEYDOWN(KSPACE)
9494
IF FIRE = 1 AND PREV_FIRE = 0 THEN
95-
' Find a free bullet slot.
95+
' Find a free bullet slot. Sentinel instead of GOTO because
96+
' rgc-basic's GOTO doesn't unwind FOR/IF nesting and would
97+
' leak if_depth across frames.
98+
PB_DONE = 0
9699
FOR PBI = 0 TO PB_MAX - 1
97-
IF PB_ACTIVE(PBI) = 0 THEN
100+
IF PB_ACTIVE(PBI) = 0 AND PB_DONE = 0 THEN
98101
PB_X(PBI) = PX + 12
99102
PB_Y(PBI) = PY - 16
100103
PB_ACTIVE(PBI) = 1
101-
GOTO BulletSpawned
104+
PB_DONE = 1
102105
END IF
103106
NEXT PBI
104-
BulletSpawned:
105107
END IF
106108
PREV_FIRE = FIRE
107109
END IF
@@ -126,29 +128,27 @@ DO
126128

127129
' --- spawn enemies entering view ---
128130
FOR OI = 1 TO MAP_OBJ_COUNT - 1
129-
IF SPAWNED(OI) = 0 THEN
130-
IF MAP_OBJ_TYPE$(OI) = "enemy" THEN
131-
IF MAP_OBJ_Y(OI) >= CAM_Y - 32 AND MAP_OBJ_Y(OI) <= CAM_Y + VIEW_H THEN
132-
FOR EJ = 0 TO EN_MAX - 1
133-
IF EN_ACTIVE(EJ) = 0 THEN
134-
EN_X(EJ) = MAP_OBJ_X(OI)
135-
EN_Y(EJ) = MAP_OBJ_Y(OI)
136-
EN_KIND$(EJ) = MAP_OBJ_KIND$(OI)
137-
EN_HP(EJ) = 1
138-
IF EN_KIND$(EJ) = "tank" THEN
139-
EN_FRAME(EJ) = 1
140-
ELSE
141-
EN_FRAME(EJ) = 1
142-
END IF
143-
EN_ACTIVE(EJ) = 1
144-
SPAWNED(OI) = 1
145-
GOTO EnemySpawned
146-
END IF
147-
NEXT EJ
148-
EnemySpawned:
149-
END IF
131+
SP_TRIG = 0
132+
IF SPAWNED(OI) = 0 AND MAP_OBJ_TYPE$(OI) = "enemy" THEN
133+
IF MAP_OBJ_Y(OI) >= CAM_Y - 32 AND MAP_OBJ_Y(OI) <= CAM_Y + VIEW_H THEN
134+
SP_TRIG = 1
150135
END IF
151136
END IF
137+
IF SP_TRIG = 1 THEN
138+
EN_DONE = 0
139+
FOR EJ = 0 TO EN_MAX - 1
140+
IF EN_ACTIVE(EJ) = 0 AND EN_DONE = 0 THEN
141+
EN_X(EJ) = MAP_OBJ_X(OI)
142+
EN_Y(EJ) = MAP_OBJ_Y(OI)
143+
EN_KIND$(EJ) = MAP_OBJ_KIND$(OI)
144+
EN_HP(EJ) = 1
145+
EN_FRAME(EJ) = 1
146+
EN_ACTIVE(EJ) = 1
147+
SPAWNED(OI) = 1
148+
EN_DONE = 1
149+
END IF
150+
NEXT EJ
151+
END IF
152152
NEXT OI
153153

154154
' --- update enemies (despawn off bottom of view) ---
@@ -163,8 +163,9 @@ DO
163163
IF PB_ACTIVE(PBI) = 1 THEN
164164
BX = PB_X(PBI)
165165
BY = PB_Y(PBI)
166+
HIT_DONE = 0
166167
FOR EI = 0 TO EN_MAX - 1
167-
IF EN_ACTIVE(EI) = 1 THEN
168+
IF EN_ACTIVE(EI) = 1 AND HIT_DONE = 0 THEN
168169
ESX = EN_X(EI)
169170
ESY = EN_Y(EI) - CAM_Y
170171
IF BX + 8 >= ESX AND BX <= ESX + 32 AND BY + 16 >= ESY AND BY <= ESY + 32 THEN
@@ -174,18 +175,18 @@ DO
174175
EN_ACTIVE(EI) = 0
175176
SCORE = SCORE + 100
176177
END IF
177-
GOTO HitDone
178+
HIT_DONE = 1
178179
END IF
179180
END IF
180181
NEXT EI
181-
HitDone:
182182
END IF
183183
NEXT PBI
184184

185185
' --- player vs enemy collision ---
186186
IF PALIVE = 1 THEN
187+
P_HIT_DONE = 0
187188
FOR EI = 0 TO EN_MAX - 1
188-
IF EN_ACTIVE(EI) = 1 THEN
189+
IF EN_ACTIVE(EI) = 1 AND P_HIT_DONE = 0 THEN
189190
ESX = EN_X(EI)
190191
ESY = EN_Y(EI) - CAM_Y
191192
IF PX + 32 >= ESX AND PX <= ESX + 32 AND PY + 32 >= ESY AND PY <= ESY + 32 THEN
@@ -195,11 +196,10 @@ DO
195196
PALIVE = 0
196197
GAME_OVER = 1
197198
END IF
198-
GOTO PlayerHitDone
199+
P_HIT_DONE = 1
199200
END IF
200201
END IF
201202
NEXT EI
202-
PlayerHitDone:
203203
END IF
204204

205205
' --- player vs solid bg tile ---

0 commit comments

Comments
 (0)