'                       Tank Game!!!!!!!!!!!!!
'
'                       By Dave Duvenaud
'
'contact me at         duvenaud@escape.ca
'
'               Press F5 to run, or Ctrl+Break to exit.
'                 if F5 doesn't work, press shift F5
'much thanks to the guy who made snoopy for the timing code, but I found
'way to improve it further by putting the stored timer variable at the
'beginning of the loop. This means that the amount of stuff happening
' in the game won't affect the speed at all, unless it surpasses the given
'time.
'
'          Made in 1998 but the landscape code in 1997
'
'       Oh yeah, you might want to use the explosion code which I took
'from MY other game, star warrior.

DIM cas AS LONG
DIM steep AS LONG
DIM tank AS STRING
DIM lkas AS STRING * 3
DIM SHARED x AS INTEGER
DIM SHARED y AS INTEGER
DIM tankx(5) AS INTEGER
DIM tanky(5) AS INTEGER
DIM shotx(5) AS INTEGER
DIM shoty(5) AS INTEGER

guypic$ = " h2 e1 r1 f1 g1 d2 r2 e1 g1 l4 h1 f1 r2 d2 f2 h2 g2"


GOTO 9909
drawtank:
        PSET (tankx, tanky), 0
        DRAW "c2"
        DRAW "x" + VARPTR$(tank$)
        PAINT (tankx, tanky - 2), 2
RETURN

tankmask:
        PSET (tankx, tanky - 1), 0
        DRAW "c0"
        DRAW "x" + VARPTR$(tank$)
RETURN


9909

tank$ = "l8 h3 r4 e3 r8 f3 r4 g3 l8"

DIM colo AS INTEGER

SCREEN 13
CLS
colo = 4
        RANDOMIZE TIMER
        boz = INT(RND * 160) + 20
        RANDOMIZE TIMER
        bo = INT(RND * 280) + 20

1 
        LOCATE 12, 12: PRINT "  Tank Game"
        LOCATE 13, 10: PRINT "By David Duvenaud"
        explosion = explosion + 1
        IF colo = 4 THEN SOUND 37, .07     'when the circle is red,make a sound
        CIRCLE (bo, boz), explosion, colo       'explosion is the radius
        CIRCLE (bo, boz + 1), explosion, colo
        'IF explosion > 20 AND col = 4 THEN col = 6  'this would make it part
        IF explosion > 30 THEN                       'orange
         IF colo = 0 THEN
          RANDOMIZE TIMER                       'I took this routine
          boz = INT(RND * 160) + 20             'from my first game,
          RANDOMIZE TIMER                       ' star warrior.
          bo = INT(RND * 280) + 20
          explosion = 0
          colo = 4
         ELSE
          colo = 0
          explosion = 0
         END IF
        END IF
IF INKEY$ = "" THEN GOTO 1

steep = 65
numtanks = 2

33 main:
CLS
LOCATE 4, 10: PRINT "Mushroom cloud"
LOCATE 5, 12: PRINT "Main menu"
PRINT
PRINT
PRINT
COLOR 4
PRINT "     (1) To the battlefeild!      "
COLOR 15
PRINT "     (2) Options"
PRINT "     (3) Info                     "
PRINT "     (4) Credits"
PRINT "     (5) Exit"
FOR i = 1 TO 5
tankx = 40 * i + 5
tanky = 57
GOSUB drawtank
DRAW "e7"
NEXT
PRINT
PRINT
PRINT
PRINT "         Steepness: "; steep
PRINT "         Players: "; numtanks
'IF artillery = 1 THEN
'PRINT "         Artillery: On"
'ELSE PRINT "       Artillery: Off"
'END IF


DO
SELECT CASE INKEY$
        CASE "1": GOTO makescreen
        CASE "2": GOTO 88
        CASE "3": GOTO info
        CASE "4": GOSUB Credits
        CASE "5": END
        CASE ELSE
END SELECT
LOOP

