Information Technology - Computer Programming - Source Code - Homebrew - Open Source - Software - Hardware - 8 bit - 16 bit - 32 bit - 64 bit - x86 - x64 - DOS - Windows - Linux - Arduino - Embedded - Development - Retro - Vintage - Math - Science - History - Hobby - Beginners - Professionals - Experiment - Research - Study - Fun - Games

Zombie Bug Out turn based survival shoot em up

Share your Express Basic creations here.
Post Reply
admin
Site Admin
Posts: 109
Joined: Wed Feb 22, 2023 6:51 am

Zombie Bug Out turn based survival shoot em up

Post by admin »

Zombie Bug Out

How long can you survive without being taken out by zombies or thirst? How many zombies can you eliminate?

Find out with this classic BASIC style game. Designed to run with Express BASIC, it is easily portable to virtually all other dialects. With Express BASIC, Zombie Bug Out may run on Linux, Windows, and DOS.

While seemingly simple, this game exposed a bunch of issues about the Express BASIC interpreter for DOS. It worked fine under Win32, Linux, and even DPMI DOS. Now it works on an 8088 as well, although it's too slow to even be remotely playable on such a limited system. The interpreter in general is extremely slow on an 8088 and this shows painfully with FOR loops or long expressions.

Developing this game and ensuring that it will technically run on an 8088 (even if it is painfully slow there) ensured that nasty code was fixed.

Now we have this nice little game. The inspiration came from another game I wrote when I was in the 9th grade somewhere around 2007-2008. I lost the code over ten years ago and always wanted to replicate it.

One neat feature about the game is the subroutine starting at line 40000. It attempts to animate the shooting of a zombie using only console text. Glorious flickering animation using the TAB function... The zombie is represented by the exclamation point. The bullet represented by a hyphen travels towards the zombie from the gun ascii art. All using a bit of math. I did notice a slight difference in how this subroutine works in Qbasic versus Express BASIC. Not sure why yet... Something to do with PRINT or TAB. Who knows...?

Give the game a try either in Express BASIC or try porting it to the language of your choice.

Code: Select all

