home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 7 Games / 07-Games.zip / meteor.zip / meteor.cmd < prev    next >
OS/2 REXX Batch file  |  1996-01-23  |  22KB  |  772 lines

  1. /* REXX */
  2. /* Title : Meteor                                           */
  3. /* Desc  : A simple action game                             */
  4. /* Author: Jeff Byrd, jeff.byrd@mcmail.vanderbilt.edu       */
  5. /* Date  : 12/22/95                                         */
  6. /*                                                          */
  7. /* Notes : If you run this program from a mapped network    */
  8. /*         drive, the high score list and demos will be     */
  9. /*         shared among all the players.                    */
  10. /*         Make sure to note all the hints on how to play.  */
  11. /*         To clear the high score/demo list, delete all    */
  12. /*         *.MSV files.                                     */
  13.  
  14. parse arg g.commLine
  15. g.commLine = translate(g.commLine)
  16. g.commLine = translate(g.commLine, "-", "/")
  17.  
  18. signal on halt            /* trap all Ctrl-Break, Ctrl-C */
  19.  
  20. call init                 /* initialize globals */
  21.  
  22. /* Main Loop */
  23. do until decision = "Q"
  24.   call doTitleSequence
  25.   decision = getDecision()
  26.   if decision = "P" then
  27.     call playGame
  28.   else if decision = "D" then
  29.     call playDemo
  30. end
  31.  
  32. call cleanUp
  33.  
  34. exit
  35.  
  36. init: procedure expose g.
  37. /* This procedure loads all libraries, starts sound, draws game items */
  38.  
  39.   /* load rexxutil functions */
  40.   call RxFuncAdd "SysLoadFuncs",  "RexxUtil", "SysLoadFuncs"
  41.   call SysLoadFuncs
  42.  
  43.   /* select a directory for temporary files - if run from a network drive, put temp on local drive */
  44.   currDrive = filespec("drive", directory())
  45.   map = SysDriveMap("c:", "remote")
  46.   if pos(currDrive, map) \= 0 then do        /* if being run from a network drive, make tmpDir on a local drive */
  47.     g.tmpDir = value("TMP",, "OS2ENVIRONMENT")
  48.     if g.tmpDir = "" then
  49.       g.tmpDir = "c:\"
  50.     else do
  51.       if right(g.tmpDir, 1) = ";" then
  52.         g.tmpDir = substr(g.tmpDir, 1, length(tmpDir)-1)
  53.       if right(g.tmpDir, 1) \= "\" then
  54.         g.tmpDir = g.tmpDir||"\"
  55.     end
  56.   end
  57.   else
  58.     g.tmpDir = ".\"
  59.  
  60.   /* start the sound if the PC is equipped */
  61.   g.soundEnabled = 0
  62.   if pos("-S", g.commLine) = 0 then do
  63.     mmDir = strip(value("MMBASE",, "OS2ENVIRONMENT"))
  64.     if right(mmDir, 1) = ";" then
  65.       mmDir = left(mmDir, length(mmDir)-1)
  66.     if right(mmDir, 1) \= "\" then
  67.       mmDir = mmDir||"\"
  68.     if mmDir \= "" & stream(mmDir"dll\mciapi.dll", "c", "query exists") \= "" then do
  69.       /* initialize sound player */
  70.       call RxFuncAdd "mciRxInit", "MCIAPI", "mciRxInit"
  71.       call mciRxInit
  72.       rc = mciRxSendString('open waveaudio wait', 'RetStr', '0', '0')
  73.       if rc = 0 then do       /* rc = 0 means successful */
  74.         g.soundEnabled = 1
  75.         mmWav = mmDir"sounds\"
  76.         g.sound.laser = mmWav"eeeooop.wav"
  77.         g.sound.hit = mmWav"pop.wav"
  78.         g.sound.crash = mmWav"doink.wav"
  79.         g.sound.point = mmWav"boing.wav"
  80.         g.sound.warp = mmWav"wooeep.wav"
  81.         g.sound.bomb = mmWav"bwaaang.wav"
  82.         g.sound.charge = mmWav"beeoong.wav"
  83.         g.sound.shield = mmWav"bweeep.wav"
  84.         g.sound.firepower = mmWav"laser.wav"
  85.       end
  86.       else
  87.         call showMMPMError rc
  88.     end
  89.   end
  90.  
  91.   /* turn cursor off */
  92.   call SysCurState OFF
  93.  
  94.   /* draw stuff */
  95.   g.shipLook = '1b'x||'[36m'||d2c(223)||d2c(219)||d2c(223)||'1b'x||'[37m'
  96.   g.shipCrash = '1b'x||'[36m'||d2c(205)||d2c(203)||d2c(205)||'1b'x||'[37m'
  97.   g.wall = '1b'x||'[32m'||d2c(221)||'1b'x||'[37m'
  98.   g.laser = '1b'x||'[43m'||d2c(186)||'1b'x||'[40m'
  99.   g.laser.width = 1
  100.   g.laser.offset = 1
  101.   g.bigLaser = '1b'x||'[43m'||'1b'x||'[37m'||d2c(179)||d2c(179)||d2c(179)||'1b'x||'[10m'||'1b'x||'[40m'
  102.   g.bigLaser.width = 3
  103.   g.bigLaser.offset = 0
  104.   g.bonus = "CWBSFP"    /* this represents the bonus objects */
  105.   g.meteor = "+"
  106.  
  107.   return
  108.  
  109. showMMPMError: procedure
  110. /* Show an error message from MMPM/2 */
  111.   parse arg rc
  112.   call mciRxGetErrorString rc, 'ErrStVar'
  113.   call SysCls
  114.   say "It looks like your PC has MMPM/2 installed, but the Wav player didn't"
  115.   say "initialize.  Here's the message from MMPM. . ."
  116.   say "Error: "rc" -  "ErrStVar
  117.   say "Press [ENTER]"
  118.   pull
  119.   return
  120.  
  121. doTitleSequence: procedure expose g.
  122. /* draw some random meteors for fun */
  123.   call clearScreen
  124.   do 50
  125.     call SysCurPos RANDOM(24), RANDOM(16, 78)
  126.     call charout, g.meteor
  127.   end
  128.  
  129.   /* make instruction screen */
  130.   call cleanQueue
  131.   queue "             "||"1b"x||"[32m*** Meteor *** "||"1b"x||"[37m"
  132.   queue "                                   "
  133.   queue "1b"x||"[32mHow to play:"||"1b"x||"[37m"
  134.   queue "   Move your ship ("g.shiplook") to avoid meteors ("g.meteor")."
  135.   queue "   Shoot meteors (10 pts each) to earn points."
  136.   queue "   The longer the laser charges, the farther it shoots."
  137.   queue "   Don't hold down the control keys.  Just tap them."
  138.   queue "                                      "
  139.   queue "1b"x||"[32mControls:"||"1b"x||"[37m"
  140.   queue "   < - move ship left       "
  141.   queue "   > - move ship right    "
  142.   queue "   [enter] - use a bomb (if you have one)"
  143.   queue "   [spacebar] - fire laser"
  144.   queue "                                  "
  145.   queue "1b"x||"[32mBonus Objects:"||"1b"x||"[37m"
  146.   queue "   "||"1b"x||"[41mC"||"1b"x||"[40m - Charge    fully charges laser"
  147.   queue "   "||"1b"x||"[42mW"||"1b"x||"[40m - Warp      goes back to easier level   "
  148.   queue "   "||"1b"x||"[43mB"||"1b"x||"[40m - Bomb      clears screen               "
  149.   queue "   "||"1b"x||"[44mS"||"1b"x||"[40m - Shield    adds to shield power        "
  150.   queue "   "||"1b"x||"[45mF"||"1b"x||"[40m - Firepower extra wide laser for 5 shots"
  151.   queue "   "||"1b"x||"[46mP"||"1b"x||"[40m - Points    gives you 50 points         "
  152.   call displayMsg 0 20 4
  153.  
  154.   call displayHighScores
  155.   return
  156.  
  157. displayHighScores: procedure expose g.
  158. /*  display high scores - each score is derived from a *.msv file in
  159.     the current directory.  *.msv files contain complete games that
  160.     are played back as demos.
  161. *.MSV format is:
  162.   name
  163.   score
  164.   random seed
  165.   all the keystrokes for the entire game
  166. */
  167.  
  168.   call SysFileTree "*.msv", "file", "FO"
  169.   if file.0 = 0 then
  170.     return  /* no high scores */
  171.  
  172.   if file.0 > 10 then
  173.     file.0 = 10
  174.  
  175.   queue "1b"x||"[32mTop 10 Scores"||"1b"x||"[37m"
  176.   queue ""
  177.  
  178.   /* warning: here comes some lazy code. . . */
  179.   scoreFile = g.tmpDir"tmpsort.in"
  180.   sortFile = g.tmpDir"tmpsort.out"
  181.  
  182.   /* read all the names and scores out of the *.msv files */
  183.   do i = 1 to file.0
  184.     name = linein(file.i)
  185.     score = linein(file.i)
  186.     call lineout scoreFile, format(score, 6)" "name
  187.     call stream file.i, "c", "close"
  188.   end
  189.   call stream scoreFile, "c", "close"
  190.  
  191.   /* use the sort OS/2 command to do my sort (I really hate sorting) */
  192.   "@sort /R <"scoreFile" >"sortFile
  193.   do while lines(sortFile) > 0
  194.     rec = linein(sortFile)
  195.     parse var rec score name
  196.     queue name
  197.     queue format(score, 15)
  198.   end
  199.   call stream sortFile, "c", "close"
  200.  
  201.   call displayMsg 0 0 0
  202.  
  203.   /* clean up */
  204.   call SysFileDelete scoreFile
  205.   call SysFileDelete sortFile
  206.  
  207.   return
  208.  
  209. getDecision: procedure
  210. /* return a character where "P" = play, "D" = show demo, "Q" = Quit */
  211.   msg = "(P)lay, (D)emo, (Q)uit, (P)lay, (D)emo, (Q)uit"
  212.   queue "     "||"1b"x||"[41mPress a key:"||"1b"x||"[40m"
  213.   call displayMsg 22 32 4
  214.   key = ""
  215.   call time "R"
  216.   rot = 1
  217.   call charout , "1b"x||"[41m"
  218.   do while key \= "P" & key \= "D" & key \= "Q" & time("E") < 30
  219.     call SysCurPos 23, 36
  220.     call charout , substr(msg, rot, length(msg)/2)
  221.     rot = rot + 1
  222.     if rot > length(msg)/2 + 1 then
  223.       rot = 1
  224.     call SysSleep 1
  225.     if chars() > 0 then
  226.       key = translate(SysGetKey("NOECHO"))
  227.   end
  228.   if key = "" then
  229.     key = "D"
  230.   call charout , "1b"x||"[40m"
  231.   return key
  232.  
  233. playDemo: procedure expose g.
  234. /* read a .msv file and replay the game the file represents */
  235.   call initDemoGame
  236.  
  237.   if s.demoFile = "" then   /* verify there is at least one demo available */
  238.     return
  239.  
  240.   do while s.shield >= 0 & chars() = 0  /* end when ship is destroyed, or a key is pressed */
  241.  
  242.     call pauseIt
  243.  
  244.     key = charin(s.demoFile, , 1)       /* a '-' means no key pressed */
  245.     if key \= "-" then
  246.       call processInput key
  247.  
  248.     call drawItems
  249.  
  250.     call testShipHit
  251.  
  252.     call drawShip
  253.  
  254.     if queued() > 0 then
  255.       call displayGameMessages
  256.  
  257.     s.level = s.level + 1
  258.  
  259.     /* let the user know to press a key to stop the demo */
  260.     if s.level/20 = trunc(s.level/20) then
  261.       queue "1b"x||"[41mPress any key"||"1b"x||"[40m"
  262.  
  263.     s.charge = s.charge + 1
  264.  
  265.   end
  266.  
  267.   call stream s.demoFile, "c", "close"
  268.  
  269.   return
  270.  
  271. initDemoGame: procedure expose g. s.
  272. /* setup to play a demo game */
  273.   call initGame
  274.  
  275.   call cleanQueue
  276.  
  277.   /* select a demo to play at random */
  278.   s.demoFile = ""
  279.   call SysFileTree "*.msv", "file", "FO"
  280.   if file.0 = 0 then
  281.     return
  282.   if file.0 > 10 then
  283.     file.0 = 10
  284.   demoNum = random(1, file.0)
  285.   s.demoFile = g.tmpDir"thisgame.dat"
  286.   "@copy "file.demoNum" "g.tmpDir"thisgame.dat >nul"
  287.   name = linein(s.demoFile)
  288.   score = linein(s.demoFile)
  289.   seed = linein(s.demoFile)
  290.   dateTime = stream(s.demoFile, "c", "query datetime")
  291.   theDate = word(dateTime, 1)
  292.   theTime = word(dateTime, 2)
  293.  
  294.   /*  It's important to seed the random generator with the same value as when
  295.       this game was played the first time */
  296.   seedIt = random(1, 1, seed)
  297.  
  298.   queue "Pilot:"
  299.   queue name
  300.   queue ""
  301.   queue "Score:"score
  302.   queue ""
  303.   queue "Played on:"
  304.   queue theDate
  305.   queue theTime
  306.   queue ""
  307.   return
  308.  
  309. playGame: procedure expose g.
  310. /* play a game of meteor */
  311.   call initGame
  312.  
  313.   do while s.shield >= 0   /* game is over when ship is hit with 0 shields */
  314.  
  315.     call pauseIt
  316.  
  317.     if chars() > 0 then do
  318.       key = SysGetKey("NOECHO")
  319.       call processInput key
  320.       s.keystrokes = s.keystrokes||key    /* save keystrokes for demo */
  321.     end
  322.     else
  323.       s.keystrokes = s.keystrokes||"-"
  324.  
  325.     call drawItems
  326.  
  327.     call testShipHit
  328.  
  329.     call drawShip
  330.  
  331.     if queued() > 0 then
  332.       call displayGameMessages
  333.  
  334.     call incrementTurnData
  335.  
  336.   end
  337.  
  338.   /* close demo file */
  339.   call charout s.demoFile, s.keystrokes
  340.   call stream s.demoFile, "c", "close"
  341.  
  342.   call gameOver
  343.  
  344.   return
  345.  
  346. initGame: procedure expose g. s.
  347. /* setup to start a game */
  348.  
  349.   /* s. is stem for ship variables */
  350.   s.col = 46              /* the ship's current display column */
  351.   s.level = 0             /* the incremental difficulty level */
  352.   s.hits = 0              /* number of meteors hit */
  353.   s.points = 0            /* number of 'P' bonuses collected */
  354.   s.charge = 0            /* charge value of ship's laser */
  355.   s.shield = 3            /* ship's shield level */
  356.   s.firepower = 0         /* ship's firepower level (wide laser) */
  357.   s.bomb = 0              /* ship's number of bombs collected */
  358.   s.warp = 0              /* number of warps collected, used for score tabulation */
  359.   s.onceALevel = 0        /* a counter for things that happen once a level */
  360.   s.keystrokes = ""       /* a buffer variable to store keystrokes to use as demo */
  361.   s.demoFile = g.tmpDir"thisgame.dat"
  362.   call SysFileDelete s.demoFile
  363.  
  364.   /* seed random number generator */
  365.   s.seed = random(1, 10000)       /* keep the seed to save with demo file */
  366.   seedIt = random(1, 1, s.seed)
  367.  
  368.   /* queue up starting messages */
  369.   queue "Hints:          "
  370.   queue "Tap the keys."
  371.   queue ""
  372.   queue "Give the laser"
  373.   queue "time to charge."
  374.   queue ""
  375.   queue "Don't run into"
  376.   queue "meteors."
  377.   queue ""
  378.   queue "Collect bonus"
  379.   queue "objects."
  380.   queue ""
  381.   queue "Look ahead for"
  382.   queue "openings."
  383.   queue ""
  384.   queue "Good Luck!"
  385.   queue ""
  386.   queue "Level:1"
  387.   queue "Score:0"
  388.   queue "Firepower:0"
  389.   queue "Shield:"||s.shield
  390.   queue "                "
  391.  
  392.   call clearScreen
  393.  
  394.   /* flush keystrokes */
  395.   do while chars() > 0
  396.     key = SysGetKey("NOECHO")
  397.   end
  398.  
  399.   /* seed elapsed time so the main loop pauses correctly */
  400.   call time "R"
  401.  
  402.   return
  403.  
  404. clearScreen: procedure expose g.
  405. /* clear the screen and draw the wall */
  406.   call SysCls
  407.   do i = 0 to 24
  408.       call SysCurPos i, 15
  409.       call charout, g.wall
  410.   end
  411.   return
  412.  
  413. processInput: procedure expose g. s.
  414. /* do appropriate action based on input */
  415.   parse arg key
  416.   if key = "," & s.col > 16 then
  417.     s.col = s.col - 1
  418.   else if key = "." & s.col < 77 then
  419.     s.col = s.col + 1
  420.   else if key = " " then
  421.     call doLaser
  422.   else if key = d2c(13) then
  423.     call doBomb
  424.  
  425.   return
  426.  
  427. checkScore: procedure expose g. s.
  428. /* see if this score is in the top 10 */
  429.   thisScore = trunc(s.hits*10+s.points*50+(s.level+s.warp*50)/10)
  430.   call SysFileTree "*.msv", "file", "FO"
  431.   num = 0
  432.  
  433.   /* if there are less than 10, and you did better than 0, you made it! */
  434.   if file.0 < 10 then do
  435.      if thisScore > 0 then do
  436.        num = file.0 + 1
  437.        do while stream("demo"num".msv", "c", "query exists") \= ""
  438.          num = num + 1
  439.        end
  440.        call saveScore "demo"num".msv" thisScore
  441.        return
  442.      end
  443.     call pressAnyKey
  444.     return
  445.   end
  446.  
  447.   /* get the current minimum score in the top 10 */
  448.   minScore = 10000
  449.   do i = 1 to file.0
  450.     name = linein(file.i)
  451.     score = linein(file.i)
  452.     call stream file.i, "c", "close"
  453.     if score < minScore then do
  454.       minScore = score
  455.       demoFileName = file.i
  456.     end
  457.   end
  458.  
  459.   /* if the minimum is lower than this, this replaces the old minimum */
  460.   if thisScore > minScore then do
  461.     call saveScore demoFileName thisScore
  462.     return
  463.   end
  464.  
  465.   call pressAnyKey
  466.  
  467.   return
  468.  
  469. pressAnyKey: procedure
  470.   do while chars() > 0
  471.     key = SysGetKey("NOECHO")
  472.   end
  473.   queue "1b"x||"[41m  Press any key  "||"1b"x||"[40m"
  474.   call displayMsg 22 37
  475.  
  476.   key = SysGetKey("NOECHO")
  477.  
  478.   return
  479.  
  480. saveScore: procedure expose g. s.
  481. /* get info and create a .msv file for this game */
  482. /* num = the 'slot' to put the game, score = the score of the game */
  483.   parse arg fileName score
  484.   name = getName()
  485.   if name = "" then   /* maybe they don't want to claim it */
  486.     return
  487.   if length(name) > 15 then
  488.     name = left(name, 15)
  489.   call SysFileDelete fileName
  490.   call lineout fileName, name
  491.   call lineout fileName, score
  492.   call lineout fileName, s.seed
  493.   call stream fileName, "c", "close"
  494.   "@copy "fileName" + "s.demoFile" >NUL"    /* merge the header with the keystrokes */
  495.  
  496.   return
  497.  
  498. getName: procedure expose g. s.
  499. /* query user for his/her name */
  500.   do while chars() > 0
  501.     key = SysGetKey("NOECHO")
  502.   end
  503.   call SysCurPos 22, 0
  504.   call charout , copies(" ", 239)
  505.   call SysCurPos 22, 0
  506.   call charout , '1b'x||'[32m'||copies("=", 80)||'1b'x||'[37m'
  507.   call SysCurPos 23, 0
  508.   call charout , "You made the top ten!  Please enter your name below (up to 15 letters)"
  509.   call SysCurState ON
  510.   call SysCurPos 24, 0
  511.   call charout , "1b"x||"[41m"||"                "||"1b"x||"[40m"
  512.   call SysCurPos 24, 0
  513.   call charout , ">"
  514.   parse pull name
  515.   call SysCurState OFF
  516.   return name
  517.  
  518. doLaser: procedure expose g. s.
  519. /* show laser shot and test for meteor hits */
  520.   call sound g.sound.laser
  521.   if s.firepower > 0 then do
  522.     s.firepower = s.firepower - 1
  523.     queue "Firepower:"||s.firepower
  524.     image = g.bigLaser
  525.     width = g.bigLaser.width
  526.     offset = g.bigLaser.offset
  527.   end
  528.   else do
  529.     image = g.laser
  530.     width = g.laser.width
  531.     offset = g.laser.offset
  532.   end
  533.  
  534.   s.charge = s.charge / 3   /* so...  24 * 3 turns fully charges the laser.  Hmmm. */
  535.   if s.charge > 24 then
  536.     s.charge = 24           /* the full height of the screen */
  537.  
  538.   /* draw laser vertically down screen */
  539.   gotit = 0
  540.   do i = 1 to s.charge
  541.     test = SysTextScreenRead(i, s.col + offset, width)
  542.     if pos(g.meteor, test) > 0 then do
  543.       call sound g.sound.hit
  544.       if test = "++ " | test = " ++" | test = "+ +" then
  545.         gotit = gotit + 2
  546.       else if test = "+++" then
  547.         gotit = gotit + 3
  548.       else
  549.         gotit = gotit + 1
  550.     end
  551.     call SysCurPos i, s.col + offset
  552.     call charout , image
  553.   end
  554.  
  555.   /* erase laser */
  556.   do i = 1 to s.charge
  557.     call SysCurPos i, s.col + offset
  558.     call charout , copies(" ", width)
  559.   end
  560.  
  561.   /* check for hits */
  562.   if gotit > 0 then do
  563.     s.hits = s.hits + gotit
  564.     queue "Score:"||s.hits*10+s.points*50
  565.   end
  566.  
  567.   s.charge = 0
  568.   return
  569.  
  570. doBomb: procedure expose g. s.
  571. /* use a bomb (clear the screen) */
  572.   if s.bomb = 0 then  /* do you have any bombs? */
  573.     return
  574.  
  575.   call sound g.sound.bomb
  576.   s.bomb = s.bomb - 1
  577.   do i = 1 to 22
  578.      call SysCurPos i, 17
  579.      call charout , copies(" ", 63)
  580.   end
  581.   queue "Bomb:"s.bomb
  582.   return
  583.  
  584. drawItems: procedure expose g. s.
  585. /* draw meteors and bonus objects */
  586.   /* show meteors */
  587.   times = RANDOM(trunc(s.level/150)+2)  /* more meteors as s.level increases */
  588.   do times
  589.     call SysCurPos 24, RANDOM(16, 78)
  590.     call charout , g.meteor
  591.   end
  592.  
  593.   /* show bonus item */
  594.   if random(10) = 0 then do
  595.     sel = random(5) + 1
  596.     call  SysCurPos 24, RANDOM(16, 78)
  597.     call charout , '1b'x||'[4'sel'm'||substr(g.bonus, sel, 1)||'1b'x||'[40m'
  598.   end
  599.  
  600.   /* show wall */
  601.   call SysCurPos 24, 15
  602.   say g.wall
  603.  
  604.   return
  605.  
  606. drawShip: procedure expose g. s.
  607. /* draw the ship at the correct column */
  608.   call SysCurPos 0, s.col
  609.   call charout , g.shiplook
  610.   return
  611.  
  612. displayGameMessages: procedure
  613. /* show the status messages that show up on the left of the wall */
  614.   call SysCurPos 24, 0
  615.   parse pull msg
  616.   call charout , '1b'x||'[37m'||msg
  617.   return
  618.  
  619. incrementTurnData: procedure expose s.
  620. /* take care of turn based house keeping */
  621.   s.level = s.level + 1
  622.   s.charge = s.charge + 1
  623.   /*  I added s.onceALevel to replace code that looked like this:
  624.       if s.level/150 = trunc(s.level/150) then  blah blah
  625.       That's just too darn much division for an arcade game  */
  626.   s.onceALevel = s.onceALevel + 1
  627.   if s.onceALevel = 150 then do
  628.     queue "Level:"trunc(s.level/150+1)    /* let the user know what level he/she is on */
  629.     s.onceALevel = 0                      /* reset the counter */
  630.     call charout s.demoFile, s.keystrokes /* flush the keystroke "buffer" */
  631.     s.keystrokes = ""
  632.   end
  633.   return
  634.  
  635. testShipHit: procedure expose g. s.
  636. /* see if the ship ran into anything */
  637.   test = SysTextScreenRead(0, s.col, 3)
  638.   if test = "   " then     /* didn't hit anything */
  639.     return
  640.   if pos(g.meteor, test) > 0 then do  /* OW!  you hit a meteor! */
  641.     call sound g.sound.crash
  642.     do 20
  643.       call SysCurPos 0, s.col
  644.       say g.shipCrash
  645.       call SysCurPos 0, s.col
  646.       say g.shipLook
  647.     end
  648.     s.shield = s.shield - 1
  649.     if s.shield >= 0 then
  650.       queue "Shield:"||s.shield
  651.   end
  652.  
  653.   /* check for bonus objects */
  654.   if pos("P", test) > 0 then do
  655.     call sound g.sound.point
  656.     s.points = s.points + 1
  657.     queue "Score:"||s.points*50+s.hits*10
  658.   end
  659.   if pos("W", test) > 0 then do
  660.     call sound g.sound.warp
  661.     s.warp = s.warp + 1
  662.     s.level = s.level - 50
  663.     if s.level < 0 then
  664.       s.level = 0
  665.     queue "Warped!"
  666.     queue "Level: "trunc(s.level/150)+1
  667.   end
  668.   if pos("B", test) > 0 then do
  669.     call sound g.sound.bomb
  670.     s.bomb = s.bomb + 1
  671.     queue "Bomb:"s.bomb
  672.   end
  673.   if pos("C", test) > 0 then do
  674.     call Sound g.sound.charge
  675.     s.charge = 9999
  676.     queue "Laser Charged!"
  677.   end
  678.   if pos("S", test) > 0 then do
  679.     s.shield = s.shield + 1
  680.     call Sound g.sound.shield
  681.     queue "Shield:"s.shield
  682.   end
  683.   if pos("F", test) > 0 then do
  684.     call Sound g.sound.firepower
  685.     s.firepower = s.firepower + 5
  686.     queue "Firepower:"||s.firepower
  687.   end
  688.   return
  689.  
  690. gameOver: procedure expose s.
  691. /* show final score and other information */
  692.   call cleanQueue
  693.   call charout ,"1b"x||"[45m"
  694.   queue ""
  695.   queue "          Game Over"
  696.   queue ""
  697.   queue "  Level  :"||format(trunc(s.level/150)+1, 4)
  698.   queue ""
  699.   queue "  Meteors:"||format(s.hits, 4)||" x 10 = "||format(s.hits*10, 6)
  700.   queue "  P Bonus:"||format(s.points, 4)||" x 50 = "||format(s.points*10, 6)
  701.   queue "  Turns  :"||format((s.level+s.warp*50), 4)||" "||d2c(246)||" 10 = "||format(trunc((s.level+s.warp*50)/10), 6)
  702.   queue ""
  703.   queue "  Score  :            "||format(trunc(s.hits*10+s.points*50+(s.level+s.warp*50)/10), 6)
  704.   queue ""
  705.   queue "1b"x||"[40m"
  706.   call displayMsg 5 32 0 30
  707.  
  708.   call SysSleep 2
  709.  
  710.   call checkScore
  711.  
  712.   return
  713.  
  714. sound: procedure expose g.
  715. /* play a wav file */
  716.   if \g.soundEnabled then
  717.     return
  718.   rc = mciRxSendString('load waveaudio 'arg(1), 'RetStr', '0', '0')
  719.   rc = mciRxSendString('play waveaudio', 'RetStr', '0', '0')
  720.  
  721.   return
  722.  
  723. displayMsg: procedure
  724. /* read through the queue and display the text lines in it */
  725.   parse arg row column padAmount fillWidth
  726.   if padAmount = "" then
  727.     padAmount = 0
  728.   if fillWidth = "" then
  729.     fillWidth = 0
  730.   do while queued() > 0
  731.     call SysCurPos row, column
  732.     parse pull msgLine
  733.     if fillWidth > 0 then
  734.       say copies(" ", padAmount)||msgLine||copies(" ", fillWidth-1-length(msgLine))||copies(" ", padAmount)
  735.     else
  736.       say copies(" ", padAmount)||msgLine||copies(" ", padAmount)
  737.     row = row + 1
  738.   end
  739.   return
  740.  
  741. cleanQueue: procedure
  742. /* purge the queue */
  743.   do while queued() > 0
  744.     pull
  745.   end
  746.   return
  747.  
  748. pauseIt:
  749. /* this makes all PC's run the game at the same speed.  It pauses for .1 seconds */
  750.   cnt = 0
  751.   do while time("E") < .15   /* loop until .15 seconds have gone by */
  752.     cnt = cnt + 1
  753.   end
  754.   do trunc((cnt*cnt)/85)
  755.      nop
  756.   end
  757.   call time "R"
  758.   return
  759.  
  760. halt:
  761. cleanUp:
  762. /* take care of housekeeping */
  763.   call charout , "1b"x||"[40m"
  764.   call SysCls
  765.   say ""
  766.   say "Thanks for playing!"
  767.   if g.soundEnabled = 1 then do
  768.     rc = mciRxSendString('close waveaudio wait', 'RetStr', '0', '0')
  769.     call MciRxExit
  770.   end
  771.   exit
  772.