Flee and Die
Add the flee option in combat and handle player death — the stakes are real.
Not every fight is worth finishing. Sometimes the player is too weak, too low on HP, or facing something too powerful. The flee option gives them a way out — but at a cost. Fleeing has a 50% chance of failure, and a failed attempt gives the monster a free attack. Death is also real now: HP reaching 0 ends the game and shows a summary of how far the player got.
The Program
5 REM === DUNGEONS OF DORIN ===
10 BORDER 0: PAPER 0: INK 7: CLS
20 PRINT AT 3, 4; INK 7; BRIGHT 1; "DUNGEONS OF DORIN"
30 PRINT AT 6, 2; INK 6; "Descend ten floors of"
35 PRINT AT 7, 2; INK 6; "darkness. Find the Heart."
40 PRINT AT 10, 2; INK 7; "Q/A = up/down"
42 PRINT AT 11, 2; INK 7; "O/P = left/right"
44 PRINT AT 14, 2; INK 7; "Press any key to begin"
50 PAUSE 0
60 CLS
70 REM === define stats ===
80 LET h = 20: LET z = 20: LET a = 3: LET f = 2
82 LET g = 0: LET e = 1: LET q = 0
84 DIM d(16,16): DIM v(16,16)
86 DIM j(5): DIM k(5): DIM l(5): DIM n(5)
90 REM === generate floor ===
92 GO SUB 1000
94 LET x = u(1,1) + 1: LET y = u(1,2) + 1
96 LET t = u(s,1) + 1: LET t2 = u(s,2) + 1
98 IF t >= 1 AND t <= 16 AND t2 >= 1 AND t2 <= 16 THEN LET d(t2,t) = 2
100 LET t = INT (RND * 3) + 2
102 IF t > 5 THEN LET t = 5
104 LET m = t
106 FOR i = 1 TO m
108 GO SUB 1600
110 LET j(i) = t: LET k(i) = t2
112 LET l(i) = 1: LET n(i) = 4
114 NEXT i
116 GO SUB 380
118 CLS
120 GO SUB 300
122 GO SUB 500
124 REM === main loop ===
126 PAUSE 0: LET i$ = INKEY$
128 LET t = x: LET t2 = y
130 IF i$ = "q" OR i$ = "Q" THEN LET t2 = y - 1
132 IF i$ = "a" OR i$ = "A" THEN LET t2 = y + 1
134 IF i$ = "o" OR i$ = "O" THEN LET t = x - 1
136 IF i$ = "p" OR i$ = "P" THEN LET t = x + 1
138 IF t = x AND t2 = y THEN GO TO 124
140 IF t < 1 OR t > 16 OR t2 < 1 OR t2 > 16 THEN GO TO 124
142 IF d(t2,t) = 1 THEN GO TO 124
144 REM check monster collision
146 FOR c = 1 TO m
148 IF j(c) = t AND k(c) = t2 AND n(c) > 0 THEN LET i = c: GO SUB 800: GO TO 160
150 NEXT c
152 LET x = t: LET y = t2
154 IF d(y,x) = 2 THEN GO SUB 600: GO TO 124
156 GO SUB 380
160 GO SUB 300
162 GO SUB 500
164 GO TO 124
300 REM === draw viewport ===
302 FOR c = -3 TO 3
304 FOR o = -3 TO 3
306 LET t = x + o: LET t2 = y + c
308 LET i = 1: LET i2 = 0
310 IF t < 1 OR t > 16 OR t2 < 1 OR t2 > 16 THEN GO TO 340
312 IF v(t2,t) = 0 THEN GO TO 340
314 LET i = d(t2,t)
316 LET i2 = 7
318 IF i = 1 THEN LET i2 = 4
320 FOR s = 1 TO m
322 IF j(s) = t AND k(s) = t2 AND n(s) > 0 THEN LET i2 = 2: LET i = 5
324 NEXT s
340 LET t3 = 3 + c: LET t4 = 11 + o
342 IF o = 0 AND c = 0 THEN LET i2 = 7: LET i = 6
344 IF i2 = 0 THEN PRINT AT t3, t4; " ": GO TO 370
346 IF i = 0 THEN PRINT AT t3, t4; INK i2; ".": GO TO 370
348 IF i = 1 THEN PRINT AT t3, t4; INK i2; CHR$ 143: GO TO 370
350 IF i = 2 THEN PRINT AT t3, t4; INK i2; ">": GO TO 370
352 IF i = 5 THEN PRINT AT t3, t4; INK i2; "M": GO TO 370
354 IF i = 6 THEN PRINT AT t3, t4; INK i2; "@": GO TO 370
356 PRINT AT t3, t4; INK i2; "?"
370 NEXT o: NEXT c
372 RETURN
380 REM === update visibility ===
382 FOR c = y - 2 TO y + 2
384 FOR o = x - 2 TO x + 2
386 IF c >= 1 AND c <= 16 AND o >= 1 AND o <= 16 THEN LET v(c,o) = 1
388 NEXT o: NEXT c
390 RETURN
500 REM === draw status ===
502 PRINT AT 8, 2; INK 7; "HP:"; h; "/"; z; " "
504 PRINT AT 9, 2; INK 4; "AT:"; a; " "
506 PRINT AT 10, 2; INK 5; "DF:"; f; " "
508 PRINT AT 8, 20; INK 6; "FL:"; e; " "
510 PRINT AT 9, 20; INK 6; "AU:"; g; " "
514 RETURN
600 REM === stairs down ===
602 LET e = e + 1
604 IF e > 10 THEN GO TO 1100
606 PRINT AT 12, 5; INK 7; BRIGHT 1; "DESCENDING..."
608 PAUSE 30
610 GO TO 90
800 REM === combat ===
802 LET i5 = l(i)
804 RESTORE 1500
806 FOR c = 1 TO i5 - 1: READ i$, t, t2, t3, t4: NEXT c
808 READ i$, t, t2, t3, t4
810 LET i4 = n(i)
812 CLS
814 PRINT AT 0, 0; INK 2; BRIGHT 1; "COMBAT: "; i$
816 PRINT AT 2, 0; INK 7; "Your HP: "; h; " Enemy HP: "; i4
820 REM combat loop
822 PRINT AT 5, 0; INK 7; "A)ttack F)lee"
824 PAUSE 0: LET i$ = INKEY$
826 IF i$ = "f" OR i$ = "F" THEN GO TO 870
828 IF i$ <> "a" AND i$ <> "A" THEN GO TO 824
830 REM player attacks
832 LET c = INT (RND * 6) + 1 + a - t3
834 IF c < 1 THEN LET c = 1
836 LET i4 = i4 - c
838 PRINT AT 8, 0; INK 4; "You hit for "; c; "! "
840 IF i4 <= 0 THEN GO TO 890
842 REM monster attacks
844 LET c = INT (RND * 6) + 1 + t2 - f
846 IF c < 1 THEN LET c = 1
848 LET h = h - c
850 PRINT AT 10, 0; INK 2; "Enemy hits for "; c; "! "
852 IF h <= 0 THEN GO TO 1200
854 PRINT AT 2, 0; INK 7; "Your HP: "; h; " Enemy HP: "; i4; " "
856 PAUSE 20
858 GO TO 820
870 REM flee
872 IF RND > 0.5 THEN PRINT AT 8, 0; INK 6; "You escape! ": PAUSE 20: CLS: RETURN
874 PRINT AT 8, 0; INK 2; "Cannot flee! "
876 LET c = INT (RND * 6) + 1 + t2 - f
878 IF c < 1 THEN LET c = 1
880 LET h = h - c
882 PRINT AT 10, 0; INK 2; "Hit for "; c; "! "
884 IF h <= 0 THEN GO TO 1200
886 PAUSE 20
888 GO TO 820
890 REM enemy defeated
892 PRINT AT 12, 0; INK 4; BRIGHT 1; "VICTORY!"
894 LET n(i) = 0
896 LET g = g + t4: LET q = q + 1
898 PRINT AT 14, 0; INK 6; "Gained "; t4; " gold"
900 PAUSE 30
902 CLS
904 RETURN
1000 REM === generate floor subroutine ===
1002 FOR i = 1 TO 16: FOR o = 1 TO 16
1004 LET d(i,o) = 1: LET v(i,o) = 0
1006 NEXT o: NEXT i
1010 LET s = INT (RND * 3) + 3
1012 DIM u(5,4)
1014 FOR i = 1 TO s
1016 LET u(i,1) = INT (RND * 10) + 2
1018 LET u(i,2) = INT (RND * 10) + 2
1020 LET u(i,3) = INT (RND * 4) + 3
1022 LET u(i,4) = INT (RND * 4) + 3
1024 FOR c = u(i,2) TO u(i,2) + u(i,4) - 1
1026 FOR o = u(i,1) TO u(i,1) + u(i,3) - 1
1028 IF c >= 1 AND c <= 16 AND o >= 1 AND o <= 16 THEN LET d(c,o) = 0
1030 NEXT o: NEXT c
1032 NEXT i
1034 FOR i = 1 TO s - 1
1036 LET t = u(i,1) + INT (u(i,3) / 2)
1038 LET t2 = u(i,2) + INT (u(i,4) / 2)
1040 LET t3 = u(i+1,1) + INT (u(i+1,3) / 2)
1042 LET t4 = u(i+1,2) + INT (u(i+1,4) / 2)
1044 IF t <= t3 THEN FOR o = t TO t3: IF t2 >= 1 AND t2 <= 16 AND o >= 1 AND o <= 16 THEN LET d(t2,o) = 0
1046 IF t <= t3 THEN NEXT o
1048 IF t > t3 THEN FOR o = t3 TO t: IF t2 >= 1 AND t2 <= 16 AND o >= 1 AND o <= 16 THEN LET d(t2,o) = 0
1050 IF t > t3 THEN NEXT o
1052 IF t2 <= t4 THEN FOR c = t2 TO t4: IF c >= 1 AND c <= 16 AND t3 >= 1 AND t3 <= 16 THEN LET d(c,t3) = 0
1054 IF t2 <= t4 THEN NEXT c
1056 IF t2 > t4 THEN FOR c = t4 TO t2: IF c >= 1 AND c <= 16 AND t3 >= 1 AND t3 <= 16 THEN LET d(c,t3) = 0
1058 IF t2 > t4 THEN NEXT c
1060 NEXT i
1062 RETURN
1100 REM === victory (placeholder) ===
1102 CLS
1104 PRINT AT 8, 4; INK 7; BRIGHT 1; "YOU FOUND THE HEART!"
1106 PRINT AT 12, 6; INK 7; "Press any key"
1108 PAUSE 0
1110 GO TO 10
1200 REM === death ===
1202 CLS
1204 PRINT AT 6, 6; INK 2; BRIGHT 1; "YOU HAVE FALLEN"
1206 PRINT AT 8, 4; INK 7; "Floor: "; e; " Kills: "; q
1208 PRINT AT 10, 4; INK 6; "Gold: "; g
1210 PRINT AT 14, 6; INK 7; "Press any key"
1212 PAUSE 0
1214 GO TO 10
1500 REM === MONSTER DATA ===
1502 DATA "Rat", 4, 1, 0, 2
1504 DATA "Goblin", 8, 2, 1, 5
1506 DATA "Skeleton", 12, 3, 2, 8
1508 DATA "Troll", 18, 4, 2, 12
1510 DATA "Wraith", 15, 5, 1, 15
1512 DATA "Dragon", 30, 6, 4, 50
1600 REM === find empty cell ===
1602 LET t = INT (RND * 14) + 2
1604 LET t2 = INT (RND * 14) + 2
1606 IF d(t2,t) <> 0 THEN GO TO 1602
1608 IF t = x AND t2 = y THEN GO TO 1602
1610 RETURN
How It Works
Lines 870-888 handle fleeing. Line 872 rolls a random number — if it exceeds 0.5, the escape succeeds. A “You escape!” message appears in yellow, and the subroutine returns to the exploration loop. The monster stays on the map, alive and in place.
Lines 874-886 handle a failed escape. The message “Cannot flee!” appears in red, followed by a monster attack. This free hit uses the same damage formula as normal combat. If the player survives, the combat loop continues — they can try to flee again or stand and fight.
The Death Screen
Lines 1000-1016 handle player death. The screen clears and displays “YOU HAVE FALLEN” in red, bright text. Below it, the game shows the floor reached, monsters killed, gold collected, and turns survived. These stats give the death a sense of progress — even a failed run accomplished something.
A low descending tone plays as a death knell. PAUSE 0 waits for a keypress, then GO TO 15 restarts the game from the title screen. All variables reset — death is permanent. There is no saving mid-run and reloading after death (at least, not yet).
Risk Assessment
The flee mechanic creates a genuine decision point. When the player encounters a monster, they must assess: can I win this fight with my current HP, attack, and defence? If the answer is uncertain, fleeing is tempting — but the 50% failure rate means it is not a free escape. A failed flee costs HP, potentially killing a player who was trying to avoid death.
This risk calculation is the core of dungeon crawl gameplay. Stats are not just numbers — they are information for making survival decisions. A player with 5 HP facing a troll with 4 attack must weigh the odds carefully. Fight and risk death in combat, or flee and risk death from the free hit.
Entity Removal
When a monster is defeated (lines 890-906), its HP in the array is set to 0. The viewport renderer (line 324) only draws monsters with HP greater than 0, so defeated monsters simply disappear. The position arrays still hold the old coordinates, but nothing reads them because the HP check filters them out. This is simpler than removing entries from the arrays.
Try This
Adjust flee odds. Change the threshold from 0.5 to 0.7 (70% success rate) or 0.3 (30%). How does this change the player willingness to engage in combat?
Add a run count. Track how many games the player has started. Display it on the death screen — “Attempt #3” adds weight to each new run.