info:
CLS
SCREEN 9
PRINT
PRINT "               Info"
PRINT
PRINT "    This game is like scorched earth, with one major difference: no turns! "
PRINT "You can only have one shot at a time but you don't have to sit there while a"
PRINT "shell is heading straight for you. Programmed in Qbasic. 1998"
PRINT
PRINT "Dont hold down the Keys!!!!!!!!!!!"
PRINT "            Controls"
PRINT
PRINT "Player       1       2       3           4"
PRINT
PRINT "Shoot:       c       /     0 (Insert)    7"
PRINT "Gun left:    a       j       Left Arrow  4 "
PRINT "Gun right:   d       l       Right Arrow 6"
PRINT "Power Up:    w       i       Up Arrow    8"
PRINT "Power Down:  s       k       Down Arrow  5 "
PRINT
PRINT "q to quit"
COLOR 10
PRINT "You gotta have Numlock on!"
COLOR 15
PRINT "Your power can be from 1 to 20"
PRINT "When your tank dies, your guy ejects from the tank."
PRINT "You can't control him, because he dies on impact! Hahahaha!"
PRINT "The object of the game is to kill the other tanks."
WHILE INKEY$ = "": WEND
SCREEN 13
GOTO 33

Credits:
CLS
SCREEN 9
PRINT
PRINT
PRINT "                         Credits"
PRINT
PRINT "          Programmed entirley by Dave Duvenaud"
PRINT
PRINT "                         Testers:"
PRINT
PRINT "John Duvenaud                    James Challis"
PRINT "Steven Duvenaud                  Bayard Devris"
PRINT
PRINT
PRINT "I have made a few other games, but this is my best so far."
PRINT "The only one I have distributed is Star Warrior."
WHILE INKEY$ = "": WEND
SCREEN 13
GOTO 33


88 CLS
LOCATE 5, 15: PRINT "Options"
LOCATE 10, 10: INPUT "Steepness(1 to 100):", lkas$
IF VAL(lkas$) > 100 OR VAL(lkas$) < 1 THEN GOTO 88 ELSE
steep = VAL(lkas$)

4 LOCATE 15, 1:
PRINT "           Players(2 to 4): "
DO
        slop$ = INKEY$
        IF slop$ > "4" OR slop$ < "2" THEN GOTO 4 ELSE
        LOCATE 15, 28: PRINT slop$
        numtanks = VAL(slop$): GOTO 29
LOOP

PRINT
29 LOCATE 18, 13: PRINT "Accept Options?"
DO
        poop$ = INKEY$
        IF poop$ = "y" THEN GOTO main
        IF poop$ = "n" THEN GOTO 88
        GOTO 29
LOOP

makescreen:                           'Makes the screen
SCREEN 9
CLS
LOCATE 1, 12: PRINT "Creating Screen"

cas = 170         'cas is the height of the land, this starts it in middle
jas = 27
bottom = 345            'bottom is the lowest point that the land can go

FOR has = 1 TO 640                      'Creates landscape
RANDOMIZE TIMER
mas = INT(RND * 3) + 1
SELECT CASE mas
        CASE 2: sas = sas + steep / 100
        CASE 3: sas = sas - steep / 100
        CASE 4: sas = sas + steep / 100
        CASE 5: sas = sas - steep / 100
END SELECT

cas = cas + sas

IF cas < 60 THEN                'keeps land height within screen
        sas = 0
        cas = 60
END IF

IF cas > bottom THEN
        cas = bottom
        sas = 0
END IF
LINE (has, cas)-(has, bottom), 6                   'Draws landscape
has = has + 1                   'I added this to make the terrain less bumpy
LINE (has, cas)-(has, bottom), 6
IF has = 150 OR has = 300 OR has = 450 THEN        'Keeps user waiting
LOCATE 1, jas: PRINT "."
jas = jas + 1
END IF
NEXT has

LOCATE 1, 10: PRINT "                           " 'erases "creating screen"

LINE (1, 28)-(639, 346), 7, B             'draws border
LINE (2, 29)-(638, 345), 7, B



LOCATE 1, 2: PRINT "Do you like this landscape? (Y or N)"

DO
inky$ = INKEY$                                'decides yes or no
SELECT CASE inky$
CASE "n", "N": GOTO makescreen
CASE "y", "Y": GOTO 101
END SELECT
LOOP

101                                      'places tanks
LOCATE 1, 2: PRINT "                                         "
FOR h = 1 TO numtanks
        tanky(h) = 38
        tankx(h) = 100 + (500 / numtanks) * (h - 1)        'spaces the tanks evenly
        tankx = tankx(h)
        tanky = tanky(h)
        'GOSUB drawtank
NEXT h

DIM land(6) AS INTEGER         'to keep track of which tanks are on the ground

                           ' I added this so that if the player used
land(5) = 5                     'less than five players it would still
land(4) = 5                          'check to see
land(3) = 5                                 'if all the tanks had landed
land(2) = 5

