home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / wbgames / battlesheep / source / sheep.c < prev    next >
C/C++ Source or Header  |  1977-12-31  |  38KB  |  1,255 lines

  1. /* Fuzzy Battle Sheep!
  2.  *
  3.  * written by John Corigliano with SAS/C 6.51
  4.  *
  5.  * ©1994 John Corigliano
  6.  *
  7.  * internet: j.corigliano@genie.geis.com
  8.  *      bix: mopp
  9.  *
  10.  */
  11.  
  12. #define __USE_SYSBASE          /* SAS/C - use Absolute Exec Base = 4    */
  13. long    __oslibversion = 0;    /* SAS/C - auotinit, any library will do */
  14.  
  15. #include <exec/types.h>
  16. #include <exec/memory.h>
  17. #include <intuition/intuition.h>
  18. #include <intuition/gadgetclass.h>
  19. #include <graphics/gfx.h>
  20. #include <graphics/gfxbase.h>
  21. #include <devices/audio.h>
  22.  
  23. #include <string.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <ctype.h>
  27.  
  28. #include <proto/intuition.h>
  29. #include <proto/exec.h>
  30. #include <proto/graphics.h>
  31. #include <proto/dos.h>
  32.  
  33. #define MakeID(a,b,c,d)      ((LONG)(a)<<24 | (LONG)(b)<<16 | (c)<<8 | (d))
  34.  
  35. #define ROW_MASK 0x80000000          /* Mask = row 1       */
  36. #define COL_MASK 0x00800000          /* Mask = column 1    */
  37. #define ALL_ROWS 0xFF000000          /* Mask = all rows    */
  38. #define ALL_COLS 0x00FFFFFF          /* Mask = all columns */
  39.  
  40. /* Macros to save some typing! */
  41. #define GET_ROW(n)   ((n / 24) + 1)
  42. #define GET_COL(n)   (n - (((n / 24) * 24) - 1))
  43. #define MAKE_SHIP(n) (ROW_MASK>>(GET_ROW(n)-1))|(COL_MASK>>(GET_COL(n)-1))
  44.  
  45. struct TextAttr Topaz80 = {"topaz.font", 8, 0, 0,};
  46.  
  47. #include "placegads.h"  /* Contains gadget and menu definitions */
  48.  
  49. #define NTSC_CLOCK    3579545L     /* For sounds */
  50. #define PAL_CLOCK     3546895L
  51.  
  52. #define OK      0xFF
  53. #define SQUARES 0xC0
  54.  
  55. /* Each square on the 2 grids will either have
  56.  * a number 0-192 or one of these values
  57.  */
  58. #define SUNK    0xFF   /* This square holds a destroyed ship            */
  59. #define MISS    0xFE   /* This square holds nothing                     */
  60. #define HIT     0xFD   /* This square has a ship currently under attack */
  61.  
  62. /* Colors to draw squares */
  63. #define FRESH 0x0
  64. #define KILL  0x1
  65. #define CURR  0x2
  66. #define SET   0x3
  67. #define EMPTY 0x4
  68.  
  69. #define TOP    0x1
  70. #define BOTTOM 0x2
  71. #define PLAYER 5
  72. #define COMP   6
  73. #define SLEN   40
  74.  
  75. #define HORIZ 0x2
  76.  
  77. /* A struct Ship holds a ULONG that determines its position on the
  78.  * grid (Ship.Pos) and a UBYTE that determines its status (Ship.Data)
  79.  *
  80.  * Ship Position Bits 00000000 00000000 00000000 00000000
  81.  *                    -------- --------------------------
  82.  *                    Rows 1-8       Columns 1 - 24
  83.  *
  84.  * Ship Data Bits 00000000
  85.  *                ||||||||_ Sunk
  86.  *                |||||||__ Orientation (0 = Vert, 1 = Horiz)
  87.  *                ||||||___ Hits 1 - 6
  88.  */
  89.  
  90. struct Ship { 
  91.     ULONG Pos;
  92.     UBYTE Data;
  93.     };
  94.  
  95. struct Ship play_ships[] = {     /* These are the player's ships */
  96.     {0x80FC0000, 0x02},
  97.     {0x40F80000, 0x02}, 
  98.     {0x20F00000, 0x02},
  99.     {0x10E00000, 0x02},
  100.     {0x08C00000, 0x02}
  101.     };
  102. struct Ship comp_ships[] = {     /* These are the computer's ships */
  103.     {0,0},
  104.     {0,0},
  105.     {0,0},
  106.     {0,0},
  107.     {0,0}
  108.     };
  109.  
  110. struct noiz {                /* Sound info structre */
  111.     UBYTE *name;             /* file to open        */
  112.     UBYTE *data;             /* sound sample data   */
  113.     ULONG  size;             /* size                */
  114.     UWORD  SPS;              /* samples per second  */
  115. };
  116. struct noiz sounds[] = {
  117.     {"sound01", NULL, 0, 0},
  118.     {"sound02", NULL, 0, 0},
  119.     {"sound03", NULL, 0, 0},
  120.     {"sound04", NULL, 0, 0},
  121.     {"sound05", NULL, 0, 0},
  122. };
  123.  
  124. UBYTE sizes[] = {6,5,4,3,2};
  125. UBYTE *Cnames[] = {"Big Daddy","Mathilda","Lamikins","Lil' Sis","Baaa-by"};
  126. UBYTE *Pnames[] = {"Mr. Big", "Sheba", "Wolfy", "Mutt", "Puppy"};
  127. UBYTE *verbs[] = {"killed", "murdered", "destroyed", "annihilated",
  128.                   "erased", "eradicated", "mutilated", "null and voided",
  129.                   "got", "pummeled", "iced", "buried", "wiped out",
  130.                   "shot down","disintegrated", "cut down",
  131.                   "bludgeoned"};
  132. UBYTE *tk[] = {"dumbest", "average", "smartest"};
  133. UBYTE dead_masks[] = {0xFC, 0xF8, 0xF0 ,0xE0, 0xC0};
  134. UBYTE comp_score = 0, play_score = 0, dir = 0;
  135. UBYTE player[192], computer[192];               /* <--  The two grids !! */
  136. ULONG Raud_dev = 1L, Laud_dev = 1L;
  137. UBYTE think = 2;
  138. BOOL in_progress = FALSE, play_one = FALSE;
  139.  
  140. /* My fuctoin prototypes */
  141. VOID closer(UBYTE *);
  142. VOID doIDCMP(VOID);
  143. VOID setPlayer(VOID);
  144. VOID dBox(ULONG, SHORT, UBYTE);
  145. VOID moveUp(struct Ship *, WORD);
  146. VOID moveDown(struct Ship *, WORD);
  147. VOID moveLeft(struct Ship *, WORD);
  148. VOID moveRight(struct Ship *, WORD);
  149. BOOL safeDraw(ULONG, ULONG, WORD);
  150. VOID shipRotate(struct Ship *, WORD);
  151. VOID pickShips(struct Ship *);
  152. LONG getRand(LONG);
  153. UBYTE collided(ULONG, ULONG, WORD, struct Ship *);
  154. UBYTE findHit(struct Ship *, ULONG, UBYTE);
  155. BOOL findBlock(UWORD, UWORD);
  156. VOID wText(UBYTE *);
  157. VOID compsTurn(VOID);
  158. BOOL findShort(UBYTE, WORD);
  159. VOID endgame(VOID);
  160. VOID updateDisplay(UBYTE);
  161. VOID getXY(UBYTE *, UBYTE *, UBYTE *, ULONG);
  162. VOID openAudio(VOID);
  163. VOID openSounds(VOID);
  164. LONG setSeek(FILE *, ULONG);
  165. VOID playSound(struct noiz *, struct IOAudio *, struct MsgPort *);
  166.  
  167. struct Screen *scn = NULL;
  168. struct Window *win = NULL;
  169. struct TextFont *wFont = NULL;
  170. struct MsgPort *RaudioMP = NULL, *LaudioMP = NULL;
  171. struct IOAudio Raudio, Laudio;
  172. BOOL playit = TRUE;
  173.  
  174. /* 
  175.  * main() sets up the audio.device and opens the Window.
  176.  * Note: No libraries are opened and the WBStartup is not handled.
  177.  * I let SAS/C handle all that nonsense!
  178.  */
  179. main()
  180. {
  181.     struct NewWindow nw = {0,11,510,175,0,1,
  182.         IDCMP_GADGETUP|IDCMP_MOUSEBUTTONS|IDCMP_CLOSEWINDOW|
  183.         IDCMP_MENUPICK, WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|
  184.         WFLG_DRAGBAR|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
  185.         &gad, NULL, NULL, NULL, NULL, 100, 11, 510, 175,
  186.         WBENCHSCREEN,
  187.     };
  188.     SHORT d;
  189.     UWORD box[6][10] = {
  190.         {9,82, 9,15, 498,15, 10,15, 10,81},
  191.         {9,153, 9,86, 498,86, 10,86, 10,152},
  192.         {475,156, 475,168, 141,168, 474,168, 474,157},
  193.         {499,15, 499,82, 10,82, 498,82, 498,16},
  194.         {499,87, 499,153, 10,153, 498,153, 498,88},
  195.         {140,168, 140,156, 474,156, 141,156, 141,167},
  196.     };
  197.  
  198.     openAudio();
  199.     openSounds();
  200.  
  201.     srand(VBeamPos());
  202.  
  203.     if (!(scn = LockPubScreen(NULL))) closer("Could not lock screen!!");
  204.     if (win = OpenWindow(&nw)) {
  205.         if (scn->Font->ta_YSize > 8) {
  206.             wFont = OpenFont(&Topaz80);
  207.             SetFont(win->RPort, wFont);
  208.         }
  209.         strip.Width = TextLength(&win->WScreen->RastPort, "Game", 4) + 8;
  210.         SetMenuStrip(win, &strip);
  211.         SetWindowTitles(win,"©1994 John Corigliano","Fuzzy Battle Sheep!");
  212.         SetAPen(win->RPort, 2);
  213.         for (d = 0; d < 6; d++) {
  214.             Move(win->RPort, box[d][0], box[d][1]);
  215.             Draw(win->RPort, box[d][2], box[d][3]);
  216.             Draw(win->RPort, box[d][4], box[d][5]);
  217.             Move(win->RPort, box[d][6], box[d][7]);
  218.             Draw(win->RPort, box[d][8], box[d][9]);
  219.             if (d == 2) SetAPen(win->RPort, 1);
  220.         }
  221.     }
  222.  
  223.     UnlockPubScreen(NULL, scn);
  224.     if (!win) closer("Window problem...");
  225.  
  226.     wText("Press 'Set Up' to begin...");
  227.     updateDisplay(TOP);
  228.     updateDisplay(BOTTOM);
  229.  
  230.     doIDCMP();
  231.  
  232.     closer(NULL);
  233. }
  234.  
  235. /* 
  236.  * This clean-up function can be called from just about anywhere in the
  237.  * program.
  238.  */
  239. VOID closer(UBYTE *s)
  240. {
  241.     BYTE i;
  242.  
  243.     if (!Raud_dev) CloseDevice((struct IORequest *)&Raudio);
  244.     if (RaudioMP)  DeletePort(RaudioMP);
  245.     if (!Laud_dev) CloseDevice((struct IORequest *)&Laudio);
  246.     if (LaudioMP)  DeletePort(LaudioMP);
  247.     for (i = 0; i < 5; i++)
  248.         if (sounds[i].data) FreeMem(sounds[i].data, sounds[i].size);
  249.     if (win) {
  250.         ClearMenuStrip(win);
  251.         CloseWindow(win);
  252.     }
  253.     if (wFont) CloseFont(wFont);
  254.     if (s) puts(s);
  255.     exit(0);
  256. }
  257.  
  258. /*
  259.  * Main message loop
  260.  */
  261. VOID doIDCMP(VOID)
  262. {
  263.     BOOL done = FALSE, my_turn = FALSE;
  264.     struct IntuiMessage *imsg;
  265.     ULONG class, ans;
  266.     UWORD code, mnum, inum, snum;
  267.     UBYTE s[SLEN];
  268.     struct EasyStruct es = {
  269.         sizeof(struct EasyStruct),
  270.         0,
  271.         "Battle Sheep Note:",
  272.         "End this game?",
  273.         "Okay | Cancel",
  274.     };
  275.  
  276.     while (!done) {
  277.         if ((my_turn) && (in_progress)) {
  278.             compsTurn();
  279.             my_turn = FALSE;
  280.         }
  281.         else {
  282.             Wait(1L << win->UserPort->mp_SigBit);
  283.             while (imsg = (struct IntuiMessage *)GetMsg(win->UserPort)) {
  284.                 class = imsg->Class;
  285.                 code = imsg->Code;
  286.                 ReplyMsg((struct Message *)imsg);
  287.                 if (class == IDCMP_GADGETUP) {
  288.                     if (in_progress) ans = EasyRequest(win, &es, NULL);
  289.                     else ans = 1;
  290.                     if (ans) {
  291.                         OffGadget(&gad, win, NULL);
  292.                         comp_score = 6;
  293.                         endgame();
  294.                         setPlayer();
  295.                         SetAPen(win->RPort, 0);
  296.                         RectFill(win->RPort, 15, 157, 135, 169);
  297.                         OnGadget(&gad, win, NULL);
  298.                     }
  299.                 }
  300.                 if (class == IDCMP_MOUSEBUTTONS) {
  301.                     if ((code == SELECTDOWN) && in_progress && !my_turn)
  302.                         my_turn = findBlock(win->MouseX, win->MouseY);
  303.                 }
  304.                 if (class == IDCMP_MENUPICK) {
  305.                     mnum = MENUNUM(code);
  306.                     inum = ITEMNUM(code);
  307.                     snum = SUBNUM(code);
  308.                     if (mnum == 0) {
  309.                         if (inum == 0) {
  310.                             think = snum;
  311.                             sprintf(s,"Thinking is now %s.",tk[think]);
  312.                             wText(s);
  313.                         }
  314.                         if (inum == 1) {
  315.                             if (snum == 0) playit = FALSE;
  316.                             else if (snum == 1) playit = TRUE;
  317.                         }
  318.                         if (inum == 3) done = TRUE;
  319.                     }
  320.                 }
  321.                 if (class == IDCMP_CLOSEWINDOW) done = TRUE;
  322.             if (done == TRUE)
  323.                 done = (EasyRequest(win, &es, NULL)) ? TRUE : FALSE;
  324.             }
  325.         }
  326.     }
  327.     while (imsg = (struct IntuiMessage *)GetMsg(win->UserPort))
  328.         ReplyMsg((struct Message *)imsg);
  329. }
  330.  
  331. /*
  332.  * This is where we get the player set-up. The lower grid is replaced
  333.  * with gadgets (defined in "placegads.h"). At the end, the gadgets are
  334.  * re-organized so that if the function is called again, the gadgets
  335.  * will be properly linked.
  336.  */
  337. VOID setPlayer(VOID)
  338. {
  339.     BOOL done = FALSE;
  340.     struct IntuiMessage *imsg;
  341.     struct Gadget *work=NULL, *active;
  342.     UWORD cur = 0;
  343.     ULONG class;
  344.  
  345.     active = &g7;
  346.  
  347.     if (play_one) updateDisplay(TOP);       /* First time? */
  348.     else play_one = TRUE;
  349.  
  350.     SetAPen(win->RPort, 0);
  351.     RectFill(win->RPort, 15, 88, 495, 152);
  352.     AddGList(win, &g12 , (~0), 12, NULL);  /* Gadget g12 is the first in */
  353.     RefreshGList(&g12, win, NULL, 12);     /* the linked list of gads    */
  354.  
  355.     dBox(play_ships[0].Pos, CURR, PLAYER);
  356.     dBox(play_ships[1].Pos, SET, PLAYER);
  357.     dBox(play_ships[2].Pos, SET, PLAYER);
  358.     dBox(play_ships[3].Pos, SET, PLAYER);
  359.     dBox(play_ships[4].Pos, SET, PLAYER);
  360.  
  361.     wText("Place your sheep...");
  362.  
  363.     OffMenu(win, NOITEM);
  364.     while (!done) {
  365.         Wait(1L << win->UserPort->mp_SigBit);
  366.         while (imsg = (struct IntuiMessage *)GetMsg(win->UserPort)) {
  367.             class = imsg->Class;
  368.             if (class == IDCMP_GADGETUP)
  369.                 work = (struct Gadget *)imsg->IAddress;
  370.             ReplyMsg((struct Message *)imsg);
  371.             if (class == IDCMP_GADGETUP) {
  372.                 switch (work->GadgetID) {
  373.                     case UP_GAD:
  374.                         moveUp(&(play_ships[cur]), cur);
  375.                         break;
  376.                     case DN_GAD:
  377.                         moveDown(&(play_ships[cur]), cur);
  378.                         break;
  379.                     case LT_GAD:
  380.                         moveLeft(&(play_ships[cur]), cur);
  381.                         break;
  382.                     case RT_GAD:
  383.                         moveRight(&(play_ships[cur]), cur);
  384.                         break;
  385.                     case RO_GAD:
  386.                         shipRotate(&(play_ships[cur]), cur);
  387.                         break;
  388.                     case RN_GAD:
  389.                         dBox(play_ships[0].Pos, FRESH, PLAYER);
  390.                         dBox(play_ships[1].Pos, FRESH, PLAYER);
  391.                         dBox(play_ships[2].Pos, FRESH, PLAYER);
  392.                         dBox(play_ships[3].Pos, FRESH, PLAYER);
  393.                         dBox(play_ships[4].Pos, FRESH, PLAYER);
  394.                         pickShips(play_ships);
  395.                         dBox(play_ships[0].Pos, SET, PLAYER);
  396.                         dBox(play_ships[1].Pos, SET, PLAYER);
  397.                         dBox(play_ships[2].Pos, SET, PLAYER);
  398.                         dBox(play_ships[3].Pos, SET, PLAYER);
  399.                         dBox(play_ships[4].Pos, SET, PLAYER);
  400.                         dBox(play_ships[cur].Pos, CURR, PLAYER);
  401.                         break;
  402.                     case QT_GAD:
  403.                         done = TRUE;
  404.                         break;
  405.                     default:
  406.                         if (work != active) {
  407.                             /* Mutual exclusion nonsense! */
  408.                             RemoveGList(win, active, 1);
  409.                             RemoveGList(win, work, 1);
  410.                             active->Flags &= ~GFLG_SELECTED;
  411.                             work->Flags |= GFLG_SELECTED;
  412.                             SetAPen(win->RPort, 0);
  413.                             RectFill(win->RPort, active->LeftEdge,
  414.                                                   active->TopEdge,
  415.                                                   active->LeftEdge + 100,
  416.                                                   active->TopEdge + 12);
  417.                             RectFill(win->RPort, work->LeftEdge,
  418.                                                   work->TopEdge,
  419.                                                   work->LeftEdge + 100,
  420.                                                   work->TopEdge + 12);
  421.                             AddGList(win, active, (~0), 1, NULL);
  422.                             AddGList(win, work, (~0), 1, NULL);
  423.                             RefreshGList(work, win, NULL, 1);
  424.                             RefreshGList(active, win, NULL, 1);
  425.                             active = work;
  426.                             dBox(play_ships[cur].Pos, SET, PLAYER);
  427.                             cur = work->GadgetID - 206;
  428.                             dBox(play_ships[cur].Pos, CURR, PLAYER);
  429.                         }
  430.                         break;
  431.                 }
  432.             }
  433.         }
  434.     }
  435.  
  436.     SetPointer(win, pnt, 16, 16, -6, 0);
  437.     wText("Please wait....");
  438.  
  439.     dBox(play_ships[0].Pos, SET, PLAYER);
  440.     dBox(play_ships[1].Pos, SET, PLAYER);
  441.     dBox(play_ships[2].Pos, SET, PLAYER);
  442.     dBox(play_ships[3].Pos, SET, PLAYER);
  443.     dBox(play_ships[4].Pos, SET, PLAYER);
  444.  
  445.     for (cur = 0; cur < 192; cur++)                /* These arrays are   */
  446.         player[cur] = computer[cur] = (UBYTE)cur;  /* the 2 grids        */
  447.     pickShips(comp_ships);
  448.     play_score = comp_score = 0;
  449.     in_progress = TRUE;
  450.  
  451.     RemoveGList(win, gad.NextGadget, 12);
  452.     g1.NextGadget  = NULL;                 /* Re-link the gadgets */
  453.     g2.NextGadget  = &g1;
  454.     g3.NextGadget  = &g2;
  455.     g4.NextGadget  = &g3;
  456.     g5.NextGadget  = &g4;
  457.     g6.NextGadget  = &g5;
  458.     g7.NextGadget  = &g6;
  459.     g8.NextGadget  = &g7;
  460.     g9.NextGadget  = &g8;
  461.     g10.NextGadget  = &g9;
  462.     g11.NextGadget  = &g10;
  463.     g12.NextGadget  = &g11;
  464.  
  465.     active->Flags &= ~GFLG_SELECTED;
  466.     g7.Flags |= GFLG_SELECTED;
  467.  
  468.     updateDisplay(BOTTOM);
  469.  
  470.     ClearPointer(win);
  471.     wText("It's your turn.");
  472.  
  473.     OnMenu(win, NOITEM);
  474.     while (imsg = (struct IntuiMessage *)GetMsg(win->UserPort))
  475.         ReplyMsg((struct Message *)imsg);
  476.  
  477.     return;
  478. }
  479.  
  480. /*
  481.  * Draws one or a series of boxes on either grid
  482.  */
  483. VOID dBox(ULONG ship, SHORT pen, UBYTE who)
  484. {
  485.     UWORD x, y = 0, z, a = 0;
  486.     SHORT b_x[6], b_y[6], ix = 2, iy = 1, ixx = 17, iyy = 6;
  487.     ULONG r_mask = ROW_MASK, c_mask = COL_MASK;
  488.  
  489.     x = 15;
  490.     for (z = 0; z < 24; z++) {
  491.         if (ship & c_mask) b_x[y++] = x;
  492.         x += 20;
  493.         c_mask >>= 1;
  494.     }
  495.     x = (who == PLAYER) ? 17 : 88;
  496.     for (z = 0; z < 8; z++)
  497.         {
  498.         if (ship & r_mask) b_y[a++] = x;
  499.         x += 8;
  500.         r_mask >>= 1;
  501.     }
  502.  
  503.     if (pen == EMPTY) {
  504.         ix = iy = 0;
  505.         ixx = 19;
  506.         iyy = 7;
  507.         pen = FRESH;
  508.     }
  509.     SetAPen(win->RPort, pen);
  510.     if (y == 1)
  511.         for (x = 0; x < a; x++) {
  512.             RectFill(win->RPort,b_x[0]+ix,b_y[x]+iy,b_x[0]+ixx,b_y[x]+iyy);
  513.         }
  514.     else
  515.         for (x = 0; x < y; x++) {
  516.             RectFill(win->RPort,b_x[x]+ix,b_y[0]+iy,b_x[x]+ixx,b_y[0]+iyy);
  517.         }
  518.     return;
  519. }
  520.  
  521. /*
  522.  * Move a ship up a row
  523.  */
  524. VOID moveUp(struct Ship *ship, WORD cur)
  525. {
  526.     ULONG row = ALL_ROWS;
  527.  
  528.     if (ship->Pos & ROW_MASK) return;
  529.     row &= ship->Pos;
  530.     row <<= 1;
  531.  
  532.     safeDraw((ship->Pos & ALL_COLS), row, cur);
  533.     return;
  534. }
  535.  
  536. /*
  537.  * Move a ship down a row
  538.  */
  539. VOID moveDown(struct Ship *ship, WORD cur)
  540. {
  541.     ULONG row = ALL_ROWS;
  542.  
  543.     if (ship->Pos & 0x01000000) return;
  544.     row &= ship->Pos;
  545.     row >>= 1;
  546.  
  547.     safeDraw((ship->Pos & ALL_COLS), row, cur);
  548.     return;
  549. }
  550.  
  551. /*
  552.  * Move a ship left one column
  553.  */
  554. VOID moveLeft(struct Ship *ship, WORD cur)
  555. {
  556.     ULONG col = ALL_COLS;
  557.  
  558.     if (ship->Pos & COL_MASK) return;
  559.     col &= ship->Pos;
  560.     col <<= 1;
  561.  
  562.     safeDraw(col, (ship->Pos & ALL_ROWS), cur);
  563.     return;
  564. }
  565.  
  566. /*
  567.  * Move a ship right one column
  568.  */
  569. VOID moveRight(struct Ship *ship, WORD cur)
  570. {
  571.     ULONG col = ALL_COLS;
  572.  
  573.     if (ship->Pos & 0x1) return;
  574.     col &= ship->Pos;
  575.     col >>= 1;
  576.  
  577.     safeDraw(col, (ship->Pos & ALL_ROWS), cur);
  578.     return;
  579. }
  580.  
  581. /*
  582.  * Turn ship 90 degrees
  583.  */
  584. VOID shipRotate(struct Ship *ship, WORD cur)
  585. {
  586.     ULONG row=ALL_ROWS, col=ALL_COLS, h_check=ROW_MASK, v_check=COL_MASK;
  587.     WORD x, y;
  588.  
  589.     for (x = 0; x < 24; x++) {
  590.         if (ship->Pos & v_check) break;
  591.         v_check >>= 1;
  592.     }
  593.  
  594.     for (y = 0; y < 8; y++) {
  595.         if (ship->Pos & h_check) break;
  596.         h_check >>= 1;
  597.     }
  598.  
  599.     if (ship->Data & HORIZ) {
  600.         if ((8 - y) < sizes[cur]) return;
  601.     }
  602.     else {
  603.         if ((24 - x) < sizes[cur]) return;
  604.     }
  605.  
  606.     row = (ALL_COLS & ship->Pos) << (8 + x - y);
  607.     col = (ALL_ROWS & ship->Pos) >> (8 + x - y);
  608.  
  609.     if (safeDraw(row, col, cur)) {
  610.         if (ship->Data & HORIZ) ship->Data = 0x0;
  611.         else ship->Data = 0x2;
  612.     }
  613.     return;
  614. }
  615.  
  616. /*
  617.  * Make sure we don't draw one ship on top of another!
  618.  */
  619. BOOL safeDraw(ULONG col, ULONG row, WORD cur)
  620. {
  621.     if (OK != collided(row, col, cur, play_ships)) return(FALSE);
  622.    
  623.     dBox(play_ships[cur].Pos, FRESH, PLAYER);
  624.     play_ships[cur].Pos = row | col;
  625.     dBox(play_ships[cur].Pos, CURR, PLAYER);
  626.  
  627.     return(TRUE);
  628. }
  629.  
  630. /*
  631.  * Is there a ship at this position?
  632.  */
  633. UBYTE collided(ULONG col, ULONG row, WORD cur, struct Ship *s)
  634. {
  635.     UBYTE x;
  636.  
  637.     for (x = 0; x < 5; x++) {
  638.         if (x != cur) {
  639.             if (((s[x]).Pos & row) && ((s[x]).Pos & col))
  640.                 return(x);
  641.         }
  642.     }
  643.  
  644.     return(OK);
  645. }
  646.  
  647. /*
  648.  * Randomly position five ship
  649.  */
  650. VOID pickShips(struct Ship *ships)
  651. {
  652.     UWORD ran, row, col, orien, touch = 1;
  653.     UBYTE x, ct;
  654.     ULONG r_mask, c_mask;
  655.     BOOL fail;
  656.  
  657.     touch = (UWORD)getRand(250);
  658.     touch = (touch <= 125) ? 0 : 1;   /* Will the ships touch? */
  659.  
  660.     for (ct = 0; ct < 5; ct++) {
  661.         do {
  662.             orien = (UWORD)getRand(250);
  663.             orien = (orien <= 125) ? 0 : 1;
  664.             fail = FALSE;
  665.             ran = (UWORD)getRand(SQUARES);
  666.             row = GET_ROW(ran);
  667.             col = GET_COL(ran);
  668.             if (orien == 1)
  669.                 while (row > (8-sizes[ct])) row -= 1;
  670.             else
  671.                 while (col > (24 - sizes[ct])) col -= 1;
  672.             r_mask = ROW_MASK >> (row-1);
  673.             c_mask = COL_MASK >> (col-1);
  674.             for (x = 0; x < (sizes[ct] - 1); x++) {
  675.                 if (orien == 1) r_mask |= r_mask >> 1;
  676.                 else c_mask |= c_mask >> 1;
  677.             }
  678.             if (OK != collided(r_mask, c_mask, ct, ships)) fail = TRUE;
  679.             if (touch) {
  680.                 if (OK != collided(r_mask>>1,c_mask, ct, ships)) fail=TRUE;
  681.                 if (OK != collided(r_mask<<1,c_mask, ct, ships)) fail=TRUE;
  682.                 if (OK != collided(r_mask,c_mask>>1, ct, ships)) fail=TRUE;
  683.                 if (OK != collided(r_mask,c_mask<<1, ct, ships)) fail=TRUE;
  684.             }
  685.         } while (fail);
  686.         ships[ct].Pos = r_mask | c_mask;
  687.         if (orien == 1) ships[ct].Data = 0x0;
  688.         else ships[ct].Data = 0x2;
  689.     }
  690.  
  691.     return;
  692. }
  693.  
  694. /*
  695.  * My function that picks a pseudo-random number between zero and max
  696.  */
  697. LONG getRand(LONG max)
  698. {
  699.     LONG z;
  700.  
  701.     do {
  702.         z = rand();
  703.         while (z > max) z %= max;
  704.     } while (z < 0);
  705.  
  706.     return(z + 1);
  707. }
  708.  
  709. /*
  710.  * Updates the grid and if there was a hit, it returns a number
  711.  * between 0 and 4 that corresponds to an array of struct Ship.
  712.  * i.e. play_ships[x]
  713.  * If not a hit, returns OK
  714.  */
  715. UBYTE findHit(struct Ship *them, ULONG ship, UBYTE who)
  716. {
  717.     UBYTE x;
  718.  
  719.     if (OK != (x = collided(ALL_ROWS & ship, ALL_COLS & ship, OK, them))) {
  720.         dBox(ship, CURR, who);
  721.         return(x);
  722.     }
  723.     else {
  724.         dBox(ship, EMPTY, who);
  725.         return (OK);
  726.     }
  727. }
  728.  
  729. /*
  730.  * Interprets mouseX and mouseY. Also determines if the player hit
  731.  * or missed.
  732.  */
  733. BOOL findBlock(UWORD x, UWORD y)
  734. {
  735.     UWORD i, j, k = 1, pos = 0;
  736.     UBYTE ct;
  737.     UBYTE hit_mask = 0x80, s[SLEN];
  738.  
  739.     if ((x < 15) || (x > 495) || (y < 88) || (y > 152)) return(FALSE);
  740.  
  741.     for (i = 88; i <= 144; i += 8) {
  742.         for (j = 15; j <= 475; j += 20, k++) {
  743.             if (((x >= j) && (x <= (j+19))) && ((y >= i) && (y<= (i+7)))) {
  744.                 pos = k;
  745.                 break;
  746.             }
  747.         }
  748.         if (pos) break;
  749.     }
  750.     pos -= 1;
  751.     if (computer[pos] >= HIT) return(FALSE);
  752.  
  753.     if (OK != (ct = findHit(comp_ships, MAKE_SHIP(computer[pos]), COMP))) {
  754.         for (j = 1; j <= sizes[ct]; j++) {
  755.             if (!(comp_ships[ct].Data & hit_mask)) break;
  756.             hit_mask >>= 1;
  757.         }
  758.         comp_ships[ct].Data |= hit_mask;
  759.         if ((dead_masks[ct] & comp_ships[ct].Data) == dead_masks[ct]) {
  760.             dBox(comp_ships[ct].Pos, KILL, COMP);
  761.             comp_ships[ct].Data |= 0x1;
  762.             i = ((UWORD)getRand(17)) - 1;
  763.             sprintf(s, "You %s %s!!!", verbs[i], Pnames[ct]);
  764.             wText(s);
  765.             if (playit) playSound(&sounds[3], &Laudio, LaudioMP);
  766.             play_score += 1;
  767.         }
  768.         else if (playit) playSound(&sounds[0], &Laudio, LaudioMP);
  769.         computer[pos] = HIT;
  770.         endgame();
  771.     }
  772.     else {
  773.         computer[pos] = MISS;
  774.         if (playit) playSound(&sounds[2], &Laudio, LaudioMP);
  775.     }
  776.  
  777.     return (TRUE);
  778. }
  779.  
  780. /*
  781.  * Centers a string of text and prints it.
  782.  */
  783. VOID wText(UBYTE *s)
  784. {
  785.     UBYTE word[SLEN], len, lj, rj, j, k = 0;
  786.     UWORD i;
  787.  
  788.     len = strlen(s);
  789.     if (!len) return;
  790.     len = (len > SLEN-1) ? SLEN-1 : len;
  791.     lj = ((SLEN - 1) - len) / 2;
  792.     rj = ((SLEN - 1) - len) - lj;
  793.  
  794.     for(i = 0; i < lj; i++) word[i] = ' ';
  795.     for(j = i; j < lj + len; j++) word[j] = s[k++];
  796.     for(i = j; i < SLEN-1; i++) word[i] = ' ';
  797.     word[SLEN-1] = '\0';
  798.  
  799.     SetAPen(win->RPort, 1);
  800.     Move(win->RPort, 155, 165);
  801.     Text(win->RPort, word, SLEN - 1);
  802.  
  803.     return;
  804. }
  805.  
  806. /*
  807.  * My very own interpretation of Fuzzy Logic! This function simply
  808.  * evaluates each square's membership in a (fictional) Fuzzy Set.
  809.  * The stronger the membership, the more likely the computer will be
  810.  * to select it. Membership is determined by:
  811.  *  1) Empty?             = No Membership
  812.  *  2) Neighbors          = Membership
  813.  *  3) Neighbors are HITs = Strongest Membership
  814.  * Note: a HIT is a ship UNDER ATTACK.
  815.  */
  816. VOID compsTurn(VOID)
  817. {
  818. #define COL_A(a) (a==0||a==24||a==48||a==72||a==96||a==120||a==144||a==168)
  819. #define COL_B(a) (a==1||a==25||a==49||a==73||a==97||a==121||a==145||a==167)
  820. #define COL_Y(a) (a==22||a==46||a==70||a==94||a==118||a==142||a==166||a==190)
  821. #define COL_Z(a) (a==23||a==47||a==71||a==95||a==119||a==143||a==167||a==191)
  822. #define ROW_A(a) (a < 24)
  823. #define ROW_B(a) ((a < 48) && (a > 23))
  824. #define ROW_Y(a) ((a < 168) && (a > 143))
  825. #define ROW_Z(a) (a > 167)
  826.  
  827.     UBYTE r = 0, row, col, hit_mask = 0x80, s[SLEN], num, i;
  828.     UBYTE sets[SQUARES], max;
  829.     ULONG row_mask, col_mask;
  830.  
  831.     if (think == 0) {      /* No logic - random pick */
  832.         while (!r) {
  833.             r = (UBYTE)getRand(SQUARES) - 1;
  834.             if (player[r] >= HIT) r = 0;
  835.         }
  836.     }
  837.     else {
  838.         if (!(play_ships[4].Data & 1))      max = 2;  /* Find shortest   */
  839.         else if (!(play_ships[3].Data & 1)) max = 3;  /* ship. Squares   */
  840.         else if (!(play_ships[2].Data & 1)) max = 4;  /* that have < max */
  841.         else if (!(play_ships[1].Data & 1)) max = 5;  /* can't be members*/
  842.         else max = 6;
  843.         for (i = 0; i < SQUARES; i++) {
  844.             sets[i] = 0;   /* Start with a membership of zero */
  845.             if ((findShort(player[i], max)) && (player[i] < HIT)) {
  846.                 /* Increase membership for HITs */
  847.                 if ((!ROW_A(i)) && (player[i-24] == HIT)) {
  848.                     sets[i] += 10;
  849.                     if ((!ROW_B(i)) && (player[i-48] == HIT)) sets[i]+=20;
  850.                 }
  851.                 if ((!ROW_Z(i)) && (player[i+24] == HIT)) {
  852.                     sets[i] += 10;
  853.                     if ((!ROW_Y(i)) && (player[i+48] == HIT)) sets[i]+=20;
  854.                 }
  855.                 if ((!COL_A(i)) && (player[i-1] == HIT)) {
  856.                     sets[i] += 10;
  857.                     if ((!COL_B(i)) && (player[i-2] == HIT)) sets[i]+=20;
  858.                 }
  859.                 if ((!COL_Z(i)) && (player[i+1] == HIT)) {
  860.                     sets[i] += 10;
  861.                     if ((!COL_Y(i))&&(player[i+2] == HIT)) sets[i]+=20;
  862.                 }
  863.                 if ((think == 2) && (sets[i] == 0)) {
  864.                     num = 0;
  865.                     /* Increase membership for neighbors */
  866.                     if ((!ROW_A(i)) && (player[i-24] < HIT)) num++;
  867.                     if ((!ROW_Z(i)) && (player[i+24] < HIT)) num++;
  868.                     if ((!COL_A(i)) && (player[i-1]  < HIT)) num++;
  869.                     if ((!COL_Z(i)) && (player[i+1]  < HIT)) num++;
  870.                     if (ROW_A(i) || ROW_Z(i) || COL_A(i) || COL_Z(i))
  871.                         sets[i] += (num + 1);
  872.                     else sets[i] += num;
  873.                 }
  874.             }
  875.         }
  876.         max = r = 0;
  877.         for (i = 0; i < SQUARES; i++) {     /* Find strongest members */
  878.             if (sets[i] > max) {
  879.                 max = sets[i];
  880.                 r = i;
  881.             }
  882.         }
  883.         if ((max > 0) && (max < 10)) {     /* No HITs, but neighbors  */
  884.             do {                                 /* Randomly select   */
  885.                 i = (UBYTE)getRand(SQUARES) - 1; /* a member with max */
  886.             } while (sets[i] != max);            /* neighbors         */
  887.             r = i;
  888.         }
  889.         else if (max == 0) {              /* Should never get here!   */
  890.             r = 0;                        /* No members! Ack!         */
  891.             while (!r) {
  892.                 r = (UBYTE)getRand(SQUARES) - 1;
  893.                 if (player[r] >= HIT) r = 0;
  894.             }
  895.         }
  896.     }
  897.  
  898.     row_mask = ROW_MASK >> (GET_ROW(player[r]) - 1);
  899.     col_mask = COL_MASK >> (GET_COL(player[r]) - 1);
  900.  
  901.     if (OK != (max = findHit(play_ships, row_mask|col_mask, PLAYER))) {
  902.         for (i = 1; i <= sizes[max]; i++) {
  903.             if (!(play_ships[max].Data & hit_mask)) break;
  904.             hit_mask >>= 1;
  905.         }
  906.         play_ships[max].Data |= hit_mask;
  907.         if ((dead_masks[max] & play_ships[max].Data) == dead_masks[max]) {
  908.             play_ships[max].Data |= 0x1;
  909.             dBox(play_ships[max].Pos, KILL, PLAYER);
  910.             if (play_ships[max].Data & HORIZ) {
  911.                 col_mask = COL_MASK;
  912.                 while (!(col_mask & play_ships[max].Pos)) col_mask >>= 1;
  913.                 for (i = 0; i < sizes[max]; i++) {
  914.                     getXY(&row, &col, &num, row_mask|col_mask);
  915.                     player[num] = SUNK;
  916.                     col_mask >>= 1;
  917.                 }
  918.             }
  919.             else {
  920.                 row_mask = ROW_MASK;
  921.                 while (!(row_mask & play_ships[max].Pos)) row_mask >>= 1;
  922.                 for (i = 0; i < sizes[max]; i++) {
  923.                     getXY(&row, &col, &num, row_mask|col_mask);
  924.                     player[num] = SUNK;
  925.                     row_mask >>= 1;
  926.                 }
  927.             }
  928.             i = ((UWORD)getRand(17)) - 1;
  929.             sprintf(s, "I %s %s!!!", verbs[i], Cnames[max]);
  930.             wText(s);
  931.             if (playit) playSound(&sounds[4], &Raudio, RaudioMP);
  932.             comp_score += 1;
  933.         }
  934.         else {
  935.             player[r] = HIT;
  936.             if (playit) playSound(&sounds[0], &Raudio, RaudioMP);
  937.         }
  938.         endgame();
  939.     }
  940.     else {
  941.         player[r] = MISS;
  942.         if (playit) playSound(&sounds[1], &Raudio, RaudioMP);
  943.     }
  944.  
  945.     return;
  946. }
  947.  
  948. /*
  949.  * Checks horizontally and vertically for neighbors
  950.  */
  951. BOOL findShort(UBYTE number, WORD shortest)
  952. {
  953.     WORD i, j;
  954.     UBYTE up_ct, dn_ct, lt_ct, rt_ct, row, col;
  955.  
  956.     up_ct = dn_ct = lt_ct = rt_ct = 0;
  957.  
  958.     row = GET_ROW(number);
  959.     col = GET_COL(number);
  960.  
  961.     if (row != 1) {
  962.         j = number - (24 * (row - 1));
  963.         for (i = number - 24; i >= j; i -= 24) {
  964.             if (player[i] >= MISS) break;
  965.             up_ct += 1;
  966.         }
  967.     }
  968.     if (row != 8) {
  969.         j = number + (24 * (8 - row));
  970.         for (i = number + 24; i <= j; i += 24) {
  971.             if (player[i] >= MISS) break;
  972.             dn_ct += 1;
  973.         }
  974.     }
  975.     if (col != 1) {
  976.         j = number - (col - 1);
  977.         for (i = number - 1; i >= j; i--) {
  978.             if (player[i] >= MISS) break;
  979.             lt_ct += 1;
  980.         }
  981.     }
  982.     if (col != 24) {
  983.         j = (24 * row) - 1;
  984.         for (i = number + 1; i <= j; i++) {
  985.             if (player[i] >= MISS) break;
  986.             rt_ct += 1;
  987.         }
  988.     }
  989.  
  990.     if (((lt_ct + rt_ct + 1)< shortest) && ((up_ct + dn_ct + 1)< shortest))
  991.         return(FALSE);
  992.     else
  993.         return(TRUE);
  994. }
  995.  
  996. /*
  997.  * Checks to see if the game has ended
  998.  */
  999. VOID endgame(VOID)
  1000. {
  1001.     UBYTE x, y, ro, co, o;
  1002.     ULONG rm, cm;
  1003.  
  1004.     if (comp_score == 5) {
  1005.         wText("I win!!!!");
  1006.         for (x = 0; x < 5; x++) {
  1007.             if (!(comp_ships[x].Data & 1)) {
  1008.                 if (comp_ships[x].Data & HORIZ) {
  1009.                     rm = comp_ships[x].Pos & ALL_ROWS;
  1010.                     cm = COL_MASK;
  1011.                     while (!(cm & comp_ships[x].Pos)) cm >>= 1;
  1012.                     for (y = 0; y < sizes[x]; y++) {
  1013.                         getXY(&ro, &co, &o, rm|cm);
  1014.                         if (computer[o] < HIT) dBox(rm|cm, SET, COMP);
  1015.                         cm >>= 1;
  1016.                     }
  1017.                 }
  1018.                 else {
  1019.                     rm = ROW_MASK;
  1020.                     cm = comp_ships[x].Pos & ALL_COLS;
  1021.                     while (!(rm & comp_ships[x].Pos)) rm >>= 1;
  1022.                     for (y = 0; y < sizes[x]; y++) {
  1023.                         getXY(&ro, &co, &o, rm|cm);
  1024.                         if (computer[o] < HIT) dBox(rm|cm, SET, COMP);
  1025.                         rm >>= 1;
  1026.                     }
  1027.                 }
  1028.             }
  1029.         }
  1030.     }
  1031.                 
  1032.     if (play_score == 5) wText("Arghh! You won!");
  1033.  
  1034.     if ((play_score >= 5) || (comp_score >= 5)) {
  1035.         for (x = 0; x < 5; x++) {
  1036.             play_ships[x].Data &= 0x2;
  1037.             comp_ships[x].Data = 0x0;
  1038.             comp_ships[x].Pos = 0x0;
  1039.         }
  1040.         comp_score = play_score = 0;
  1041.         in_progress = FALSE;
  1042.     }
  1043.     return;
  1044. }
  1045.  
  1046. /*
  1047.  * Redraws grid
  1048.  */
  1049. VOID updateDisplay(UBYTE side)
  1050. {
  1051.     UWORD x, y;
  1052.     UWORD y1 = 17, y2 = 81;
  1053.  
  1054.     SetDrMd(win->RPort, JAM2);
  1055.     SetAPen(win->RPort, 0);
  1056.  
  1057.     if (side == BOTTOM) {
  1058.         y1 = 88;
  1059.         y2 = 152;
  1060.     }
  1061.  
  1062.     RectFill(win->RPort, 15, y1, 495, y2);
  1063.     SetAPen(win->RPort, 2);
  1064.     for (x = 15; x <= 475; x += 20) {
  1065.         Move(win->RPort, x, y1);
  1066.         Draw(win->RPort, x, y2 - 1);
  1067.         Move(win->RPort, x+1, y1);
  1068.         Draw(win->RPort, x+1, y2 - 2);
  1069.     }
  1070.     for (y = y1; y <= (y2 - 8); y += 8) {
  1071.         Move(win->RPort, 15, y);
  1072.         Draw(win->RPort, 493,y);
  1073.     }
  1074.     SetAPen(win->RPort, 1);
  1075.     for (x = 34; x <= 494; x += 20) {
  1076.         for (y = y1; y <= (y2 - 8); y += 8) {
  1077.             Move(win->RPort, x, y);
  1078.             Draw(win->RPort, x, y+7);
  1079.             Draw(win->RPort, x-18, y+7);
  1080.             Move(win->RPort, x-1, y+1);
  1081.             Draw(win->RPort, x-1, y+6);
  1082.         }
  1083.     }
  1084.  
  1085.     return;
  1086. }
  1087.  
  1088. /*
  1089.  * Converts a ULONG (i.e. struct Ship.Pos) to row, column, and ordinal
  1090.  * number.
  1091.  * Example 0x80800000 = 10000000100000000000000000000000 binary
  1092.  * which corresponds to ^row 1  ^column 1
  1093.  * which would be player[0] or computer[0]
  1094.  */
  1095. VOID getXY(UBYTE *r, UBYTE *c, UBYTE *ord, ULONG comp)
  1096. {
  1097.     UBYTE i;
  1098.     ULONG row_mask = ROW_MASK, col_mask = COL_MASK;
  1099.  
  1100.     for (i = 1; i <= 8; i++) {
  1101.         if (comp & row_mask) break;
  1102.         row_mask >>= 1;
  1103.     }
  1104.     *r = i;
  1105.     for (i = 1; i <= 24; i++) {
  1106.         if (comp & col_mask) break;
  1107.         col_mask >>= 1;
  1108.     }
  1109.     *c = i;
  1110.     *ord = (((*r - 1) * 24) + *c) - 1;
  1111.     
  1112.     return;
  1113. }
  1114.  
  1115. /*
  1116.  * Open audio.device and allocate one left channel and one right channel
  1117.  */
  1118. VOID openAudio(VOID)
  1119. {
  1120.     UBYTE Rchan[] = { 0x1, 0x8 }, Lchan[] = { 0x2, 0x4};
  1121.  
  1122.     if (!(RaudioMP = CreatePort(0, 0))) return;
  1123.     Raudio.ioa_Request.io_Command                = ADCMD_ALLOCATE;
  1124.     Raudio.ioa_Request.io_Message.mn_ReplyPort   = RaudioMP;
  1125.     Raudio.ioa_Request.io_Message.mn_Node.ln_Pri = 120;
  1126.     Raudio.ioa_Request.io_Flags                  = ADIOF_NOWAIT;
  1127.     Raudio.ioa_AllocKey                          = 0;
  1128.     Raudio.ioa_Data                              = Rchan;
  1129.     Raudio.ioa_Length                            = sizeof(Rchan);
  1130.     Raud_dev = OpenDevice(AUDIONAME, 0L, (struct IORequest *)&Raudio, 0L);
  1131.     if (Raud_dev) {
  1132.         DeletePort(RaudioMP);
  1133.         RaudioMP = NULL;
  1134.     }
  1135.  
  1136.     Raudio.ioa_Request.io_Command = CMD_WRITE;
  1137.     Raudio.ioa_Request.io_Flags   |= ADIOF_PERVOL;
  1138.     Raudio.ioa_Volume             = 60;
  1139.     Raudio.ioa_Cycles             = 1;
  1140.  
  1141.     if (!(LaudioMP = CreatePort(0, 0))) return;
  1142.     Laudio.ioa_Request.io_Command                = ADCMD_ALLOCATE;
  1143.     Laudio.ioa_Request.io_Message.mn_ReplyPort   = LaudioMP;
  1144.     Laudio.ioa_Request.io_Message.mn_Node.ln_Pri = 120;
  1145.     Laudio.ioa_Request.io_Flags                  = ADIOF_NOWAIT;
  1146.     Laudio.ioa_AllocKey                          = 0;
  1147.     Laudio.ioa_Data                              = Lchan;
  1148.     Laudio.ioa_Length                            = sizeof(Lchan);
  1149.     Laud_dev = OpenDevice(AUDIONAME, 0L, (struct IORequest *)&Laudio, 0L);
  1150.     if (Laud_dev) {
  1151.         DeletePort(LaudioMP);
  1152.         LaudioMP = NULL;
  1153.     }
  1154.     Laudio.ioa_Request.io_Command = CMD_WRITE;
  1155.     Laudio.ioa_Request.io_Flags   |= ADIOF_PERVOL;
  1156.     Laudio.ioa_Volume             = 60;
  1157.     Laudio.ioa_Cycles             = 1;
  1158.  
  1159.     return;
  1160. }
  1161.  
  1162. /*
  1163.  * Read 8VSX sound samples into memory
  1164.  */
  1165. VOID openSounds(VOID)
  1166. {
  1167. #define ID_BODY  MakeID('B', 'O', 'D', 'Y')
  1168. #define ID_VHDR  MakeID('V', 'H', 'D', 'R')
  1169.  
  1170.     FILE *fi;
  1171.     LONG fi_seek;
  1172.     UBYTE i;
  1173.     struct Voice8Header {
  1174.         ULONG oneShotHiSamples;
  1175.         ULONG repeatHiSamples;
  1176.         ULONG samplesPerHiCycle;
  1177.         UWORD samplePerSec;
  1178.         UBYTE ctOctave;
  1179.         UBYTE sCompression;
  1180.         LONG  volume;
  1181.     } vhdr;
  1182.  
  1183.     for (i = 0; i < 5; i++) {
  1184.         if (fi = fopen(sounds[i].name, "rb")) {
  1185.             fi_seek = setSeek(fi, ID_VHDR);
  1186.             if (fi_seek != -1) {
  1187.                 fseek(fi, fi_seek + 8, SEEK_SET);
  1188.                 fread((VOID *)&vhdr, 1, sizeof(struct Voice8Header), fi);
  1189.                 sounds[i].SPS = vhdr.samplePerSec;
  1190.                 sounds[i].size = vhdr.oneShotHiSamples;
  1191.                 if (!sounds[i].size) sounds[i].size = vhdr.repeatHiSamples;
  1192.                 fi_seek = setSeek(fi, ID_BODY);
  1193.                 if (fi_seek != -1) {
  1194.                     fseek(fi, fi_seek + 8, SEEK_SET);
  1195.                     sounds[i].data = AllocMem(sounds[i].size, MEMF_CHIP);
  1196.                     fread((VOID *)sounds[i].data, 1, sounds[i].size, fi);
  1197.                 }
  1198.             }
  1199.             fclose(fi);
  1200.         }
  1201.     }
  1202.  
  1203.     return;
  1204. }
  1205.  
  1206. /*
  1207.  * Find a Chunk ID in an IFF file
  1208.  */
  1209. LONG setSeek(FILE *sf, ULONG ID)
  1210. {
  1211.     WORD ct, i;
  1212.     BOOL test = FALSE;
  1213.     LONG byts = 0, seek = 0;
  1214.     UBYTE buf[1024];
  1215.  
  1216.     rewind(sf);
  1217.     ct = fread((VOID *)buf, 1, 1024, sf);
  1218.     while (1) {
  1219.         for (i = 0; i < ct; i++) {
  1220.             if (MakeID(buf[i],buf[i+1],buf[i+2],buf[i+3]) == ID) {
  1221.                 test = TRUE;
  1222.                 break;
  1223.             }
  1224.         }
  1225.         if (test || feof(sf)) break;
  1226.         ct = fread(buf, 1, 1024, sf);
  1227.         byts += ct;
  1228.     }
  1229.     seek = byts + i;
  1230.     if (test) return(seek);
  1231.     else return(-1);
  1232. }
  1233.  
  1234. /*
  1235.  * Play an 8VSX sound sample
  1236.  */
  1237. VOID playSound(struct noiz *nz, struct IOAudio *io_p, struct MsgPort *port)
  1238. {
  1239.     struct Message *msg;
  1240.  
  1241.     if (!port) return;
  1242.     if (!nz->data) return;
  1243.     if (GfxBase->DisplayFlags & PAL)
  1244.         io_p->ioa_Period = PAL_CLOCK / nz->SPS;
  1245.     else
  1246.         io_p->ioa_Period = NTSC_CLOCK / nz->SPS;
  1247.     io_p->ioa_Data = (UBYTE *)nz->data;
  1248.     io_p->ioa_Length = nz->size;
  1249.     BeginIO((struct IORequest *)io_p);
  1250.     WaitPort(port);
  1251.     msg = GetMsg(port);
  1252.  
  1253.     return;
  1254. }
  1255.