5748215 [rkeene@sledge /home/rkeene/devel/archive/quickbasic]$ cat -n mgorilla.bas
   1: '                         Q B a s i c   G o r i l l a s
   2: '
   3: '                   Copyright (C) Microsoft Corporation 1990
   4: '
   5: ' Your mission is to hit your opponent with the exploding banana
   6: ' by varying the angle and power of your throw, taking into account
   7: ' wind speed, gravity, and the city skyline.
   8: '
   9: ' Speed of this game is determined by the constant SPEEDCONST.  If the
  10: ' program is too slow or too fast adjust the "CONST SPEEDCONST = 500" line
  11: ' below.  The larger the number the faster the game will go.
  12: '
  13: ' To run this game, press Shift+F5.
  14: '
  15: ' To exit QBasic, press Alt, F, X.
  16: '
  17: ' To get help on a BASIC keyword, move the cursor to the keyword and press
  18: ' F1 or click the right mouse button.
  19: '
  20: 
  21: 'Set default data type to integer for faster game play
  22: DEFINT A-Z
  23: 
  24: 'Sub Declarations
  25: DECLARE SUB DoSun (Mouth)
  26: DECLARE SUB SetScreen ()
  27: DECLARE SUB EndGame ()
  28: DECLARE SUB Center (Row, Text$)
  29: DECLARE SUB Intro ()
  30: DECLARE SUB SparklePause ()
  31: DECLARE SUB GetInputs (Player1$, Player2$, NumGames)
  32: DECLARE SUB PlayGame (Player1$, Player2$, NumGames)
  33: DECLARE SUB DoExplosion (x#, y#)
  34: DECLARE SUB MakeCityScape (BCoor() AS ANY)
  35: DECLARE SUB PlaceGorillas (BCoor() AS ANY)
  36: DECLARE SUB UpdateScores (Record(), PlayerNum, Results)
  37: DECLARE SUB DrawGorilla (x, y, arms)
  38: DECLARE SUB GorillaIntro (Player1$, Player2$)
  39: DECLARE SUB Rest (t#)
  40: DECLARE SUB VictoryDance (Player)
  41: DECLARE SUB ClearGorillas ()
  42: DECLARE SUB DrawBan (xc#, yc#, r, bc)
  43: DECLARE FUNCTION Scl (n!)
  44: DECLARE FUNCTION GetNum# (Row, Col)
  45: DECLARE FUNCTION DoShot (PlayerNum, x, y)
  46: DECLARE FUNCTION ExplodeGorilla (x#, y#)
  47: DECLARE FUNCTION Getn# (Row, Col)
  48: DECLARE FUNCTION PlotShot (StartX, StartY, Angle#, Velocity, PlayerNum)
  49: DECLARE FUNCTION CalcDelay! ()
  50: 
  51: 'Make all arrays Dynamic
  52: '$DYNAMIC
  53: 
  54: 'User-Defined TYPEs
  55: TYPE XYPoint
  56:   XCoor AS INTEGER
  57:   YCoor AS INTEGER
  58: END TYPE
  59: 
  60: 'Constants
  61: CONST SPEEDCONST = 500
  62: CONST TRUE = -1
  63: CONST FALSE = NOT TRUE
  64: CONST HITSELF = 1
  65: CONST BACKATTR = 0
  66: CONST OBJECTCOLOR = 1
  67: CONST WINDOWCOLOR = 14
  68: CONST SUNATTR = 3
  69: CONST SUNHAPPY = FALSE
  70: CONST SUNSHOCK = TRUE
  71: CONST RIGHTUP = 1
  72: CONST LEFTUP = 2
  73: CONST ARMSDOWN = 3
  74: 
  75: 'Global Variables
  76: DIM SHARED GorillaX(1 TO 2)  'Location of the two gorillas
  77: DIM SHARED GorillaY(1 TO 2)
  78: DIM SHARED LastBuilding
  79: 
  80: DIM SHARED pi#
  81: DIM SHARED LBan&(x), RBan&(x), UBan&(x), DBan&(x) 'Graphical picture of banana
  82: DIM SHARED GorD&(120)        'Graphical picture of Gorilla arms down
  83: DIM SHARED GorL&(120)        'Gorilla left arm raised
  84: DIM SHARED GorR&(120)        'Gorilla right arm raised
  85: 
  86: DIM SHARED gravity#
  87: DIM SHARED Wind
  88: 
  89: 'Screen Mode Variables
  90: DIM SHARED ScrHeight
  91: DIM SHARED ScrWidth
  92: DIM SHARED Mode
  93: DIM SHARED MaxCol
  94: 
  95: 'Screen Color Variables
  96: DIM SHARED ExplosionColor
  97: DIM SHARED SunColor
  98: DIM SHARED BackColor
  99: DIM SHARED SunHit
 100: 
 101: DIM SHARED SunHt
 102: DIM SHARED GHeight
 103: DIM SHARED MachSpeed AS SINGLE
 104: 
 105:   DEF FnRan (x) = INT(RND(1) * x) + 1
 106:   DEF SEG = 0                         ' Set NumLock to ON
 107:   KeyFlags = PEEK(1047)
 108:   IF (KeyFlags AND 32) = 0 THEN
 109:     POKE 1047, KeyFlags OR 32
 110:   END IF
 111:   DEF SEG
 112: 
 113:   GOSUB InitVars
 114:   Intro
 115:   GetInputs Name1$, Name2$, NumGames
 116:   GorillaIntro Name1$, Name2$
 117:   PlayGame Name1$, Name2$, NumGames
 118:  
 119:   DEF SEG = 0                         ' Restore NumLock state
 120:   POKE 1047, KeyFlags
 121:   DEF SEG
 122: END
 123: 
 124: 
 125: CGABanana:
 126:   'BananaLeft
 127:   DATA 327686, -252645316, 60
 128:   'BananaDown
 129:   DATA 196618, -1057030081, 49344
 130:   'BananaUp
 131:   DATA 196618, -1056980800, 63
 132:   'BananaRight
 133:   DATA 327686,  1010580720, 240
 134: 
 135: EGABanana:
 136:   'BananaLeft
 137:   DATA 458758,202116096,471604224,943208448,943208448,943208448,471604224,202116096,0
 138:   'BananaDown
 139:   DATA 262153, -2134835200, -2134802239, -2130771968, -2130738945,8323072, 8323199, 4063232, 4063294
 140:   'BananaUp
 141:   DATA 262153, 4063232, 4063294, 8323072, 8323199, -2130771968, -2130738945, -2134835200,-2134802239
 142:   'BananaRight
 143:   DATA 458758, -1061109760, -522133504, 1886416896, 1886416896, 1886416896,-522133504,-1061109760,0
 144: 
 145: InitVars:
 146:   pi# = 4 * ATN(1#)
 147: 
 148:   'This is a clever way to pick the best graphics mode available
 149:   ON ERROR GOTO ScreenModeError
 150:   Mode = 9
 151:   SCREEN Mode
 152:   ON ERROR GOTO PaletteError
 153:   IF Mode = 9 THEN PALETTE 4, 0   'Check for 64K EGA
 154:   ON ERROR GOTO 0
 155: 
 156:   MachSpeed = CalcDelay
 157: 
 158:   IF Mode = 9 THEN
 159:     ScrWidth = 640
 160:     ScrHeight = 350
 161:     GHeight = 25
 162:     RESTORE EGABanana
 163:     REDIM LBan&(8), RBan&(8), UBan&(8), DBan&(8)
 164: 
 165:     FOR i = 0 TO 8
 166:       READ LBan&(i)
 167:     NEXT i
 168: 
 169:     FOR i = 0 TO 8
 170:       READ DBan&(i)
 171:     NEXT i
 172: 
 173:     FOR i = 0 TO 8
 174:       READ UBan&(i)
 175:     NEXT i
 176: 
 177:     FOR i = 0 TO 8
 178:       READ RBan&(i)
 179:     NEXT i
 180: 
 181:     SunHt = 39
 182: 
 183:   ELSE
 184: 
 185:     ScrWidth = 320
 186:     ScrHeight = 200
 187:     GHeight = 12
 188:     RESTORE CGABanana
 189:     REDIM LBan&(2), RBan&(2), UBan&(2), DBan&(2)
 190:     REDIM GorL&(20), GorD&(20), GorR&(20)
 191: 
 192:     FOR i = 0 TO 2
 193:       READ LBan&(i)
 194:     NEXT i
 195:     FOR i = 0 TO 2
 196:       READ DBan&(i)
 197:     NEXT i
 198:     FOR i = 0 TO 2
 199:       READ UBan&(i)
 200:     NEXT i
 201:     FOR i = 0 TO 2
 202:       READ RBan&(i)
 203:     NEXT i
 204: 
 205:     MachSpeed = MachSpeed * 1.3
 206:     SunHt = 20
 207:   END IF
 208: RETURN
 209: 
 210: ScreenModeError:
 211:   IF Mode = 1 THEN
 212:     CLS
 213:     LOCATE 10, 5
 214:     PRINT "Sorry, you must have CGA, EGA color, or VGA graphics to play GORILLA.BAS"
 215:     END
 216:   ELSE
 217:     Mode = 1
 218:     RESUME
 219:   END IF
 220: 
 221: PaletteError:
 222:   Mode = 1            '64K EGA cards will run in CGA mode.
 223:   RESUME NEXT
 224: 
 225: REM $STATIC
 226: 'CalcDelay:
 227: '  Checks speed of the machine.
 228: FUNCTION CalcDelay!
 229: 
 230:   s! = TIMER
 231:   DO
 232:     i! = i! + 1
 233:   LOOP UNTIL TIMER - s! >= .5
 234:   CalcDelay! = i!
 235: 
 236: END FUNCTION
 237: 
 238: ' Center:
 239: '   Centers and prints a text string on a given row
 240: ' Parameters:
 241: '   Row - screen row number
 242: '   Text$ - text to be printed
 243: '
 244: SUB Center (Row, Text$)
 245:   Col = MaxCol \ 2
 246:   LOCATE Row, Col - (LEN(Text$) / 2 + .5)
 247:   PRINT Text$;
 248: END SUB
 249: 
 250: ' DoExplosion:
 251: '   Produces explosion when a shot is fired
 252: ' Parameters:
 253: '   X#, Y# - location of explosion
 254: '
 255: SUB DoExplosion (x#, y#)
 256: 
 257:   PLAY "MBO0L32EFGEFDC"
 258:   Radius = ScrHeight / 50
 259:   IF Mode = 9 THEN Inc# = .5 ELSE Inc# = .41
 260:   FOR c# = 0 TO Radius STEP Inc#
 261:     CIRCLE (x#, y#), c#, ExplosionColor
 262:   NEXT c#
 263:   FOR c# = Radius TO 0 STEP (-1 * Inc#)
 264:     CIRCLE (x#, y#), c#, BACKATTR
 265:     FOR i = 1 TO 100
 266:     NEXT i
 267:     Rest .005
 268:   NEXT c#
 269: END SUB
 270: 
 271: ' DoShot:
 272: '   Controls banana shots by accepting player input and plotting
 273: '   shot angle
 274: ' Parameters:
 275: '   PlayerNum - Player
 276: '   x, y - Player's gorilla position
 277: '
 278: FUNCTION DoShot (PlayerNum, x, y)
 279: 
 280:   'Input shot
 281:   IF PlayerNum = 1 THEN
 282:     LocateCol = 1
 283:   ELSE
 284:     IF Mode = 9 THEN
 285:       LocateCol = 66
 286:     ELSE
 287:       LocateCol = 26
 288:     END IF
 289:   END IF
 290: 
 291:   LOCATE 2, LocateCol
 292:   PRINT "Angle:";
 293:   Angle# = GetNum#(2, LocateCol + 7)
 294: 
 295:   LOCATE 3, LocateCol
 296:   PRINT "Velocity:";
 297:   Velocity = GetNum#(3, LocateCol + 10)
 298: 
 299:   IF PlayerNum = 2 THEN
 300:     Angle# = 180 - Angle#
 301:   END IF
 302: 
 303:   'Erase input
 304:   FOR i = 1 TO 4
 305:     LOCATE i, 1
 306:     PRINT SPACE$(30 \ (80 \ MaxCol));
 307:     LOCATE i, (50 \ (80 \ MaxCol))
 308:     PRINT SPACE$(30 \ (80 \ MaxCol));
 309:   NEXT
 310: 
 311:   SunHit = FALSE
 312:   PlayerHit = PlotShot(x, y, Angle#, Velocity, PlayerNum)
 313:   IF PlayerHit = 0 THEN
 314:     DoShot = FALSE
 315:   ELSE
 316:     DoShot = TRUE
 317:     IF PlayerHit = PlayerNum THEN PlayerNum = 3 - PlayerNum
 318:     VictoryDance PlayerNum
 319:   END IF
 320: 
 321: END FUNCTION
 322: 
 323: ' DoSun:
 324: '   Draws the sun at the top of the screen.
 325: ' Parameters:
 326: '   Mouth - If TRUE draws "O" mouth else draws a smile mouth.
 327: '
 328: SUB DoSun (Mouth)
 329: 
 330:   'set position of sun
 331:   x = ScrWidth \ 2: y = Scl(25)
 332: 
 333:   'clear old sun
 334:   LINE (x - Scl(22), y - Scl(18))-(x + Scl(22), y + Scl(18)), BACKATTR, BF
 335: 
 336:   'draw new sun:
 337:   'body
 338:   CIRCLE (x, y), Scl(12), SUNATTR
 339:   PAINT (x, y), SUNATTR
 340: 
 341:   'rays
 342:   LINE (x - Scl(20), y)-(x + Scl(20), y), SUNATTR
 343:   LINE (x, y - Scl(15))-(x, y + Scl(15)), SUNATTR
 344: 
 345:   LINE (x - Scl(15), y - Scl(10))-(x + Scl(15), y + Scl(10)), SUNATTR
 346:   LINE (x - Scl(15), y + Scl(10))-(x + Scl(15), y - Scl(10)), SUNATTR
 347: 
 348:   LINE (x - Scl(8), y - Scl(13))-(x + Scl(8), y + Scl(13)), SUNATTR
 349:   LINE (x - Scl(8), y + Scl(13))-(x + Scl(8), y - Scl(13)), SUNATTR
 350: 
 351:   LINE (x - Scl(18), y - Scl(5))-(x + Scl(18), y + Scl(5)), SUNATTR
 352:   LINE (x - Scl(18), y + Scl(5))-(x + Scl(18), y - Scl(5)), SUNATTR
 353: 
 354:   'mouth
 355:   IF Mouth THEN  'draw "o" mouth
 356:     CIRCLE (x, y + Scl(5)), Scl(2.9), 0
 357:     PAINT (x, y + Scl(5)), 0, 0
 358:   ELSE           'draw smile
 359:     CIRCLE (x, y), Scl(8), 0, (210 * pi# / 180), (330 * pi# / 180)
 360:   END IF
 361: 
 362:   'eyes
 363:   CIRCLE (x - 3, y - 2), 1, 0
 364:   CIRCLE (x + 3, y - 2), 1, 0
 365:   PSET (x - 3, y - 2), 0
 366:   PSET (x + 3, y - 2), 0
 367: 
 368: END SUB
 369: 
 370: 'DrawBan:
 371: '  Draws the banana
 372: 'Parameters:
 373: '  xc# - Horizontal Coordinate
 374: '  yc# - Vertical Coordinate
 375: '  r - rotation position (0-3). (  \_/  ) /-\
 376: '  bc - if TRUE then DrawBan draws the banana ELSE it erases the banana
 377: SUB DrawBan (xc#, yc#, r, bc)
 378: 
 379: SELECT CASE r
 380:   CASE 0
 381:     IF bc THEN PUT (xc#, yc#), LBan&, PSET ELSE PUT (xc#, yc#), LBan&, XOR
 382:   CASE 1
 383:     IF bc THEN PUT (xc#, yc#), UBan&, PSET ELSE PUT (xc#, yc#), UBan&, XOR
 384:   CASE 2
 385:     IF bc THEN PUT (xc#, yc#), DBan&, PSET ELSE PUT (xc#, yc#), DBan&, XOR
 386:   CASE 3
 387:     IF bc THEN PUT (xc#, yc#), RBan&, PSET ELSE PUT (xc#, yc#), RBan&, XOR
 388: END SELECT
 389: 
 390: END SUB
 391: 
 392: 'DrawGorilla:
 393: '  Draws the Gorilla in either CGA or EGA mode
 394: '  and saves the graphics data in an array.
 395: 'Parameters:
 396: '  x - x coordinate of gorilla
 397: '  y - y coordinate of the gorilla
 398: '  arms - either Left up, Right up, or both down
 399: SUB DrawGorilla (x, y, arms)
 400:   DIM i AS SINGLE   ' Local index must be single precision
 401: 
 402:   'draw head
 403:   LINE (x - Scl(4), y)-(x + Scl(2.9), y + Scl(6)), OBJECTCOLOR, BF
 404:   LINE (x - Scl(5), y + Scl(2))-(x + Scl(4), y + Scl(4)), OBJECTCOLOR, BF
 405: 
 406:   'draw eyes/brow
 407:   LINE (x - Scl(3), y + Scl(2))-(x + Scl(2), y + Scl(2)), 0
 408: 
 409:   'draw nose if ega
 410:   IF Mode = 9 THEN
 411:     FOR i = -2 TO -1
 412:       PSET (x + i, y + 4), 0
 413:       PSET (x + i + 3, y + 4), 0
 414:     NEXT i
 415:   END IF
 416: 
 417:   'neck
 418:   LINE (x - Scl(3), y + Scl(7))-(x + Scl(2), y + Scl(7)), OBJECTCOLOR
 419: 
 420:   'body
 421:   LINE (x - Scl(8), y + Scl(8))-(x + Scl(6.9), y + Scl(14)), OBJECTCOLOR, BF
 422:   LINE (x - Scl(6), y + Scl(15))-(x + Scl(4.9), y + Scl(20)), OBJECTCOLOR, BF
 423: 
 424:   'legs
 425:   FOR i = 0 TO 4
 426:     CIRCLE (x + Scl(i), y + Scl(25)), Scl(10), OBJECTCOLOR, 3 * pi# / 4, 9 * pi# / 8
 427:     CIRCLE (x + Scl(-6) + Scl(i - .1), y + Scl(25)), Scl(10), OBJECTCOLOR, 15 * pi# / 8, pi# / 4
 428:   NEXT
 429: 
 430:   'chest
 431:   CIRCLE (x - Scl(4.9), y + Scl(10)), Scl(4.9), 0, 3 * pi# / 2, 0
 432:   CIRCLE (x + Scl(4.9), y + Scl(10)), Scl(4.9), 0, pi#, 3 * pi# / 2
 433: 
 434:   FOR i = -5 TO -1
 435:     SELECT CASE arms
 436:       CASE 1
 437:         'Right arm up
 438:         CIRCLE (x + Scl(i - .1), y + Scl(14)), Scl(9), OBJECTCOLOR, 3 * pi# / 4, 5 * pi# / 4
 439:         CIRCLE (x + Scl(4.9) + Scl(i), y + Scl(4)), Scl(9), OBJECTCOLOR, 7 * pi# / 4, pi# / 4
 440:         GET (x - Scl(15), y - Scl(1))-(x + Scl(14), y + Scl(28)), GorR&
 441:       CASE 2
 442:         'Left arm up
 443:         CIRCLE (x + Scl(i - .1), y + Scl(4)), Scl(9), OBJECTCOLOR, 3 * pi# / 4, 5 * pi# / 4
 444:         CIRCLE (x + Scl(4.9) + Scl(i), y + Scl(14)), Scl(9), OBJECTCOLOR, 7 * pi# / 4, pi# / 4
 445:         GET (x - Scl(15), y - Scl(1))-(x + Scl(14), y + Scl(28)), GorL&
 446:       CASE 3
 447:         'Both arms down
 448:         CIRCLE (x + Scl(i - .1), y + Scl(14)), Scl(9), OBJECTCOLOR, 3 * pi# / 4, 5 * pi# / 4
 449:         CIRCLE (x + Scl(4.9) + Scl(i), y + Scl(14)), Scl(9), OBJECTCOLOR, 7 * pi# / 4, pi# / 4
 450:         GET (x - Scl(15), y - Scl(1))-(x + Scl(14), y + Scl(28)), GorD&
 451:     END SELECT
 452:   NEXT i
 453: END SUB
 454: 
 455: 'ExplodeGorilla:
 456: '  Causes gorilla explosion when a direct hit occurs
 457: 'Parameters:
 458: '  X#, Y# - shot location
 459: FUNCTION ExplodeGorilla (x#, y#)
 460:   YAdj = Scl(12)
 461:   XAdj = Scl(5)
 462:   SclX# = ScrWidth / 320
 463:   SclY# = ScrHeight / 200
 464:   IF x# < ScrWidth / 2 THEN PlayerHit = 1 ELSE PlayerHit = 2
 465:   PLAY "MBO0L16EFGEFDC"
 466: 
 467:   FOR i = 1 TO 8 * SclX#
 468:     CIRCLE (GorillaX(PlayerHit) + 3.5 * SclX# + XAdj, GorillaY(PlayerHit) + 7 * SclY# + YAdj), i, ExplosionColor, , , -1.57
 469:     LINE (GorillaX(PlayerHit) + 7 * SclX#, GorillaY(PlayerHit) + 9 * SclY# - i)-(GorillaX(PlayerHit), GorillaY(PlayerHit) + 9 * SclY# - i), ExplosionColor
 470:   NEXT i
 471: 
 472:   FOR i = 1 TO 16 * SclX#
 473:     IF i < (8 * SclX#) THEN CIRCLE (GorillaX(PlayerHit) + 3.5 * SclX# + XAdj, GorillaY(PlayerHit) + 7 * SclY# + YAdj), (8 * SclX# + 1) - i, BACKATTR, , , -1.57
 474:     CIRCLE (GorillaX(PlayerHit) + 3.5 * SclX# + XAdj, GorillaY(PlayerHit) + YAdj), i, i MOD 2 + 1, , , -1.57
 475:   NEXT i
 476: 
 477:   FOR i = 24 * SclX# TO 1 STEP -1
 478:     CIRCLE (GorillaX(PlayerHit) + 3.5 * SclX# + XAdj, GorillaY(PlayerHit) + YAdj), i, BACKATTR, , , -1.57
 479:     FOR Count = 1 TO 200
 480:     NEXT
 481:   NEXT i
 482: 
 483:   ExplodeGorilla = PlayerHit
 484: END FUNCTION
 485: 
 486: 'GetInputs:
 487: '  Gets user inputs at beginning of game
 488: 'Parameters:
 489: '  Player1$, Player2$ - player names
 490: '  NumGames - number of games to play
 491: SUB GetInputs (Player1$, Player2$, NumGames)
 492:   COLOR 7, 0
 493:   CLS
 494: 
 495:   LOCATE 8, 15
 496:   LINE INPUT "Name of Player 1 (Default = 'Player 1'): "; Player1$
 497:   IF Player1$ = "" THEN
 498:     Player1$ = "Player 1"
 499:   ELSE
 500:     Player1$ = LEFT$(Player1$, 10)
 501:   END IF
 502: 
 503:   LOCATE 10, 15
 504:   LINE INPUT "Name of Player 2 (Default = 'Player 2'): "; Player2$
 505:   IF Player2$ = "" THEN
 506:     Player2$ = "Player 2"
 507:   ELSE
 508:     Player2$ = LEFT$(Player2$, 10)
 509:   END IF
 510: 
 511:   DO
 512:     LOCATE 12, 56: PRINT SPACE$(25);
 513:     LOCATE 12, 13
 514:     INPUT "Play to how many total points (Default = 3)"; game$
 515:     NumGames = VAL(LEFT$(game$, 2))
 516:   LOOP UNTIL NumGames > 0 AND LEN(game$) < 3 OR LEN(game$) = 0
 517:   IF NumGames = 0 THEN NumGames = 3
 518: 
 519:   DO
 520:     LOCATE 14, 53: PRINT SPACE$(28);
 521:     LOCATE 14, 17
 522:     INPUT "Gravity in Meters/Sec (Earth = 9.8)"; grav$
 523:     gravity# = VAL(grav$)
 524:   LOOP UNTIL gravity# > 0 OR LEN(grav$) = 0
 525:   IF gravity# = 0 THEN gravity# = 9.8
 526: END SUB
 527: 
 528: 'GetNum:
 529: '  Gets valid numeric input from user
 530: 'Parameters:
 531: '  Row, Col - location to echo input
 532: FUNCTION GetNum# (Row, Col)
 533:   Result$ = ""
 534:   Done = FALSE
 535:   WHILE INKEY$ <> "": WEND   'Clear keyboard buffer
 536: 
 537:   DO WHILE NOT Done
 538: 
 539:     LOCATE Row, Col
 540:     PRINT Result$; CHR$(95); "    ";
 541: 
 542:     Kbd$ = INKEY$
 543:     SELECT CASE Kbd$
 544:       CASE "0" TO "9"
 545:         Result$ = Result$ + Kbd$
 546:       CASE "."
 547:         IF INSTR(Result$, ".") = 0 THEN
 548:           Result$ = Result$ + Kbd$
 549:         END IF
 550:       CASE CHR$(13)
 551:         IF VAL(Result$) > 360 THEN
 552:           Result$ = ""
 553:         ELSE
 554:           Done = TRUE
 555:         END IF
 556:       CASE CHR$(8)
 557:         IF LEN(Result$) > 0 THEN
 558:           Result$ = LEFT$(Result$, LEN(Result$) - 1)
 559:         END IF
 560:       CASE ELSE
 561:         IF LEN(Kbd$) > 0 THEN
 562:           BEEP
 563:         END IF
 564:       END SELECT
 565:   LOOP
 566: 
 567:   LOCATE Row, Col
 568:   PRINT Result$; " ";
 569: 
 570:   GetNum# = VAL(Result$)
 571: END FUNCTION
 572: 
 573: 'GorillaIntro:
 574: '  Displays gorillas on screen for the first time
 575: '  allows the graphical data to be put into an array
 576: 'Parameters:
 577: '  Player1$, Player2$ - The names of the players
 578: '
 579: SUB GorillaIntro (Player1$, Player2$)
 580:   LOCATE 16, 34: PRINT "--------------"
 581:   LOCATE 18, 34: PRINT "V = View Intro"
 582:   LOCATE 19, 34: PRINT "P = Play Game"
 583:   LOCATE 21, 35: PRINT "Your Choice?"
 584: 
 585:   DO WHILE Char$ = ""
 586:     Char$ = INKEY$
 587:   LOOP
 588: 
 589:   IF Mode = 1 THEN
 590:     x = 125
 591:     y = 100
 592:   ELSE
 593:     x = 278
 594:     y = 175
 595:   END IF
 596: 
 597:   SCREEN Mode
 598:   SetScreen
 599: 
 600:   IF Mode = 1 THEN Center 5, "Please wait while gorillas are drawn."
 601: 
 602:   VIEW PRINT 9 TO 24
 603: 
 604:   IF Mode = 9 THEN PALETTE OBJECTCOLOR, BackColor
 605:  
 606:   DrawGorilla x, y, ARMSDOWN
 607:   CLS 2
 608:   DrawGorilla x, y, LEFTUP
 609:   CLS 2
 610:   DrawGorilla x, y, RIGHTUP
 611:   CLS 2
 612:  
 613:   VIEW PRINT 1 TO 25
 614:   IF Mode = 9 THEN PALETTE OBJECTCOLOR, 46
 615:  
 616:   IF UCASE$(Char$) = "V" THEN
 617:     Center 2, "Q B A S I C   G O R I L L A S"
 618:     Center 5, "             STARRING:               "
 619:     P$ = Player1$ + " AND " + Player2$
 620:     Center 7, P$
 621: 
 622:     PUT (x - 13, y), GorD&, PSET
 623:     PUT (x + 47, y), GorD&, PSET
 624:     Rest 1
 625: 
 626:     PUT (x - 13, y), GorL&, PSET
 627:     PUT (x + 47, y), GorR&, PSET
 628:     PLAY "t120o1l16b9n0baan0bn0bn0baaan0b9n0baan0b"
 629:     Rest .3
 630: 
 631:     PUT (x - 13, y), GorR&, PSET
 632:     PUT (x + 47, y), GorL&, PSET
 633:     PLAY "o2l16e-9n0e-d-d-n0e-n0e-n0e-d-d-d-n0e-9n0e-d-d-n0e-"
 634:     Rest .3
 635: 
 636:     PUT (x - 13, y), GorL&, PSET
 637:     PUT (x + 47, y), GorR&, PSET
 638:     PLAY "o2l16g-9n0g-een0g-n0g-n0g-eeen0g-9n0g-een0g-"
 639:     Rest .3
 640: 
 641:     PUT (x - 13, y), GorR&, PSET
 642:     PUT (x + 47, y), GorL&, PSET
 643:     PLAY "o2l16b9n0baan0g-n0g-n0g-eeen0o1b9n0baan0b"
 644:     Rest .3
 645: 
 646:     FOR i = 1 TO 4
 647:       PUT (x - 13, y), GorL&, PSET
 648:       PUT (x + 47, y), GorR&, PSET
 649:       PLAY "T160O0L32EFGEFDC"
 650:       Rest .1
 651:       PUT (x - 13, y), GorR&, PSET
 652:       PUT (x + 47, y), GorL&, PSET
 653:       PLAY "T160O0L32EFGEFDC"
 654:       Rest .1
 655:     NEXT
 656:   END IF
 657: END SUB
 658: 
 659: 'Intro:
 660: '  Displays game introduction
 661: SUB Intro
 662: 
 663:   SCREEN 0
 664:   WIDTH 80, 25
 665:   MaxCol = 80
 666:   COLOR 15, 0
 667:   CLS
 668: 
 669:   Center 4, "Q B a s i c    G O R I L L A S"
 670:   COLOR 7
 671:   Center 6, "Copyright (C) Microsoft Corporation 1990"
 672:   Center 8, "Your mission is to hit your opponent with the exploding"
 673:   Center 9, "banana by varying the angle and power of your throw, taking"
 674:   Center 10, "into account wind speed, gravity, and the city skyline."
 675:   Center 11, "The wind speed is shown by a directional arrow at the bottom"
 676:   Center 12, "of the playing field, its length relative to its strength."
 677:   Center 24, "Press any key to continue"
 678: 
 679:   PLAY "MBT160O1L8CDEDCDL4ECC"
 680:   SparklePause
 681:   IF Mode = 1 THEN MaxCol = 40
 682: END SUB
 683: 
 684: 'MakeCityScape:
 685: '  Creates random skyline for game
 686: 'Parameters:
 687: '  BCoor() - a user-defined type array which stores the coordinates of
 688: '  the upper left corner of each building.
 689: SUB MakeCityScape (BCoor() AS XYPoint)
 690: 
 691:   x = 2
 692: 
 693:   'Set the sloping trend of the city scape. NewHt is new building height
 694:   Slope = FnRan(6)
 695:   SELECT CASE Slope
 696:     CASE 1: NewHt = 15                 'Upward slope
 697:     CASE 2: NewHt = 130                'Downward slope
 698:     CASE 3 TO 5: NewHt = 15            '"V" slope - most common
 699:     CASE 6: NewHt = 130                'Inverted "V" slope
 700:   END SELECT
 701: 
 702:   IF Mode = 9 THEN
 703:     BottomLine = 335                   'Bottom of building
 704:     HtInc = 10                         'Increase value for new height
 705:     DefBWidth = 37                     'Default building height
 706:     RandomHeight = 120                 'Random height difference
 707:     WWidth = 3                         'Window width
 708:     WHeight = 6                        'Window height
 709:     WDifV = 15                         'Counter for window spacing - vertical
 710:     WDifh = 10                         'Counter for window spacing - horizontal
 711:   ELSE
 712:     BottomLine = 190
 713:     HtInc = 6
 714:     NewHt = NewHt * 20 \ 35            'Adjust for CGA
 715:     DefBWidth = 18
 716:     RandomHeight = 54
 717:     WWidth = 1
 718:     WHeight = 2
 719:     WDifV = 5
 720:     WDifh = 4
 721:   END IF
 722: 
 723:   CurBuilding = 1
 724:   DO
 725: 
 726:     SELECT CASE Slope
 727:       CASE 1
 728:         NewHt = NewHt + HtInc
 729:       CASE 2
 730:         NewHt = NewHt - HtInc
 731:       CASE 3 TO 5
 732:         IF x > ScrWidth \ 2 THEN
 733:           NewHt = NewHt - 2 * HtInc
 734:         ELSE
 735:           NewHt = NewHt + 2 * HtInc
 736:         END IF
 737:       CASE 4
 738:         IF x > ScrWidth \ 2 THEN
 739:           NewHt = NewHt + 2 * HtInc
 740:         ELSE
 741:           NewHt = NewHt - 2 * HtInc
 742:         END IF
 743:     END SELECT
 744: 
 745:     'Set width of building and check to see if it would go off the screen
 746:     BWidth = FnRan(DefBWidth) + DefBWidth
 747:     IF x + BWidth > ScrWidth THEN BWidth = ScrWidth - x - 2
 748: 
 749:     'Set height of building and check to see if it goes below screen
 750:     BHeight = FnRan(RandomHeight) + NewHt
 751:     IF BHeight < HtInc THEN BHeight = HtInc
 752: 
 753:     'Check to see if Building is too high
 754:     IF BottomLine - BHeight <= MaxHeight + GHeight THEN BHeight = MaxHeight + GHeight - 5
 755: 
 756:     'Set the coordinates of the building into the array
 757:     BCoor(CurBuilding).XCoor = x
 758:     BCoor(CurBuilding).YCoor = BottomLine - BHeight
 759: 
 760:     IF Mode = 9 THEN BuildingColor = FnRan(3) + 4 ELSE BuildingColor = 2
 761: 
 762:     'Draw the building, outline first, then filled
 763:     LINE (x - 1, BottomLine + 1)-(x + BWidth + 1, BottomLine - BHeight - 1), BACKGROUND, B
 764:     LINE (x, BottomLine)-(x + BWidth, BottomLine - BHeight), BuildingColor, BF
 765: 
 766:     'Draw the windows
 767:     c = x + 3
 768:     DO
 769:       FOR i = BHeight - 3 TO 7 STEP -WDifV
 770:         IF Mode <> 9 THEN
 771:           WinColr = (FnRan(2) - 2) * -3
 772:         ELSEIF FnRan(4) = 1 THEN
 773:           WinColr = 8
 774:         ELSE
 775:           WinColr = WINDOWCOLOR
 776:         END IF
 777:         LINE (c, BottomLine - i)-(c + WWidth, BottomLine - i + WHeight), WinColr, BF
 778:       NEXT
 779:       c = c + WDifh
 780:     LOOP UNTIL c >= x + BWidth - 3
 781: 
 782:     x = x + BWidth + 2
 783: 
 784:     CurBuilding = CurBuilding + 1
 785: 
 786:   LOOP UNTIL x > ScrWidth - HtInc
 787: 
 788:   LastBuilding = CurBuilding - 1
 789: 
 790:   'Set Wind speed
 791:   Wind = FnRan(10) - 5
 792:   IF FnRan(3) = 1 THEN
 793:     IF Wind > 0 THEN
 794:       Wind = Wind + FnRan(10)
 795:     ELSE
 796:       Wind = Wind - FnRan(10)
 797:     END IF
 798:   END IF
 799: 
 800:   'Draw Wind speed arrow
 801:   IF Wind <> 0 THEN
 802:     WindLine = Wind * 3 * (ScrWidth \ 320)
 803:     LINE (ScrWidth \ 2, ScrHeight - 5)-(ScrWidth \ 2 + WindLine, ScrHeight - 5), ExplosionColor
 804:     IF Wind > 0 THEN ArrowDir = -2 ELSE ArrowDir = 2
 805:     LINE (ScrWidth / 2 + WindLine, ScrHeight - 5)-(ScrWidth / 2 + WindLine + ArrowDir, ScrHeight - 5 - 2), ExplosionColor
 806:     LINE (ScrWidth / 2 + WindLine, ScrHeight - 5)-(ScrWidth / 2 + WindLine + ArrowDir, ScrHeight - 5 + 2), ExplosionColor
 807:   END IF
 808: END SUB
 809: 
 810: 'PlaceGorillas:
 811: '  PUTs the Gorillas on top of the buildings.  Must have drawn
 812: '  Gorillas first.
 813: 'Parameters:
 814: '  BCoor() - user-defined TYPE array which stores upper left coordinates
 815: '  of each building.
 816: SUB PlaceGorillas (BCoor() AS XYPoint)
 817:     
 818:   IF Mode = 9 THEN
 819:     XAdj = 14
 820:     YAdj = 30
 821:   ELSE
 822:     XAdj = 7
 823:     YAdj = 16
 824:   END IF
 825:   SclX# = ScrWidth / 320
 826:   SclY# = ScrHeight / 200
 827:     
 828:   'Place gorillas on second or third building from edge
 829:   FOR i = 1 TO 2
 830:     IF i = 1 THEN BNum = FnRan(2) + 1 ELSE BNum = LastBuilding - FnRan(2)
 831: 
 832:     BWidth = BCoor(BNum + 1).XCoor - BCoor(BNum).XCoor
 833:     GorillaX(i) = BCoor(BNum).XCoor + BWidth / 2 - XAdj
 834:     GorillaY(i) = BCoor(BNum).YCoor - YAdj
 835:     PUT (GorillaX(i), GorillaY(i)), GorD&, PSET
 836:   NEXT i
 837: 
 838: END SUB
 839: 
 840: 'PlayGame:
 841: '  Main game play routine
 842: 'Parameters:
 843: '  Player1$, Player2$ - player names
 844: '  NumGames - number of games to play
 845: SUB PlayGame (Player1$, Player2$, NumGames)
 846:   DIM BCoor(0 TO 30) AS XYPoint
 847:   DIM TotalWins(1 TO 2)
 848: 
 849:   J = 1
 850:   
 851:   FOR i = 1 TO NumGames
 852:     
 853:     CLS
 854:     RANDOMIZE (TIMER)
 855:     CALL MakeCityScape(BCoor())
 856:     CALL PlaceGorillas(BCoor())
 857:     DoSun SUNHAPPY
 858:     Hit = FALSE
 859:     DO WHILE Hit = FALSE
 860:       J = 1 - J
 861:       LOCATE 1, 1
 862:       PRINT Player1$
 863:       LOCATE 1, (MaxCol - 1 - LEN(Player2$))
 864:       PRINT Player2$
 865:       Center 23, LTRIM$(STR$(TotalWins(1))) + ">Score<" + LTRIM$(STR$(TotalWins(2)))
 866:       Tosser = J + 1: Tossee = 3 - J
 867: 
 868:       'Plot the shot.  Hit is true if Gorilla gets hit.
 869:       Hit = DoShot(Tosser, GorillaX(Tosser), GorillaY(Tosser))
 870: 
 871:       'Reset the sun, if it got hit
 872:       IF SunHit THEN DoSun SUNHAPPY
 873: 
 874:       IF Hit = TRUE THEN CALL UpdateScores(TotalWins(), Tosser, Hit)
 875:     LOOP
 876:     SLEEP 1
 877:   NEXT i
 878: 
 879:   SCREEN 0
 880:   WIDTH 80, 25
 881:   COLOR 7, 0
 882:   MaxCol = 80
 883:   CLS
 884: 
 885:   Center 8, "GAME OVER!"
 886:   Center 10, "Score:"
 887:   LOCATE 11, 30: PRINT Player1$; TAB(50); TotalWins(1)
 888:   LOCATE 12, 30: PRINT Player2$; TAB(50); TotalWins(2)
 889:   Center 24, "Press any key to continue"
 890:   SparklePause
 891:   COLOR 7, 0
 892:   CLS
 893: END SUB
 894: 
 895: 'PlayGame:
 896: '  Plots banana shot across the screen
 897: 'Parameters:
 898: '  StartX, StartY - starting shot location
 899: '  Angle - shot angle
 900: '  Velocity - shot velocity
 901: '  PlayerNum - the banana thrower
 902: FUNCTION PlotShot (StartX, StartY, Angle#, Velocity, PlayerNum)
 903: 
 904:   Angle# = Angle# / 180 * pi#  'Convert degree angle to radians
 905:   Radius = Mode MOD 7
 906: 
 907:   InitXVel# = COS(Angle#) * Velocity
 908:   InitYVel# = SIN(Angle#) * Velocity
 909: 
 910:   oldx# = StartX
 911:   oldy# = StartY
 912: 
 913:   'draw gorilla toss
 914:   IF PlayerNum = 1 THEN
 915:     PUT (StartX, StartY), GorL&, PSET
 916:   ELSE
 917:     PUT (StartX, StartY), GorR&, PSET
 918:   END IF
 919:   
 920:   'throw sound
 921:   PLAY "MBo0L32A-L64CL16BL64A+"
 922:   Rest .1
 923: 
 924:   'redraw gorilla
 925:   PUT (StartX, StartY), GorD&, PSET
 926: 
 927:   adjust = Scl(4)                   'For scaling CGA
 928: 
 929:   xedge = Scl(9) * (2 - PlayerNum)  'Find leading edge of banana for check
 930: 
 931:   Impact = FALSE
 932:   ShotInSun = FALSE
 933:   OnScreen = TRUE
 934:   PlayerHit = 0
 935:   NeedErase = FALSE
 936: 
 937:   StartXPos = StartX
 938:   StartYPos = StartY - adjust - 3
 939: 
 940:   IF PlayerNum = 2 THEN
 941:     StartXPos = StartXPos + Scl(25)
 942:     direction = Scl(4)
 943:   ELSE
 944:     direction = Scl(-4)
 945:   END IF
 946: 
 947:   IF Velocity < 2 THEN              'Shot too slow - hit self
 948:     x# = StartX
 949:     y# = StartY
 950:     pointval = OBJECTCOLOR
 951:   END IF
 952:    
 953:   DO WHILE (NOT Impact) AND OnScreen
 954:  
 955:   Rest .02
 956: 
 957:   'Erase old banana, if necessary
 958:   IF NeedErase THEN
 959:     NeedErase = FALSE
 960:     CALL DrawBan(oldx#, oldy#, oldrot, FALSE)
 961:   END IF
 962: 
 963:   x# = StartXPos + (InitXVel# * t#) + (.5 * (Wind / 5) * t# ^ 2)
 964:   y# = StartYPos + ((-1 * (InitYVel# * t#)) + (.5 * gravity# * t# ^ 2)) * (ScrHeight / 350)
 965:          
 966:   IF (x# >= ScrWidth - Scl(10)) OR (x# <= 3) OR (y# >= ScrHeight - 3) THEN
 967:     OnScreen = FALSE
 968:   END IF
 969: 
 970:           
 971:   IF OnScreen AND y# > 0 THEN
 972: 
 973:     'check it
 974:     LookY = 0
 975:     LookX = Scl(8 * (2 - PlayerNum))
 976:     DO
 977:       pointval = POINT(x# + LookX, y# + LookY)
 978:       IF pointval = 0 THEN
 979:         Impact = FALSE
 980:         IF ShotInSun = TRUE THEN
 981:           IF ABS(ScrWidth \ 2 - x#) > Scl(20) OR y# > SunHt THEN ShotInSun = FALSE
 982:         END IF
 983:       ELSEIF pointval = SUNATTR AND y# < SunHt THEN
 984:         IF NOT SunHit THEN DoSun SUNSHOCK
 985:         SunHit = TRUE
 986:         ShotInSun = TRUE
 987:       ELSE
 988:         Impact = TRUE
 989:       END IF
 990:       LookX = LookX + direction
 991:       LookY = LookY + Scl(6)
 992:     LOOP UNTIL Impact OR LookX <> Scl(4)
 993:    
 994:     IF NOT ShotInSun AND NOT Impact THEN
 995:       'plot it
 996:       rot = (t# * 10) MOD 4
 997:       CALL DrawBan(x#, y#, rot, TRUE)
 998:       NeedErase = TRUE
 999:     END IF
1000:             
1001:     oldx# = x#
1002:     oldy# = y#
1003:     oldrot = rot
1004: 
1005:   END IF
1006: 
1007:       
1008:   t# = t# + .1
1009: 
1010:   LOOP
1011: 
1012:   IF pointval <> OBJECTCOLOR AND Impact THEN
1013:     CALL DoExplosion(x# + adjust, y# + adjust)
1014:   ELSEIF pointval = OBJECTCOLOR THEN
1015:     PlayerHit = ExplodeGorilla(x#, y#)
1016:   END IF
1017: 
1018:   PlotShot = PlayerHit
1019: 
1020: END FUNCTION
1021: 
1022: 'Rest:
1023: '  pauses the program
1024: SUB Rest (t#)
1025:   s# = TIMER
1026:   t2# = MachSpeed * t# / SPEEDCONST
1027:   DO
1028:   LOOP UNTIL TIMER - s# > t2#
1029: END SUB
1030: 
1031: 'Scl:
1032: '  Pass the number in to scaling for cga.  If the number is a decimal, then we
1033: '  want to scale down for cga or scale up for ega.  This allows a full range
1034: '  of numbers to be generated for scaling.
1035: '  (i.e. for 3 to get scaled to 1, pass in 2.9)
1036: FUNCTION Scl (n!)
1037: 
1038:   IF n! <> INT(n!) THEN
1039:       IF Mode = 1 THEN n! = n! - 1
1040:   END IF
1041:   IF Mode = 1 THEN
1042:       Scl = CINT(n! / 2 + .1)
1043:   ELSE
1044:       Scl = CINT(n!)
1045:   END IF
1046: 
1047: END FUNCTION
1048: 
1049: 'SetScreen:
1050: '  Sets the appropriate color statements
1051: SUB SetScreen
1052: 
1053:   IF Mode = 9 THEN
1054:     ExplosionColor = 2
1055:     BackColor = 1
1056:     PALETTE 0, 1
1057:     PALETTE 1, 46
1058:     PALETTE 2, 44
1059:     PALETTE 3, 54
1060:     PALETTE 5, 7
1061:     PALETTE 6, 4
1062:     PALETTE 7, 3
1063:     PALETTE 9, 63       'Display Color
1064:   ELSE
1065:     ExplosionColor = 2
1066:     BackColor = 0
1067:     COLOR BackColor, 2
1068: 
1069:   END IF
1070: 
1071: END SUB
1072: 
1073: 'SparklePause:
1074: '  Creates flashing border for intro and game over screens
1075: SUB SparklePause
1076: 
1077:   COLOR 4, 0
1078:   A$ = "*    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    "
1079:   WHILE INKEY$ <> "": WEND 'Clear keyboard buffer
1080: 
1081:   WHILE INKEY$ = ""
1082:     FOR A = 1 TO 5
1083:       LOCATE 1, 1                             'print horizontal sparkles
1084:       PRINT MID$(A$, A, 80);
1085:       LOCATE 22, 1
1086:       PRINT MID$(A$, 6 - A, 80);
1087: 
1088:       FOR b = 2 TO 21                         'Print Vertical sparkles
1089:         c = (A + b) MOD 5
1090:         IF c = 1 THEN
1091:           LOCATE b, 80
1092:           PRINT "*";
1093:           LOCATE 23 - b, 1
1094:           PRINT "*";
1095:         ELSE
1096:           LOCATE b, 80
1097:           PRINT " ";
1098:           LOCATE 23 - b, 1
1099:           PRINT " ";
1100:         END IF
1101:       NEXT b
1102:     NEXT A
1103:   WEND
1104: END SUB
1105: 
1106: 'UpdateScores:
1107: '  Updates players' scores
1108: 'Parameters:
1109: '  Record - players' scores
1110: '  PlayerNum - player
1111: '  Results - results of player's shot
1112: SUB UpdateScores (Record(), PlayerNum, Results)
1113:   IF Results = HITSELF THEN
1114:     Record(ABS(PlayerNum - 3)) = Record(ABS(PlayerNum - 3)) + 1
1115:   ELSE
1116:     Record(PlayerNum) = Record(PlayerNum) + 1
1117:   END IF
1118: END SUB
1119: 
1120: 'VictoryDance:
1121: '  gorilla dances after he has eliminated his opponent
1122: 'Parameters:
1123: '  Player - which gorilla is dancing
1124: SUB VictoryDance (Player)
1125: 
1126:   FOR i# = 1 TO 4
1127:     PUT (GorillaX(Player), GorillaY(Player)), GorL&, PSET
1128:     PLAY "MFO0L32EFGEFDC"
1129:     Rest .2
1130:     PUT (GorillaX(Player), GorillaY(Player)), GorR&, PSET
1131:     PLAY "MFO0L32EFGEFDC"
1132:     Rest .2
1133:   NEXT
1134: END SUB
1135: 
5748216 [rkeene@sledge /home/rkeene/devel/archive/quickbasic]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2000-05-09 21:04:59