DO
IF INKEY$ = CHR$(27) THEN END         'escape key
FOR mamja = 1 TO numtanks
IF POINT(tankx(mamja), tanky(mamja) + 5) = 7 OR POINT(tankx(mamja), tanky(mamja) + 1) = 6 OR POINT(tankx(mamja), tanky(mamja) + 1) = 7 THEN
land(mamja) = 5
ELSE
        tanky(mamja) = tanky(mamja) + 1
        tanky = tanky(mamja)
        tankx = tankx(mamja)
        GOSUB tankmask
        GOSUB drawtank
        land(mamja) = 3
END IF
NEXT mamja

            'checks to see if they all touched ground
IF land(1) = 5 AND land(2) = 5 AND land(3) = 5 AND land(4) = 5 AND land(5) = 5 THEN notdone = 5

LOOP UNTIL notdone = 5

DIM rad(10) AS INTEGER
DIM ang(5) AS INTEGER
DIM grav(5) AS DOUBLE
DIM thrust(5) AS DOUBLE

shotpic$ = "u1 d2 u1 l1 r2"
soundon = 1

GOTO 2                    'so that it skips this
blowup:
rad(c) = rad(c) + 1
IF col(c) = 4 AND soundon = 1 THEN SOUND 37, .07
CIRCLE (explox(c), exploy(c)), rad(c), col(c)
CIRCLE (explox(c), exploy(c) - 1), rad(c), col(c)
IF col = 0 THEN
rad(c) = rad(c) + 1                           'make it erase faster
CIRCLE (explox(c), exploy(c)), rad(c), col(c)
CIRCLE (explox(c), exploy(c) - 1), rad(c), col(c)
LINE (1, 28)-(639, 346), 7, B             'draws border
LINE (2, 29)-(638, 345), 7, B
END IF
IF rad(c) > 35 THEN
IF col(c) = 4 THEN
rad(c) = 0
col(c) = 0
ELSE
LINE (1, 28)-(639, 346), 7, B             'draws border
LINE (2, 29)-(638, 345), 7, B
explo(c) = 0
END IF
END IF
RETURN
2

dead(3) = 1
dead(2) = 1
dead(1) = 1
dead(4) = 1                'makes all of them dead
dead(5) = 1

FOR i = 0 TO numtanks                'revives the real players
        dead(i) = 0
        power(i) = 7                  'and sets all the variables
        health(i) = 100
        guygrav(i) = -3
        guythrust(i) = -1
        shot(i) = 0
        explo(i) = 0
        rad(i) = 0
        ang(i) = 0
        guy(i) = 0
        guydead(i) = 0
        notdone = 0
        mamja(i) = 0
NEXT i
winner = 0
guydead = 0
dead = 0
'GOSUB drawcan
                       
           'If you're looking at the code, you should know that c is the     
           'player number, and that h is the player number for keys
                        '************************************************
beginning:              'the start of the loop***************************
FOR c = 1 TO numtanks

w! = TIMER
76 IF c = 1 OR c = 2 OR c = 3 THEN
LOCATE 1, (27 * c) - 26
ELSE    'puts them on two lines
IF c > 3 AND c < 6 THEN LOCATE 2, (27 * (c - 2)) - 26:  'it was crashing here
END IF                                                  'so I added an if
PRINT "Tank"; c; "Pwr:"; power(c); "Armor:"; health(c)


IF guy(c) = 1 THEN
IF POINT(guyx(c), guyy(c) - 4) = 6 OR POINT(guyx(c), guyy(c) + 10) = 6 OR POINT(guyx(c) - 3, guyy(c)) = 6 OR POINT(guyx(c), guyy(c) - 4) = 2 OR POINT(guyx(c) - 5, guyy(c) + 4) = 2 OR guyx(c) < 1 OR guyx(c) > 640 OR guyy(c) > 350 THEN
LINE (guyx(c), guyy(c))-(guyx(c), guyy(c)), 0
DRAW "c0"
DRAW "x" + VARPTR$(guypic$)
guy(c) = 0                               'this is the guy sub
guydead(c) = 1                          ' it's alot like the shot sub
guydead = guydead + 1
ELSE
guygrav(c) = guygrav(c) + .2
LINE (guyx(c), guyy(c))-(guyx(c), guyy(c)), 0
DRAW "c0"
DRAW "x" + VARPTR$(guypic$)
guyy(c) = guyy(c) + guygrav(c)
guyx(c) = guyx(c) + guythrust(c)
LINE (guyx(c), guyy(c))-(guyx(c), guyy(c)), 0
DRAW "c15"
DRAW "x" + VARPTR$(guypic$)
END IF
END IF