1 REM Zombie Bug-out by Gemino Smothers
2 REM Lucid Apogee 2024 www.lucidapogee.com
3 REM Run with Express BASIC
10 CLS: GOSUB 10000: GOSUB 20000: GOSUB 100: GOTO 10
100 IF NOT(die) THEN CLS: GOSUB 1000: GOSUB 2000: GOSUB 3000: GOTO 100
110 LET die = 0: LET lvl = 0: LET s = 0: LET t = 0: RETURN
1000 IF die THEN RETURN
1010 IF NOT(g) THEN PRINT "Area cleared."; CHR$(10): GOSUB 10000
1020 PRINT "Level: "; lvl; " Score: "; s; " Thirst: "; t; "/"; 16 + lvl; CHR$(10)
1030 PRINT TAB(15); "N"; CHR$(10); TAB(14); "W E"; CHR$(10); TAB(15); "S"; CHR$(10): GOSUB 4000 
1040 PRINT "  (1) Go North (2) Go East"; CHR$(10); "  (3) Go South (4) Go West"
1050 PRINT "  (5) Wait (6) Shoot Gun"; CHR$(10); "  (0) Give Up"; CHR$(10)
1060 INPUT "   What is your decision"; a: PRINT: RETURN
2000 IF a = 1 AND py > 1 THEN PRINT "You move North."; CHR$(10): LET py = py - 1
2010 IF a = 2 AND px < mx THEN PRINT "You move East."; CHR$(10): LET px = px + 1
2020 IF a = 3 AND py < my THEN PRINT "You move South."; CHR$(10): LET py = py + 1
2030 IF a = 4 AND px > 1 THEN PRINT "You move West."; CHR$(10): LET px = px - 1
2040 IF a = 5 THEN PRINT "Waiting..."; CHR$(10)
2050 IF a = 6 THEN GOSUB 5000
2060 IF a <> 0 THEN 2090
2070 CLS: PRINT "Final Score: "; s; CHR$(10): LET fs = 0: LET die = 1
2080 INPUT "Enter any number to continue:", a
2090 LET t = t + 1: IF px = wx AND py = wy THEN LET t = 0
2100 IF NOT(t = 16 + lvl) THEN 2130
2110 CLS: PRINT "You are too thirsty to go on..."; CHR$(10); CHR$(10); "Final Score: "; s; CHR$(10)
2120 LET fs = 0: LET die = 1: INPUT "Enter any number to continue:", a
2130 RETURN
3000 IF sk THEN LET sk = sk - 1: RETURN
3010 LET ch = INT(RND * 2): FOR i = 0 TO (zcnt * 2) - 1 STEP 2
3020 IF NOT(@(i)) AND NOT(@(i + 1)) THEN 3100
3030 IF ch AND @(i + 1) > py THEN LET @(i + 1) = @(i + 1) - 1: GOTO 3100
3040 IF ch AND @(i) < px THEN LET @(i) = @(i) + 1: GOTO 3100
3050 IF ch AND @(i + 1) < py THEN LET @(i + 1) = @(i + 1) + 1: GOTO 3100
3060 IF ch AND @(i) > px THEN LET @(i) = @(i) - 1
3070 IF NOT(@(i) = px AND @(i + 1) = py) THEN 3100
3080 CLS: PRINT "A zombie has eliminated you..."; CHR$(10); "Final Score: "; s; CHR$(10)
3090 INPUT "Enter any number to continue:", a: LET fs = 0: LET die = 1: BREAK i
3100 NEXT i: RETURN
4000 FOR dy = py - 2 TO py + 2: PRINT TAB(13);: FOR dx = px - 2 TO px + 2: LET f = 0
4010 IF dx < 1 OR dx > mx OR dy < 1 OR dy > my THEN LET f = 1: PRINT "#";: GOTO 4060
4020 IF dx = px AND dy = py THEN LET f = 1: PRINT "+";: GOTO 4060
4030 FOR i = 0 TO (zcnt * 2) - 1 STEP 2
4040 IF dx = @(i) AND dy = @(i + 1) THEN LET f = 1: PRINT "!";: BREAK i
4050 NEXT i
4060 IF NOT(f) AND dx = wx AND dy = wy AND wf THEN LET f = 1: PRINT "~";
4070 IF NOT(f) THEN PRINT ".";
4080 NEXT dx: PRINT: NEXT dy: PRINT: RETURN
5000 PRINT "  (1) Shoot North (2) Shoot East"
5005 PRINT "  (3) Shoot South (4) Shoot West"; CHR$(10)
5010 INPUT "   What is your decision"; a: PRINT
5020 IF a = 1 THEN LET sx = px: LET sy = py - 1
5030 IF a = 2 THEN LET sx = px + 1: LET sy = py
5040 IF a = 3 THEN LET sx = px: LET sy = py + 1
5050 IF a = 4 THEN LET sx = px - 1: LET sy = py
5060 FOR i = 0 TO (zcnt * 2) - 1 STEP 2
5070 IF NOT(sx = @(i) AND sy = @(i + 1)) THEN GOTO 5110
5080 LET g = g - 1: LET @(i) = 0: LET @(i + 1) = 0: LET s = s + 1
5090 GOSUB 40000: PRINT "You have eliminated a zombie!"; CHR$(10)
5100 INPUT "Enter any number to continue:", a: BREAK i
5110 NEXT i: RETURN
10000 IF fs THEN PRINT "Looking for zombies...";
10010 LET lvl = lvl + 1: LET zcnt = INT(RND * (lvl * 2)) + 1: LET g = zcnt
10020 LET mx = INT(RND * 8) + 4 + lvl: LET my = INT(RND * 8) + 4 + lvl
10030 FOR i = 0 TO (zcnt * 2) - 1 STEP 2: PRINT "...";
10040 LET @(i) = INT(RND * mx) + 1: LET @(i + 1) = INT(RND * my) + 1
10050 NEXT i: LET px = INT(RND * mx) + 1: LET py = INT(RND * my) + 1
10060 LET wx = INT(RND * mx) + 1: LET wy = INT(RND * my) + 1: LET wf = 1
10070 PRINT: PRINT: IF NOT(fs) THEN 10090
10080 PRINT "Zombies found."; CHR$(10): INPUT "Enter any number to continue:", a
10090 LET fs = 1: LET sk = 2: CLS: RETURN
20000 CLS: PRINT TAB(10); "Zombie Bug-out"; CHR$(10)
20010 PRINT " (1) Bug-out (2) Help (0) Give Up"; CHR$(10)
20020 INPUT "     What is your decision"; a: CLS
20030 IF a = 0 THEN END
20040 IF a = 1 THEN RETURN
20050 IF a = 2 THEN GOSUB 30000
20060 GOTO 20000
30000 PRINT "Objective: Survive the zombie invasion."; CHR$(10)
30010 PRINT "You're represented by a + while the zombies are a ! symbol."; CHR$(10)
30020 PRINT "Tiles with the ~ symbol are water sources."
30030 PRINT "Tiles with the # symbol are trees representing the map edge."
30040 PRINT "Tiles with the . symbol represent a blank space on the map."; CHR$(10)
30050 PRINT "You may either move, wait, or attack."
30060 PRINT "Waiting allows you to pass a turn without moving."; CHR$(10)
30070 PRINT "To eliminate a zombie, you must attack while adjacent to it."
30080 PRINT "Multiple zombies may occupy a single tile at a time."
30090 PRINT "Zombies will eliminate you if they move to the same map tile you're on."; CHR$(10)
30100 PRINT "If you get too thirsy, you will be unable to continue."; CHR$(10)
30110 PRINT "[+] Hunter [!] Zombie [#] Tree"; CHR$(10)
30120 INPUT "Enter any number to continue:", a: CLS: RETURN
40000 FOR b = 1 TO 61: CLS
40010 PRINT "  /=============="; TAB(b); "-"; TAB(79 - b - 17); "!"
40020 PRINT " / ____/"
40030 PRINT "/_/  `"
40040 NEXT b: RETURN
Post Reply