home *** CD-ROM | disk | FTP | other *** search
- /* Fuzzy Battle Sheep!
- *
- * written by John Corigliano with SAS/C 6.51
- *
- * ©1994 John Corigliano
- *
- * internet: j.corigliano@genie.geis.com
- * bix: mopp
- *
- */
-
- #define __USE_SYSBASE /* SAS/C - use Absolute Exec Base = 4 */
- long __oslibversion = 0; /* SAS/C - auotinit, any library will do */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <intuition/intuition.h>
- #include <intuition/gadgetclass.h>
- #include <graphics/gfx.h>
- #include <graphics/gfxbase.h>
- #include <devices/audio.h>
-
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
-
- #include <proto/intuition.h>
- #include <proto/exec.h>
- #include <proto/graphics.h>
- #include <proto/dos.h>
-
- #define MakeID(a,b,c,d) ((LONG)(a)<<24 | (LONG)(b)<<16 | (c)<<8 | (d))
-
- #define ROW_MASK 0x80000000 /* Mask = row 1 */
- #define COL_MASK 0x00800000 /* Mask = column 1 */
- #define ALL_ROWS 0xFF000000 /* Mask = all rows */
- #define ALL_COLS 0x00FFFFFF /* Mask = all columns */
-
- /* Macros to save some typing! */
- #define GET_ROW(n) ((n / 24) + 1)
- #define GET_COL(n) (n - (((n / 24) * 24) - 1))
- #define MAKE_SHIP(n) (ROW_MASK>>(GET_ROW(n)-1))|(COL_MASK>>(GET_COL(n)-1))
-
- struct TextAttr Topaz80 = {"topaz.font", 8, 0, 0,};
-
- #include "placegads.h" /* Contains gadget and menu definitions */
-
- #define NTSC_CLOCK 3579545L /* For sounds */
- #define PAL_CLOCK 3546895L
-
- #define OK 0xFF
- #define SQUARES 0xC0
-
- /* Each square on the 2 grids will either have
- * a number 0-192 or one of these values
- */
- #define SUNK 0xFF /* This square holds a destroyed ship */
- #define MISS 0xFE /* This square holds nothing */
- #define HIT 0xFD /* This square has a ship currently under attack */
-
- /* Colors to draw squares */
- #define FRESH 0x0
- #define KILL 0x1
- #define CURR 0x2
- #define SET 0x3
- #define EMPTY 0x4
-
- #define TOP 0x1
- #define BOTTOM 0x2
- #define PLAYER 5
- #define COMP 6
- #define SLEN 40
-
- #define HORIZ 0x2
-
- /* A struct Ship holds a ULONG that determines its position on the
- * grid (Ship.Pos) and a UBYTE that determines its status (Ship.Data)
- *
- * Ship Position Bits 00000000 00000000 00000000 00000000
- * -------- --------------------------
- * Rows 1-8 Columns 1 - 24
- *
- * Ship Data Bits 00000000
- * ||||||||_ Sunk
- * |||||||__ Orientation (0 = Vert, 1 = Horiz)
- * ||||||___ Hits 1 - 6
- */
-
- struct Ship {
- ULONG Pos;
- UBYTE Data;
- };
-
- struct Ship play_ships[] = { /* These are the player's ships */
- {0x80FC0000, 0x02},
- {0x40F80000, 0x02},
- {0x20F00000, 0x02},
- {0x10E00000, 0x02},
- {0x08C00000, 0x02}
- };
- struct Ship comp_ships[] = { /* These are the computer's ships */
- {0,0},
- {0,0},
- {0,0},
- {0,0},
- {0,0}
- };
-
- struct noiz { /* Sound info structre */
- UBYTE *name; /* file to open */
- UBYTE *data; /* sound sample data */
- ULONG size; /* size */
- UWORD SPS; /* samples per second */
- };
- struct noiz sounds[] = {
- {"sound01", NULL, 0, 0},
- {"sound02", NULL, 0, 0},
- {"sound03", NULL, 0, 0},
- {"sound04", NULL, 0, 0},
- {"sound05", NULL, 0, 0},
- };
-
- UBYTE sizes[] = {6,5,4,3,2};
- UBYTE *Cnames[] = {"Big Daddy","Mathilda","Lamikins","Lil' Sis","Baaa-by"};
- UBYTE *Pnames[] = {"Mr. Big", "Sheba", "Wolfy", "Mutt", "Puppy"};
- UBYTE *verbs[] = {"killed", "murdered", "destroyed", "annihilated",
- "erased", "eradicated", "mutilated", "null and voided",
- "got", "pummeled", "iced", "buried", "wiped out",
- "shot down","disintegrated", "cut down",
- "bludgeoned"};
- UBYTE *tk[] = {"dumbest", "average", "smartest"};
- UBYTE dead_masks[] = {0xFC, 0xF8, 0xF0 ,0xE0, 0xC0};
- UBYTE comp_score = 0, play_score = 0, dir = 0;
- UBYTE player[192], computer[192]; /* <-- The two grids !! */
- ULONG Raud_dev = 1L, Laud_dev = 1L;
- UBYTE think = 2;
- BOOL in_progress = FALSE, play_one = FALSE;
-
- /* My fuctoin prototypes */
- VOID closer(UBYTE *);
- VOID doIDCMP(VOID);
- VOID setPlayer(VOID);
- VOID dBox(ULONG, SHORT, UBYTE);
- VOID moveUp(struct Ship *, WORD);
- VOID moveDown(struct Ship *, WORD);
- VOID moveLeft(struct Ship *, WORD);
- VOID moveRight(struct Ship *, WORD);
- BOOL safeDraw(ULONG, ULONG, WORD);
- VOID shipRotate(struct Ship *, WORD);
- VOID pickShips(struct Ship *);
- LONG getRand(LONG);
- UBYTE collided(ULONG, ULONG, WORD, struct Ship *);
- UBYTE findHit(struct Ship *, ULONG, UBYTE);
- BOOL findBlock(UWORD, UWORD);
- VOID wText(UBYTE *);
- VOID compsTurn(VOID);
- BOOL findShort(UBYTE, WORD);
- VOID endgame(VOID);
- VOID updateDisplay(UBYTE);
- VOID getXY(UBYTE *, UBYTE *, UBYTE *, ULONG);
- VOID openAudio(VOID);
- VOID openSounds(VOID);
- LONG setSeek(FILE *, ULONG);
- VOID playSound(struct noiz *, struct IOAudio *, struct MsgPort *);
-
- struct Screen *scn = NULL;
- struct Window *win = NULL;
- struct TextFont *wFont = NULL;
- struct MsgPort *RaudioMP = NULL, *LaudioMP = NULL;
- struct IOAudio Raudio, Laudio;
- BOOL playit = TRUE;
-
- /*
- * main() sets up the audio.device and opens the Window.
- * Note: No libraries are opened and the WBStartup is not handled.
- * I let SAS/C handle all that nonsense!
- */
- main()
- {
- struct NewWindow nw = {0,11,510,175,0,1,
- IDCMP_GADGETUP|IDCMP_MOUSEBUTTONS|IDCMP_CLOSEWINDOW|
- IDCMP_MENUPICK, WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|
- WFLG_DRAGBAR|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
- &gad, NULL, NULL, NULL, NULL, 100, 11, 510, 175,
- WBENCHSCREEN,
- };
- SHORT d;
- UWORD box[6][10] = {
- {9,82, 9,15, 498,15, 10,15, 10,81},
- {9,153, 9,86, 498,86, 10,86, 10,152},
- {475,156, 475,168, 141,168, 474,168, 474,157},
- {499,15, 499,82, 10,82, 498,82, 498,16},
- {499,87, 499,153, 10,153, 498,153, 498,88},
- {140,168, 140,156, 474,156, 141,156, 141,167},
- };
-
- openAudio();
- openSounds();
-
- srand(VBeamPos());
-
- if (!(scn = LockPubScreen(NULL))) closer("Could not lock screen!!");
- if (win = OpenWindow(&nw)) {
- if (scn->Font->ta_YSize > 8) {
- wFont = OpenFont(&Topaz80);
- SetFont(win->RPort, wFont);
- }
- strip.Width = TextLength(&win->WScreen->RastPort, "Game", 4) + 8;
- SetMenuStrip(win, &strip);
- SetWindowTitles(win,"©1994 John Corigliano","Fuzzy Battle Sheep!");
- SetAPen(win->RPort, 2);
- for (d = 0; d < 6; d++) {
- Move(win->RPort, box[d][0], box[d][1]);
- Draw(win->RPort, box[d][2], box[d][3]);
- Draw(win->RPort, box[d][4], box[d][5]);
- Move(win->RPort, box[d][6], box[d][7]);
- Draw(win->RPort, box[d][8], box[d][9]);
- if (d == 2) SetAPen(win->RPort, 1);
- }
- }
-
- UnlockPubScreen(NULL, scn);
- if (!win) closer("Window problem...");
-
- wText("Press 'Set Up' to begin...");
- updateDisplay(TOP);
- updateDisplay(BOTTOM);
-
- doIDCMP();
-
- closer(NULL);
- }
-
- /*
- * This clean-up function can be called from just about anywhere in the
- * program.
- */
- VOID closer(UBYTE *s)
- {
- BYTE i;
-
- if (!Raud_dev) CloseDevice((struct IORequest *)&Raudio);
- if (RaudioMP) DeletePort(RaudioMP);
- if (!Laud_dev) CloseDevice((struct IORequest *)&Laudio);
- if (LaudioMP) DeletePort(LaudioMP);
- for (i = 0; i < 5; i++)
- if (sounds[i].data) FreeMem(sounds[i].data, sounds[i].size);
- if (win) {
- ClearMenuStrip(win);
- CloseWindow(win);
- }
- if (wFont) CloseFont(wFont);
- if (s) puts(s);
- exit(0);
- }
-
- /*
- * Main message loop
- */
- VOID doIDCMP(VOID)
- {
- BOOL done = FALSE, my_turn = FALSE;
- struct IntuiMessage *imsg;
- ULONG class, ans;
- UWORD code, mnum, inum, snum;
- UBYTE s[SLEN];
- struct EasyStruct es = {
- sizeof(struct EasyStruct),
- 0,
- "Battle Sheep Note:",
- "End this game?",
- "Okay | Cancel",
- };
-
- while (!done) {
- if ((my_turn) && (in_progress)) {
- compsTurn();
- my_turn = FALSE;
- }
- else {
- Wait(1L << win->UserPort->mp_SigBit);
- while (imsg = (struct IntuiMessage *)GetMsg(win->UserPort)) {
- class = imsg->Class;
- code = imsg->Code;
- ReplyMsg((struct Message *)imsg);
- if (class == IDCMP_GADGETUP) {
- if (in_progress) ans = EasyRequest(win, &es, NULL);
- else ans = 1;
- if (ans) {
- OffGadget(&gad, win, NULL);
- comp_score = 6;
- endgame();
- setPlayer();
- SetAPen(win->RPort, 0);
- RectFill(win->RPort, 15, 157, 135, 169);
- OnGadget(&gad, win, NULL);
- }
- }
- if (class == IDCMP_MOUSEBUTTONS) {
- if ((code == SELECTDOWN) && in_progress && !my_turn)
- my_turn = findBlock(win->MouseX, win->MouseY);
- }
- if (class == IDCMP_MENUPICK) {
- mnum = MENUNUM(code);
- inum = ITEMNUM(code);
- snum = SUBNUM(code);
- if (mnum == 0) {
- if (inum == 0) {
- think = snum;
- sprintf(s,"Thinking is now %s.",tk[think]);
- wText(s);
- }
- if (inum == 1) {
- if (snum == 0) playit = FALSE;
- else if (snum == 1) playit = TRUE;
- }
- if (inum == 3) done = TRUE;
- }
- }
- if (class == IDCMP_CLOSEWINDOW) done = TRUE;
- if (done == TRUE)
- done = (EasyRequest(win, &es, NULL)) ? TRUE : FALSE;
- }
- }
- }
- while (imsg = (struct IntuiMessage *)GetMsg(win->UserPort))
- ReplyMsg((struct Message *)imsg);
- }
-
- /*
- * This is where we get the player set-up. The lower grid is replaced
- * with gadgets (defined in "placegads.h"). At the end, the gadgets are
- * re-organized so that if the function is called again, the gadgets
- * will be properly linked.
- */
- VOID setPlayer(VOID)
- {
- BOOL done = FALSE;
- struct IntuiMessage *imsg;
- struct Gadget *work=NULL, *active;
- UWORD cur = 0;
- ULONG class;
-
- active = &g7;
-
- if (play_one) updateDisplay(TOP); /* First time? */
- else play_one = TRUE;
-
- SetAPen(win->RPort, 0);
- RectFill(win->RPort, 15, 88, 495, 152);
- AddGList(win, &g12 , (~0), 12, NULL); /* Gadget g12 is the first in */
- RefreshGList(&g12, win, NULL, 12); /* the linked list of gads */
-
- dBox(play_ships[0].Pos, CURR, PLAYER);
- dBox(play_ships[1].Pos, SET, PLAYER);
- dBox(play_ships[2].Pos, SET, PLAYER);
- dBox(play_ships[3].Pos, SET, PLAYER);
- dBox(play_ships[4].Pos, SET, PLAYER);
-
- wText("Place your sheep...");
-
- OffMenu(win, NOITEM);
- while (!done) {
- Wait(1L << win->UserPort->mp_SigBit);
- while (imsg = (struct IntuiMessage *)GetMsg(win->UserPort)) {
- class = imsg->Class;
- if (class == IDCMP_GADGETUP)
- work = (struct Gadget *)imsg->IAddress;
- ReplyMsg((struct Message *)imsg);
- if (class == IDCMP_GADGETUP) {
- switch (work->GadgetID) {
- case UP_GAD:
- moveUp(&(play_ships[cur]), cur);
- break;
- case DN_GAD:
- moveDown(&(play_ships[cur]), cur);
- break;
- case LT_GAD:
- moveLeft(&(play_ships[cur]), cur);
- break;
- case RT_GAD:
- moveRight(&(play_ships[cur]), cur);
- break;
- case RO_GAD:
- shipRotate(&(play_ships[cur]), cur);
- break;
- case RN_GAD:
- dBox(play_ships[0].Pos, FRESH, PLAYER);
- dBox(play_ships[1].Pos, FRESH, PLAYER);
- dBox(play_ships[2].Pos, FRESH, PLAYER);
- dBox(play_ships[3].Pos, FRESH, PLAYER);
- dBox(play_ships[4].Pos, FRESH, PLAYER);
- pickShips(play_ships);
- dBox(play_ships[0].Pos, SET, PLAYER);
- dBox(play_ships[1].Pos, SET, PLAYER);
- dBox(play_ships[2].Pos, SET, PLAYER);
- dBox(play_ships[3].Pos, SET, PLAYER);
- dBox(play_ships[4].Pos, SET, PLAYER);
- dBox(play_ships[cur].Pos, CURR, PLAYER);
- break;
- case QT_GAD:
- done = TRUE;
- break;
- default:
- if (work != active) {
- /* Mutual exclusion nonsense! */
- RemoveGList(win, active, 1);
- RemoveGList(win, work, 1);
- active->Flags &= ~GFLG_SELECTED;
- work->Flags |= GFLG_SELECTED;
- SetAPen(win->RPort, 0);
- RectFill(win->RPort, active->LeftEdge,
- active->TopEdge,
- active->LeftEdge + 100,
- active->TopEdge + 12);
- RectFill(win->RPort, work->LeftEdge,
- work->TopEdge,
- work->LeftEdge + 100,
- work->TopEdge + 12);
- AddGList(win, active, (~0), 1, NULL);
- AddGList(win, work, (~0), 1, NULL);
- RefreshGList(work, win, NULL, 1);
- RefreshGList(active, win, NULL, 1);
- active = work;
- dBox(play_ships[cur].Pos, SET, PLAYER);
- cur = work->GadgetID - 206;
- dBox(play_ships[cur].Pos, CURR, PLAYER);
- }
- break;
- }
- }
- }
- }
-
- SetPointer(win, pnt, 16, 16, -6, 0);
- wText("Please wait....");
-
- dBox(play_ships[0].Pos, SET, PLAYER);
- dBox(play_ships[1].Pos, SET, PLAYER);
- dBox(play_ships[2].Pos, SET, PLAYER);
- dBox(play_ships[3].Pos, SET, PLAYER);
- dBox(play_ships[4].Pos, SET, PLAYER);
-
- for (cur = 0; cur < 192; cur++) /* These arrays are */
- player[cur] = computer[cur] = (UBYTE)cur; /* the 2 grids */
- pickShips(comp_ships);
- play_score = comp_score = 0;
- in_progress = TRUE;
-
- RemoveGList(win, gad.NextGadget, 12);
- g1.NextGadget = NULL; /* Re-link the gadgets */
- g2.NextGadget = &g1;
- g3.NextGadget = &g2;
- g4.NextGadget = &g3;
- g5.NextGadget = &g4;
- g6.NextGadget = &g5;
- g7.NextGadget = &g6;
- g8.NextGadget = &g7;
- g9.NextGadget = &g8;
- g10.NextGadget = &g9;
- g11.NextGadget = &g10;
- g12.NextGadget = &g11;
-
- active->Flags &= ~GFLG_SELECTED;
- g7.Flags |= GFLG_SELECTED;
-
- updateDisplay(BOTTOM);
-
- ClearPointer(win);
- wText("It's your turn.");
-
- OnMenu(win, NOITEM);
- while (imsg = (struct IntuiMessage *)GetMsg(win->UserPort))
- ReplyMsg((struct Message *)imsg);
-
- return;
- }
-
- /*
- * Draws one or a series of boxes on either grid
- */
- VOID dBox(ULONG ship, SHORT pen, UBYTE who)
- {
- UWORD x, y = 0, z, a = 0;
- SHORT b_x[6], b_y[6], ix = 2, iy = 1, ixx = 17, iyy = 6;
- ULONG r_mask = ROW_MASK, c_mask = COL_MASK;
-
- x = 15;
- for (z = 0; z < 24; z++) {
- if (ship & c_mask) b_x[y++] = x;
- x += 20;
- c_mask >>= 1;
- }
- x = (who == PLAYER) ? 17 : 88;
- for (z = 0; z < 8; z++)
- {
- if (ship & r_mask) b_y[a++] = x;
- x += 8;
- r_mask >>= 1;
- }
-
- if (pen == EMPTY) {
- ix = iy = 0;
- ixx = 19;
- iyy = 7;
- pen = FRESH;
- }
- SetAPen(win->RPort, pen);
- if (y == 1)
- for (x = 0; x < a; x++) {
- RectFill(win->RPort,b_x[0]+ix,b_y[x]+iy,b_x[0]+ixx,b_y[x]+iyy);
- }
- else
- for (x = 0; x < y; x++) {
- RectFill(win->RPort,b_x[x]+ix,b_y[0]+iy,b_x[x]+ixx,b_y[0]+iyy);
- }
- return;
- }
-
- /*
- * Move a ship up a row
- */
- VOID moveUp(struct Ship *ship, WORD cur)
- {
- ULONG row = ALL_ROWS;
-
- if (ship->Pos & ROW_MASK) return;
- row &= ship->Pos;
- row <<= 1;
-
- safeDraw((ship->Pos & ALL_COLS), row, cur);
- return;
- }
-
- /*
- * Move a ship down a row
- */
- VOID moveDown(struct Ship *ship, WORD cur)
- {
- ULONG row = ALL_ROWS;
-
- if (ship->Pos & 0x01000000) return;
- row &= ship->Pos;
- row >>= 1;
-
- safeDraw((ship->Pos & ALL_COLS), row, cur);
- return;
- }
-
- /*
- * Move a ship left one column
- */
- VOID moveLeft(struct Ship *ship, WORD cur)
- {
- ULONG col = ALL_COLS;
-
- if (ship->Pos & COL_MASK) return;
- col &= ship->Pos;
- col <<= 1;
-
- safeDraw(col, (ship->Pos & ALL_ROWS), cur);
- return;
- }
-
- /*
- * Move a ship right one column
- */
- VOID moveRight(struct Ship *ship, WORD cur)
- {
- ULONG col = ALL_COLS;
-
- if (ship->Pos & 0x1) return;
- col &= ship->Pos;
- col >>= 1;
-
- safeDraw(col, (ship->Pos & ALL_ROWS), cur);
- return;
- }
-
- /*
- * Turn ship 90 degrees
- */
- VOID shipRotate(struct Ship *ship, WORD cur)
- {
- ULONG row=ALL_ROWS, col=ALL_COLS, h_check=ROW_MASK, v_check=COL_MASK;
- WORD x, y;
-
- for (x = 0; x < 24; x++) {
- if (ship->Pos & v_check) break;
- v_check >>= 1;
- }
-
- for (y = 0; y < 8; y++) {
- if (ship->Pos & h_check) break;
- h_check >>= 1;
- }
-
- if (ship->Data & HORIZ) {
- if ((8 - y) < sizes[cur]) return;
- }
- else {
- if ((24 - x) < sizes[cur]) return;
- }
-
- row = (ALL_COLS & ship->Pos) << (8 + x - y);
- col = (ALL_ROWS & ship->Pos) >> (8 + x - y);
-
- if (safeDraw(row, col, cur)) {
- if (ship->Data & HORIZ) ship->Data = 0x0;
- else ship->Data = 0x2;
- }
- return;
- }
-
- /*
- * Make sure we don't draw one ship on top of another!
- */
- BOOL safeDraw(ULONG col, ULONG row, WORD cur)
- {
- if (OK != collided(row, col, cur, play_ships)) return(FALSE);
-
- dBox(play_ships[cur].Pos, FRESH, PLAYER);
- play_ships[cur].Pos = row | col;
- dBox(play_ships[cur].Pos, CURR, PLAYER);
-
- return(TRUE);
- }
-
- /*
- * Is there a ship at this position?
- */
- UBYTE collided(ULONG col, ULONG row, WORD cur, struct Ship *s)
- {
- UBYTE x;
-
- for (x = 0; x < 5; x++) {
- if (x != cur) {
- if (((s[x]).Pos & row) && ((s[x]).Pos & col))
- return(x);
- }
- }
-
- return(OK);
- }
-
- /*
- * Randomly position five ship
- */
- VOID pickShips(struct Ship *ships)
- {
- UWORD ran, row, col, orien, touch = 1;
- UBYTE x, ct;
- ULONG r_mask, c_mask;
- BOOL fail;
-
- touch = (UWORD)getRand(250);
- touch = (touch <= 125) ? 0 : 1; /* Will the ships touch? */
-
- for (ct = 0; ct < 5; ct++) {
- do {
- orien = (UWORD)getRand(250);
- orien = (orien <= 125) ? 0 : 1;
- fail = FALSE;
- ran = (UWORD)getRand(SQUARES);
- row = GET_ROW(ran);
- col = GET_COL(ran);
- if (orien == 1)
- while (row > (8-sizes[ct])) row -= 1;
- else
- while (col > (24 - sizes[ct])) col -= 1;
- r_mask = ROW_MASK >> (row-1);
- c_mask = COL_MASK >> (col-1);
- for (x = 0; x < (sizes[ct] - 1); x++) {
- if (orien == 1) r_mask |= r_mask >> 1;
- else c_mask |= c_mask >> 1;
- }
- if (OK != collided(r_mask, c_mask, ct, ships)) fail = TRUE;
- if (touch) {
- if (OK != collided(r_mask>>1,c_mask, ct, ships)) fail=TRUE;
- if (OK != collided(r_mask<<1,c_mask, ct, ships)) fail=TRUE;
- if (OK != collided(r_mask,c_mask>>1, ct, ships)) fail=TRUE;
- if (OK != collided(r_mask,c_mask<<1, ct, ships)) fail=TRUE;
- }
- } while (fail);
- ships[ct].Pos = r_mask | c_mask;
- if (orien == 1) ships[ct].Data = 0x0;
- else ships[ct].Data = 0x2;
- }
-
- return;
- }
-
- /*
- * My function that picks a pseudo-random number between zero and max
- */
- LONG getRand(LONG max)
- {
- LONG z;
-
- do {
- z = rand();
- while (z > max) z %= max;
- } while (z < 0);
-
- return(z + 1);
- }
-
- /*
- * Updates the grid and if there was a hit, it returns a number
- * between 0 and 4 that corresponds to an array of struct Ship.
- * i.e. play_ships[x]
- * If not a hit, returns OK
- */
- UBYTE findHit(struct Ship *them, ULONG ship, UBYTE who)
- {
- UBYTE x;
-
- if (OK != (x = collided(ALL_ROWS & ship, ALL_COLS & ship, OK, them))) {
- dBox(ship, CURR, who);
- return(x);
- }
- else {
- dBox(ship, EMPTY, who);
- return (OK);
- }
- }
-
- /*
- * Interprets mouseX and mouseY. Also determines if the player hit
- * or missed.
- */
- BOOL findBlock(UWORD x, UWORD y)
- {
- UWORD i, j, k = 1, pos = 0;
- UBYTE ct;
- UBYTE hit_mask = 0x80, s[SLEN];
-
- if ((x < 15) || (x > 495) || (y < 88) || (y > 152)) return(FALSE);
-
- for (i = 88; i <= 144; i += 8) {
- for (j = 15; j <= 475; j += 20, k++) {
- if (((x >= j) && (x <= (j+19))) && ((y >= i) && (y<= (i+7)))) {
- pos = k;
- break;
- }
- }
- if (pos) break;
- }
- pos -= 1;
- if (computer[pos] >= HIT) return(FALSE);
-
- if (OK != (ct = findHit(comp_ships, MAKE_SHIP(computer[pos]), COMP))) {
- for (j = 1; j <= sizes[ct]; j++) {
- if (!(comp_ships[ct].Data & hit_mask)) break;
- hit_mask >>= 1;
- }
- comp_ships[ct].Data |= hit_mask;
- if ((dead_masks[ct] & comp_ships[ct].Data) == dead_masks[ct]) {
- dBox(comp_ships[ct].Pos, KILL, COMP);
- comp_ships[ct].Data |= 0x1;
- i = ((UWORD)getRand(17)) - 1;
- sprintf(s, "You %s %s!!!", verbs[i], Pnames[ct]);
- wText(s);
- if (playit) playSound(&sounds[3], &Laudio, LaudioMP);
- play_score += 1;
- }
- else if (playit) playSound(&sounds[0], &Laudio, LaudioMP);
- computer[pos] = HIT;
- endgame();
- }
- else {
- computer[pos] = MISS;
- if (playit) playSound(&sounds[2], &Laudio, LaudioMP);
- }
-
- return (TRUE);
- }
-
- /*
- * Centers a string of text and prints it.
- */
- VOID wText(UBYTE *s)
- {
- UBYTE word[SLEN], len, lj, rj, j, k = 0;
- UWORD i;
-
- len = strlen(s);
- if (!len) return;
- len = (len > SLEN-1) ? SLEN-1 : len;
- lj = ((SLEN - 1) - len) / 2;
- rj = ((SLEN - 1) - len) - lj;
-
- for(i = 0; i < lj; i++) word[i] = ' ';
- for(j = i; j < lj + len; j++) word[j] = s[k++];
- for(i = j; i < SLEN-1; i++) word[i] = ' ';
- word[SLEN-1] = '\0';
-
- SetAPen(win->RPort, 1);
- Move(win->RPort, 155, 165);
- Text(win->RPort, word, SLEN - 1);
-
- return;
- }
-
- /*
- * My very own interpretation of Fuzzy Logic! This function simply
- * evaluates each square's membership in a (fictional) Fuzzy Set.
- * The stronger the membership, the more likely the computer will be
- * to select it. Membership is determined by:
- * 1) Empty? = No Membership
- * 2) Neighbors = Membership
- * 3) Neighbors are HITs = Strongest Membership
- * Note: a HIT is a ship UNDER ATTACK.
- */
- VOID compsTurn(VOID)
- {
- #define COL_A(a) (a==0||a==24||a==48||a==72||a==96||a==120||a==144||a==168)
- #define COL_B(a) (a==1||a==25||a==49||a==73||a==97||a==121||a==145||a==167)
- #define COL_Y(a) (a==22||a==46||a==70||a==94||a==118||a==142||a==166||a==190)
- #define COL_Z(a) (a==23||a==47||a==71||a==95||a==119||a==143||a==167||a==191)
- #define ROW_A(a) (a < 24)
- #define ROW_B(a) ((a < 48) && (a > 23))
- #define ROW_Y(a) ((a < 168) && (a > 143))
- #define ROW_Z(a) (a > 167)
-
- UBYTE r = 0, row, col, hit_mask = 0x80, s[SLEN], num, i;
- UBYTE sets[SQUARES], max;
- ULONG row_mask, col_mask;
-
- if (think == 0) { /* No logic - random pick */
- while (!r) {
- r = (UBYTE)getRand(SQUARES) - 1;
- if (player[r] >= HIT) r = 0;
- }
- }
- else {
- if (!(play_ships[4].Data & 1)) max = 2; /* Find shortest */
- else if (!(play_ships[3].Data & 1)) max = 3; /* ship. Squares */
- else if (!(play_ships[2].Data & 1)) max = 4; /* that have < max */
- else if (!(play_ships[1].Data & 1)) max = 5; /* can't be members*/
- else max = 6;
- for (i = 0; i < SQUARES; i++) {
- sets[i] = 0; /* Start with a membership of zero */
- if ((findShort(player[i], max)) && (player[i] < HIT)) {
- /* Increase membership for HITs */
- if ((!ROW_A(i)) && (player[i-24] == HIT)) {
- sets[i] += 10;
- if ((!ROW_B(i)) && (player[i-48] == HIT)) sets[i]+=20;
- }
- if ((!ROW_Z(i)) && (player[i+24] == HIT)) {
- sets[i] += 10;
- if ((!ROW_Y(i)) && (player[i+48] == HIT)) sets[i]+=20;
- }
- if ((!COL_A(i)) && (player[i-1] == HIT)) {
- sets[i] += 10;
- if ((!COL_B(i)) && (player[i-2] == HIT)) sets[i]+=20;
- }
- if ((!COL_Z(i)) && (player[i+1] == HIT)) {
- sets[i] += 10;
- if ((!COL_Y(i))&&(player[i+2] == HIT)) sets[i]+=20;
- }
- if ((think == 2) && (sets[i] == 0)) {
- num = 0;
- /* Increase membership for neighbors */
- if ((!ROW_A(i)) && (player[i-24] < HIT)) num++;
- if ((!ROW_Z(i)) && (player[i+24] < HIT)) num++;
- if ((!COL_A(i)) && (player[i-1] < HIT)) num++;
- if ((!COL_Z(i)) && (player[i+1] < HIT)) num++;
- if (ROW_A(i) || ROW_Z(i) || COL_A(i) || COL_Z(i))
- sets[i] += (num + 1);
- else sets[i] += num;
- }
- }
- }
- max = r = 0;
- for (i = 0; i < SQUARES; i++) { /* Find strongest members */
- if (sets[i] > max) {
- max = sets[i];
- r = i;
- }
- }
- if ((max > 0) && (max < 10)) { /* No HITs, but neighbors */
- do { /* Randomly select */
- i = (UBYTE)getRand(SQUARES) - 1; /* a member with max */
- } while (sets[i] != max); /* neighbors */
- r = i;
- }
- else if (max == 0) { /* Should never get here! */
- r = 0; /* No members! Ack! */
- while (!r) {
- r = (UBYTE)getRand(SQUARES) - 1;
- if (player[r] >= HIT) r = 0;
- }
- }
- }
-
- row_mask = ROW_MASK >> (GET_ROW(player[r]) - 1);
- col_mask = COL_MASK >> (GET_COL(player[r]) - 1);
-
- if (OK != (max = findHit(play_ships, row_mask|col_mask, PLAYER))) {
- for (i = 1; i <= sizes[max]; i++) {
- if (!(play_ships[max].Data & hit_mask)) break;
- hit_mask >>= 1;
- }
- play_ships[max].Data |= hit_mask;
- if ((dead_masks[max] & play_ships[max].Data) == dead_masks[max]) {
- play_ships[max].Data |= 0x1;
- dBox(play_ships[max].Pos, KILL, PLAYER);
- if (play_ships[max].Data & HORIZ) {
- col_mask = COL_MASK;
- while (!(col_mask & play_ships[max].Pos)) col_mask >>= 1;
- for (i = 0; i < sizes[max]; i++) {
- getXY(&row, &col, &num, row_mask|col_mask);
- player[num] = SUNK;
- col_mask >>= 1;
- }
- }
- else {
- row_mask = ROW_MASK;
- while (!(row_mask & play_ships[max].Pos)) row_mask >>= 1;
- for (i = 0; i < sizes[max]; i++) {
- getXY(&row, &col, &num, row_mask|col_mask);
- player[num] = SUNK;
- row_mask >>= 1;
- }
- }
- i = ((UWORD)getRand(17)) - 1;
- sprintf(s, "I %s %s!!!", verbs[i], Cnames[max]);
- wText(s);
- if (playit) playSound(&sounds[4], &Raudio, RaudioMP);
- comp_score += 1;
- }
- else {
- player[r] = HIT;
- if (playit) playSound(&sounds[0], &Raudio, RaudioMP);
- }
- endgame();
- }
- else {
- player[r] = MISS;
- if (playit) playSound(&sounds[1], &Raudio, RaudioMP);
- }
-
- return;
- }
-
- /*
- * Checks horizontally and vertically for neighbors
- */
- BOOL findShort(UBYTE number, WORD shortest)
- {
- WORD i, j;
- UBYTE up_ct, dn_ct, lt_ct, rt_ct, row, col;
-
- up_ct = dn_ct = lt_ct = rt_ct = 0;
-
- row = GET_ROW(number);
- col = GET_COL(number);
-
- if (row != 1) {
- j = number - (24 * (row - 1));
- for (i = number - 24; i >= j; i -= 24) {
- if (player[i] >= MISS) break;
- up_ct += 1;
- }
- }
- if (row != 8) {
- j = number + (24 * (8 - row));
- for (i = number + 24; i <= j; i += 24) {
- if (player[i] >= MISS) break;
- dn_ct += 1;
- }
- }
- if (col != 1) {
- j = number - (col - 1);
- for (i = number - 1; i >= j; i--) {
- if (player[i] >= MISS) break;
- lt_ct += 1;
- }
- }
- if (col != 24) {
- j = (24 * row) - 1;
- for (i = number + 1; i <= j; i++) {
- if (player[i] >= MISS) break;
- rt_ct += 1;
- }
- }
-
- if (((lt_ct + rt_ct + 1)< shortest) && ((up_ct + dn_ct + 1)< shortest))
- return(FALSE);
- else
- return(TRUE);
- }
-
- /*
- * Checks to see if the game has ended
- */
- VOID endgame(VOID)
- {
- UBYTE x, y, ro, co, o;
- ULONG rm, cm;
-
- if (comp_score == 5) {
- wText("I win!!!!");
- for (x = 0; x < 5; x++) {
- if (!(comp_ships[x].Data & 1)) {
- if (comp_ships[x].Data & HORIZ) {
- rm = comp_ships[x].Pos & ALL_ROWS;
- cm = COL_MASK;
- while (!(cm & comp_ships[x].Pos)) cm >>= 1;
- for (y = 0; y < sizes[x]; y++) {
- getXY(&ro, &co, &o, rm|cm);
- if (computer[o] < HIT) dBox(rm|cm, SET, COMP);
- cm >>= 1;
- }
- }
- else {
- rm = ROW_MASK;
- cm = comp_ships[x].Pos & ALL_COLS;
- while (!(rm & comp_ships[x].Pos)) rm >>= 1;
- for (y = 0; y < sizes[x]; y++) {
- getXY(&ro, &co, &o, rm|cm);
- if (computer[o] < HIT) dBox(rm|cm, SET, COMP);
- rm >>= 1;
- }
- }
- }
- }
- }
-
- if (play_score == 5) wText("Arghh! You won!");
-
- if ((play_score >= 5) || (comp_score >= 5)) {
- for (x = 0; x < 5; x++) {
- play_ships[x].Data &= 0x2;
- comp_ships[x].Data = 0x0;
- comp_ships[x].Pos = 0x0;
- }
- comp_score = play_score = 0;
- in_progress = FALSE;
- }
- return;
- }
-
- /*
- * Redraws grid
- */
- VOID updateDisplay(UBYTE side)
- {
- UWORD x, y;
- UWORD y1 = 17, y2 = 81;
-
- SetDrMd(win->RPort, JAM2);
- SetAPen(win->RPort, 0);
-
- if (side == BOTTOM) {
- y1 = 88;
- y2 = 152;
- }
-
- RectFill(win->RPort, 15, y1, 495, y2);
- SetAPen(win->RPort, 2);
- for (x = 15; x <= 475; x += 20) {
- Move(win->RPort, x, y1);
- Draw(win->RPort, x, y2 - 1);
- Move(win->RPort, x+1, y1);
- Draw(win->RPort, x+1, y2 - 2);
- }
- for (y = y1; y <= (y2 - 8); y += 8) {
- Move(win->RPort, 15, y);
- Draw(win->RPort, 493,y);
- }
- SetAPen(win->RPort, 1);
- for (x = 34; x <= 494; x += 20) {
- for (y = y1; y <= (y2 - 8); y += 8) {
- Move(win->RPort, x, y);
- Draw(win->RPort, x, y+7);
- Draw(win->RPort, x-18, y+7);
- Move(win->RPort, x-1, y+1);
- Draw(win->RPort, x-1, y+6);
- }
- }
-
- return;
- }
-
- /*
- * Converts a ULONG (i.e. struct Ship.Pos) to row, column, and ordinal
- * number.
- * Example 0x80800000 = 10000000100000000000000000000000 binary
- * which corresponds to ^row 1 ^column 1
- * which would be player[0] or computer[0]
- */
- VOID getXY(UBYTE *r, UBYTE *c, UBYTE *ord, ULONG comp)
- {
- UBYTE i;
- ULONG row_mask = ROW_MASK, col_mask = COL_MASK;
-
- for (i = 1; i <= 8; i++) {
- if (comp & row_mask) break;
- row_mask >>= 1;
- }
- *r = i;
- for (i = 1; i <= 24; i++) {
- if (comp & col_mask) break;
- col_mask >>= 1;
- }
- *c = i;
- *ord = (((*r - 1) * 24) + *c) - 1;
-
- return;
- }
-
- /*
- * Open audio.device and allocate one left channel and one right channel
- */
- VOID openAudio(VOID)
- {
- UBYTE Rchan[] = { 0x1, 0x8 }, Lchan[] = { 0x2, 0x4};
-
- if (!(RaudioMP = CreatePort(0, 0))) return;
- Raudio.ioa_Request.io_Command = ADCMD_ALLOCATE;
- Raudio.ioa_Request.io_Message.mn_ReplyPort = RaudioMP;
- Raudio.ioa_Request.io_Message.mn_Node.ln_Pri = 120;
- Raudio.ioa_Request.io_Flags = ADIOF_NOWAIT;
- Raudio.ioa_AllocKey = 0;
- Raudio.ioa_Data = Rchan;
- Raudio.ioa_Length = sizeof(Rchan);
- Raud_dev = OpenDevice(AUDIONAME, 0L, (struct IORequest *)&Raudio, 0L);
- if (Raud_dev) {
- DeletePort(RaudioMP);
- RaudioMP = NULL;
- }
-
- Raudio.ioa_Request.io_Command = CMD_WRITE;
- Raudio.ioa_Request.io_Flags |= ADIOF_PERVOL;
- Raudio.ioa_Volume = 60;
- Raudio.ioa_Cycles = 1;
-
- if (!(LaudioMP = CreatePort(0, 0))) return;
- Laudio.ioa_Request.io_Command = ADCMD_ALLOCATE;
- Laudio.ioa_Request.io_Message.mn_ReplyPort = LaudioMP;
- Laudio.ioa_Request.io_Message.mn_Node.ln_Pri = 120;
- Laudio.ioa_Request.io_Flags = ADIOF_NOWAIT;
- Laudio.ioa_AllocKey = 0;
- Laudio.ioa_Data = Lchan;
- Laudio.ioa_Length = sizeof(Lchan);
- Laud_dev = OpenDevice(AUDIONAME, 0L, (struct IORequest *)&Laudio, 0L);
- if (Laud_dev) {
- DeletePort(LaudioMP);
- LaudioMP = NULL;
- }
- Laudio.ioa_Request.io_Command = CMD_WRITE;
- Laudio.ioa_Request.io_Flags |= ADIOF_PERVOL;
- Laudio.ioa_Volume = 60;
- Laudio.ioa_Cycles = 1;
-
- return;
- }
-
- /*
- * Read 8VSX sound samples into memory
- */
- VOID openSounds(VOID)
- {
- #define ID_BODY MakeID('B', 'O', 'D', 'Y')
- #define ID_VHDR MakeID('V', 'H', 'D', 'R')
-
- FILE *fi;
- LONG fi_seek;
- UBYTE i;
- struct Voice8Header {
- ULONG oneShotHiSamples;
- ULONG repeatHiSamples;
- ULONG samplesPerHiCycle;
- UWORD samplePerSec;
- UBYTE ctOctave;
- UBYTE sCompression;
- LONG volume;
- } vhdr;
-
- for (i = 0; i < 5; i++) {
- if (fi = fopen(sounds[i].name, "rb")) {
- fi_seek = setSeek(fi, ID_VHDR);
- if (fi_seek != -1) {
- fseek(fi, fi_seek + 8, SEEK_SET);
- fread((VOID *)&vhdr, 1, sizeof(struct Voice8Header), fi);
- sounds[i].SPS = vhdr.samplePerSec;
- sounds[i].size = vhdr.oneShotHiSamples;
- if (!sounds[i].size) sounds[i].size = vhdr.repeatHiSamples;
- fi_seek = setSeek(fi, ID_BODY);
- if (fi_seek != -1) {
- fseek(fi, fi_seek + 8, SEEK_SET);
- sounds[i].data = AllocMem(sounds[i].size, MEMF_CHIP);
- fread((VOID *)sounds[i].data, 1, sounds[i].size, fi);
- }
- }
- fclose(fi);
- }
- }
-
- return;
- }
-
- /*
- * Find a Chunk ID in an IFF file
- */
- LONG setSeek(FILE *sf, ULONG ID)
- {
- WORD ct, i;
- BOOL test = FALSE;
- LONG byts = 0, seek = 0;
- UBYTE buf[1024];
-
- rewind(sf);
- ct = fread((VOID *)buf, 1, 1024, sf);
- while (1) {
- for (i = 0; i < ct; i++) {
- if (MakeID(buf[i],buf[i+1],buf[i+2],buf[i+3]) == ID) {
- test = TRUE;
- break;
- }
- }
- if (test || feof(sf)) break;
- ct = fread(buf, 1, 1024, sf);
- byts += ct;
- }
- seek = byts + i;
- if (test) return(seek);
- else return(-1);
- }
-
- /*
- * Play an 8VSX sound sample
- */
- VOID playSound(struct noiz *nz, struct IOAudio *io_p, struct MsgPort *port)
- {
- struct Message *msg;
-
- if (!port) return;
- if (!nz->data) return;
- if (GfxBase->DisplayFlags & PAL)
- io_p->ioa_Period = PAL_CLOCK / nz->SPS;
- else
- io_p->ioa_Period = NTSC_CLOCK / nz->SPS;
- io_p->ioa_Data = (UBYTE *)nz->data;
- io_p->ioa_Length = nz->size;
- BeginIO((struct IORequest *)io_p);
- WaitPort(port);
- msg = GetMsg(port);
-
- return;
- }
-