IF shot(c) = 1 THEN                'checks if a shot is in the air
LINE (shotx(c), shoty(c))-(shotx(c), shoty(c)), 0
DRAW "c0"
DRAW "x" + VARPTR$(shotpic$)        'erases shot
shotx(c) = shotx(c) + thrust(c)
shoty(c) = shoty(c) + grav(c)
grav(c) = grav(c) + .2
LINE (shotx(c), shoty(c))-(shotx(c), shoty(c)), 0
DRAW "c15"
DRAW "x" + VARPTR$(shotpic$)                          'draws shot


'IF POINT(shotx(c) - 2, shoty(c)) = 7 OR POINT(shotx(c) + 2, shoty(c)) = 7 OR POINT(shotx(c) + 1, shoty(c) - 1) = 7 OR POINT(shotx(c) - 1, shoty(c) - 1) = 7 THEN
'IF shoty(c) < 40 THEN grav(c) = -grav(c)       'bounce off roof
'IF shoty(c) > 500 THEN grav(c) = -grav(c)      'bounce off floor
'ELSE thrust(c) = -thrust(c)                    'Bounce off walls
'PRINT "Boing!"
'END IF

IF POINT(shotx(c) - 1, shoty(c) + 1) <> 0 OR POINT(shotx(c) + 1, shoty(c) + 1) <> 0 OR POINT(shotx(c) + 1, shoty(c) - 1) <> 0 OR POINT(shotx(c) - 1, shoty(c) - 1) <> 0 THEN


IF explo(c) = 1 THEN                            'this is also a complex
 IF col(c) = 0 THEN rad(c) = 35                'peice of work... don't try
 rad(c) = rad(c) + 1                          'to understand it.
 FOR i = 1 TO rad(c)
  CIRCLE (explox(c), exploy(c)), i, 0
  CIRCLE (explox(c), exploy(c) - 1), i, 0
 NEXT i
END IF
explox(c) = shotx(c)
exploy(c) = shoty(c)
col(c) = 4                             'changes explosion color
rad(c) = 0                             'resets explosion radius
explo(c) = 1                           'says that it's exploding
shot(c) = 0                            'erases the shot
END IF
END IF
98


IF explo(c) = 1 THEN
kn = c
FOR kn = 1 TO numtanks                'this speeds up the explosions
        GOSUB blowup     'and checks if it's exploding
NEXT kn
END IF


IF dead(c) = 1 THEN
IF numtanks - guydead < 2 THEN GOTO 87
IF c = numtanks THEN EXIT FOR
c = c + 1              'checks if that tank is dead!
GOTO 76          ' so that if first tank dies, succesive guys can go flying
END IF            ' all the stuff before this happens even if tank is dead



IF numtanks - guydead < 2 THEN GOTO 87
IF POINT(tankx(c), tanky(c) - 8) = 4 THEN         'checks  if tank is hurt
blast(c) = 1
health(c) = health(c) - 4
IF health(c) = 0 THEN
PRINT "Tank number "; c; " died!"
dead(c) = 1
guy(c) = 1
guyx(c) = tankx(c)
guyy(c) = tanky(c) - 7
dead = dead + 1
RANDOMIZE TIMER                         'this makes the guy go randomly
a = INT(RND * 8) - 4                    'flying in any direction
guythrust(c) = a
RANDOMIZE TIMER
s = INT(RND * 6) - 8
guygrav(c) = s
IF numtanks - guydead = 1 THEN
87 PRINT "Game Over."                            'Declare the winner!
  FOR p = 1 TO numtanks
        IF dead(p) = 0 THEN
        winner = p
        END IF
  NEXT
IF winner <> 0 THEN
        PRINT "Player"; winner; "is the winner!"
ELSE
        PRINT "It's a Tie"
END IF
s! = TIMER
DO
LOOP UNTIL TIMER > s! + .1
SLEEP
SCREEN 13
GOTO 33                     'That's all, folks
END IF
END IF
END IF

IF POINT(tankx(c), tanky(c)) = 0 THEN       'so that it redraws the tank after a hit
FOR j = 1 TO 10                             ' a hit
IF explo(c) = 1 THEN GOSUB blowup
NEXT j
LINE (tankx(c), tanky(c))-(tankx(c), tanky(c)), 0
DRAW "c2"
DRAW "x" + VARPTR$(tank$)
PAINT (tankx(c), tanky(c) - 2), 2
END IF

sps$ = INKEY$
        SELECT CASE sps$                          'checks the keys
        CASE CHR$(27): END
        CASE "w": h = 1: GOSUB powerup
        CASE "s": h = 1: GOSUB powerdown
        CASE "c": h = 1: GOSUB shoot
        CASE "d": h = 1: GOSUB angright
        CASE "a": h = 1: GOSUB angleft
        CASE "i": h = 2: GOSUB powerup
        CASE "k": h = 2: GOSUB powerdown
        CASE "/": h = 2: GOSUB shoot
        CASE "l": h = 2: GOSUB angright
        CASE "j": h = 2: GOSUB angleft
        CASE "8": h = 4: GOSUB powerup
        CASE "5": h = 4: GOSUB powerdown
        CASE "7": h = 4: GOSUB shoot
        CASE "6": h = 4: GOSUB angright
        CASE "4": h = 4: GOSUB angleft
        CASE CHR$(0) + "H": h = 3: GOSUB powerup
        CASE CHR$(0) + "P": h = 3: GOSUB powerdown
        CASE CHR$(0) + "K": h = 3: GOSUB angleft
        CASE CHR$(0) + "M": h = 3: GOSUB angright
        CASE "0": h = 3: GOSUB shoot
        CASE ELSE
END SELECT

IF POINT(tankx(c), tanky(c) + 1) = 0 THEN                   'makes tank fall
GOSUB erasecan                            'otherwise it will leave cannon trails
LINE (tankx(c), tanky(c))-(tankx(c), tanky(c)), 0
DRAW "c0"
DRAW "x" + VARPTR$(tank$)
tanky(c) = tanky(c) + 1
LINE (tankx(c), tanky(c))-(tankx(c), tanky(c)), 0
DRAW "c2"
DRAW "x" + VARPTR$(tank$)
PAINT (tankx(c), tanky(c) - 2), 2
GOSUB erasecan              ' it used to leave a trail of cannons when you
                                'fell before I added this
GOSUB drawcan        'so even when we're falling we know our angle
END IF

NEXT c                     'end of loop
DO
LOOP UNTIL TIMER > w! + .01
GOTO beginning



drawcan:
IF dead(h) = 1 THEN RETURN
ang = ang(h)
LINE (tankx(h), tanky(h) - 7)-(tankx(h), tanky(h) - 7), 0
DRAW "c2"
DRAW "TA=" + VARPTR$(ang)
DRAW "u5"
ang = -ang
DRAW "TA=" + VARPTR$(hgd)
RETURN

erasecan:
ang = ang(h)
LINE (tankx(h), tanky(h) - 7)-(tankx(h), tanky(h) - 7), 0
DRAW "c0"
DRAW "TA=" + VARPTR$(ang)
DRAW "u5"
ang = -ang
DRAW "TA=" + VARPTR$(hhgf)    'resets the angle
RETURN

powerup:
power(h) = power(h) + 1
IF power(h) > 20 THEN power(h) = 20
RETURN

powerdown:
power(h) = power(h) - 1
IF power(h) < 1 THEN power(h) = 1
RETURN

shoot:
IF dead(h) = 1 THEN RETURN     'can't shoot if he's dead
 IF shot(h) = 0 THEN
  IF ang(h) < 0 THEN
thrust(h) = (-power(h) / 90) * ang(h)      'these formulas took me a long time
grav(h) = -power(h) + thrust(h)            ' to get right.
ELSE
thrust(h) = (-power(h) / 90) * ang(h)     'they control the up and side thrust
grav(h) = -power(h) - thrust(h)            'of the bullet.
up(h) = grav(h)                           'I've seen lots of games that could
END IF                                    ' use this formula.
GOSUB drawcan                             'if you use it, at least tell me.
shotx(h) = POINT(0)
shoty(h) = POINT(1) - 1
shot(h) = 1
FOR l = 1 TO 1
        i = 1500 - (l * 10)
        SOUND (i), 1
NEXT l
END IF
RETURN

angright:
GOSUB erasecan
ang(h) = ang(h) - 5
IF ang(h) < -90 THEN ang(h) = -90
GOSUB drawcan
RETURN

angleft:
GOSUB erasecan
ang(h) = ang(h) + 5
IF ang(h) > 90 THEN ang(h) = 90
GOSUB drawcan
RETURN

