home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
412.lha
/
crabs
/
crabs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-29
|
14KB
|
475 lines
/************************************************************************/
/* */
/* ###################### */
/* A n t h o n y ## ## ## */
/* ########## */
/* T h y s s e n #### ## #### */
/* #### ## #### */
/* #### ## #### */
/* */
/************************************************************************/
/*
** Crabs - also for AMIGA under lattace C
*/
#include <stdio.h>
#include <string.h>
#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>
#include <exec/exec.h>
#include <proto/all.h>
#define BM_SRC 0xC0 /* minterm source only */
#define BM_DST 0xA0 /* minterm destination only */
#include "crabs.h"
/* intuition variables */
struct Library *IntuitionBase = NULL, *GfxBase = NULL;
struct Screen *WBScrn = NULL;
struct Window *Window = NULL; /* Window pointer */
struct RastPort *RPwindow = NULL; /* windows raster port */
struct Remember *Remember = NULL; /* memory allocation memory */
struct Task *MyTask = NULL; /* my tasks address */
struct IntuiMessage *message = NULL;
int WBScrX, WBScrY; /* size of workbench screen */
ULONG WindowSignal; /* IDCMP window signal */
struct NewWindow NW = {
30, 200, 350, 40, 0, 1, /* position, size and colors */
CLOSEWINDOW, /* IDCMP messages */
ACTIVATE| SIMPLE_REFRESH| WINDOWDEPTH|
WINDOWDRAG| WINDOWCLOSE, /* window flags */
NULL, NULL, /* gadget, checkmark */
(UBYTE *) " << CRABS >> ", /* name of window */
NULL,NULL, /* screen-> , BitMap-> */
0,0,0,0, /* min and max size (disable) */
WBENCHSCREEN /* screen type */
};
/* program varibles */
typedef struct {
int x, y;
} point;
typedef enum {
Looking, /* crab is looking for food */
Nibbling, /* crab took a nibble and is stepping back */
Munching /* crab is eating the food (after step back) */
} crabstatus;
static struct {
crabstatus stat; /* current status of crab */
point pos; /* upper left corner screen coords */
point vel; /* velocity (pixels/cycle) */
point old; /* last position for backward step */
int lp; /* life points of this crab */
struct RastPort *RP; /* which map is the crab using */
} crab[MAXCRABS]; /* crabs' state */
int NumCrabs = 0; /* number of crabs on screen */
/* Crab images to be drawen to the screen using the mask */
unsigned short chip crabup[] = /* facing up */
# include "crabup.i"
#ifndef ONEIMAGE
unsigned short chip crabdown[] = /* facing down */
# include "crabdown.i"
unsigned short chip crabright[] = /* facing right */
# include "crabright.i"
unsigned short chip crableft[] = /* facing left */
# include "crableft.i"
#endif
unsigned short chip crabmask[] = /* crabs mask */
# include "crabmask.i"
/* Bitmaps and raster ports of the screens */
struct BitMap BMtemp, BMmask, BMup;
struct RastPort RPtemp, RPmask, RPup, RPscreen;
#ifndef ONEIMAGE
struct BitMap BMdown, BMright, BMleft;
struct RastPort RPdown, RPright, RPleft;
#endif
/* function declarations */
extern void Init(), OpenLibraries(), InitWindow(), InitRP(), Print();
extern void CrabsExit(), Cycle(), DrawCrab(), HideCrab(), ModVel(), NewVel();
extern BOOL MoveCrab(), TestCrab(), TestBackground();
extern void RandInit();
extern int RandInt();
#ifdef CBACK
/* Cback.o initializations */
LONG _stack = 2000;
char *_procname = "Crabs";
LONG _priority = -1;
LONG _BackGroundIO = 0;
#endif
void
_main()
{
Init();
for (;;) {
Cycle();
}
/* NOTREACHED */
}
void
Init()
/* set up initial crab layer */
{
int i; /* crab # */
OpenLibraries(); /* open the various system structures */
if( ! (Window = OpenWindow( &NW )) )
CrabsExit(NULL);
RPwindow = Window->RPort;
WindowSignal = 1<<Window->UserPort->mp_SigBit;
InitWindow();
MyTask = FindTask( NULL );
WBScrn = Window->WScreen;
WBScrX = WBScrn->Width -SIZE;
WBScrY = WBScrn->Height -SIZE/2;
memcpy((char *) &RPscreen, (char *) &(WBScrn->RastPort),
sizeof( struct RastPort ));
InitRP(&RPup, &BMup, &crabup);
InitRP(&RPmask, &BMmask, &crabmask);
InitRP(&RPtemp, &BMtemp, NULL);
#ifndef ONEIMAGE
InitRP(&RPdown, &BMdown, &crabdown);
InitRP(&RPleft, &BMdown, &crableft);
InitRP(&RPright, &BMright, &crabright);
#endif
RandInit();
/* Create initial set of crabs: */
for (NumCrabs = 0; NumCrabs < STARTCRABS; NumCrabs++) {
for (i = PLACELIM; i > 0; i--) {
crab[NumCrabs].pos.x = RandInt(0, WBScrX-1);
crab[NumCrabs].pos.y = RandInt(0, WBScrY-1);
crab[NumCrabs].old = crab[NumCrabs].pos;
if( !TestBackground(NumCrabs) )
break; /* space found */
}
if( !i ) /* did we reach the placement limit */
CrabsExit("Can't place crabs! No empty space found!");
crab[NumCrabs].lp = REPROlp / 2;
crab[NumCrabs].stat = Looking;
NewVel(NumCrabs);
DrawCrab(NumCrabs);
}
}
void
OpenLibraries()
{
if( ! (IntuitionBase = OpenLibrary( "intuition.library", 0 )) )
CrabsExit("Can't open Intuition Library");
if( ! (GfxBase = OpenLibrary( "graphics.library", 0 )) )
CrabsExit("Can't Open Graphics Library");
}
void
InitWindow()
{
Move(RPwindow, Window->BorderLeft,
Window->BorderTop + RPwindow->TxBaseline );
SetAPen(RPwindow, 3);
Print("Reproducing Crabs by Anthony Thyssen");
SetAPen(RPwindow, 1);
Print(" Original idea from Scientific American");
}
void
InitRP(rp, bm, image)
struct RastPort *rp;
struct BitMap *bm;
short *image;
{
InitBitMap(bm, 1, SIZE,SIZE/2);
if( image )
bm->Planes[0] = (PLANEPTR) image;
else
if( !(bm->Planes[0] = (PLANEPTR)
AllocRemember( &Remember, RASSIZE(SIZE,SIZE/2),
MEMF_CHIP | MEMF_CLEAR) ) ) { /* allocate with memory */
CrabsExit("Can't alloc raster");
}
InitRastPort( rp );
rp->BitMap = bm;
}
void
Print(str)
char *str;
{
Text( RPwindow, str, strlen(str) );
Move( RPwindow, Window->BorderLeft,
RPwindow->cp_y + RPwindow->TxHeight); /* move to next line */
}
void
CrabsExit(exitmessage)
char *exitmessage;
/* exit crabs - remove all traces */
{
int i;
for (i = 0; i < NumCrabs; ++i)
HideCrab(i);
RefreshWindowFrame(Window);
InitWindow();
if( Window && exitmessage ) {
Print(exitmessage);
/*printf("%s\n", exitmessage); /* Debugging */
Delay(200);
}
FreeRemember( &Remember, TRUE ); /* Frre all allocated memory */
if( Window ) CloseWindow( Window );
if( GfxBase ) CloseLibrary( GfxBase );
if( IntuitionBase ) CloseLibrary( IntuitionBase );
_exit(0);
}
void
Cycle()
/* one motion cycle for all crabs */
{
int i;
/* test for window closure */
if( message = (struct IntuiMessage *)GetMsg(Window->UserPort) ) {
ReplyMsg( (struct Message *)message );
switch( message->Class ) {
case CLOSEWINDOW : /* window closed message */
CrabsExit("Crabs are Exiting");
}
} /* Message test */
if( NumCrabs < 5 )
Delay( DELAY ); /* slow down the small number of crabs */
for (i = 0; i < NumCrabs; i++) {
/* did something bite the crab - image corrupted ? */
if (TestCrab(i)) { /* if so damage the crab */
crab[i].lp -= BITElp;
NewVel(i);
}
switch( crab[i].stat ) { /* do the nessary move */
case Looking:
HideCrab(i); /* erase crab from previous position */
crab[i].old = crab[i].pos; /* record current position */
if (MoveCrab(i)) /* find the new positioN */
crab[i].lp -= BOUNCElp; /* crab bounced - that smarts */
if (TestBackground(i)) /* Test if crab hits an object */
crab[i].stat = Nibbling; /* if so crab will now nibble */
crab[i].lp -= MOVElp; /* drain movement cost from crab */
if (crab[i].lp < 0) { /* check on starvation */
crab[i] = crab[--NumCrabs];
if (NumCrabs == 0)
CrabsExit("The last Crab just died!\n");
i--;
continue; /* repeat this crab as it is the next one */
}
DrawCrab(i); /* redraw crab here */
ModVel(i, 1); /* very slight direction change */
break;
case Nibbling:
HideCrab(i); /* erase crab from previous position */
crab[i].pos = crab[i].old; /* move crab backwards */
DrawCrab(i); /* draw crab here */
crab[i].stat = Munching; /* chew over the food */
break;
case Munching:
crab[i].lp += FEEDlp; /* feed the food to the crab */
ModVel(i, FEEDVEL); /* look in roughly the same dir as before */
crab[i].stat = Looking; /* time taken to eat - look for more */
if (crab[i].lp >= REPROlp) { /* check for reproduction */
HideCrab(i); /* remove parent */
crab[i].lp /= 2; /* half life force */
if (NumCrabs < MAXCRABS) { /* is a new crab is possible */
crab[NumCrabs] = crab[i]; /* child is a copy of parent */
crab[NumCrabs].vel.x = -crab[NumCrabs].vel.x; /* reverse dir */
crab[NumCrabs].vel.y = -crab[NumCrabs].vel.y;
crab[NumCrabs].lp -= BITElp; /* child is weak */
MoveCrab(i); /* move crabs away from each other */
MoveCrab(NumCrabs++); /* move child twice - inc number crabs */
/* leave the child undrawen and corrupted! */
}
DrawCrab(i); /* draw parent regardless of child state */
}
break;
}
} /* move next crab */
}
BOOL
MoveCrab(i)
int i;
/* move crab to on screen position - don't draw it */
/* if the crab hits edge of screen return TRUE */
{
BOOL hit = FALSE;
crab[i].pos.x += crab[i].vel.x; /* motion */
crab[i].pos.y += crab[i].vel.y;
if( crab[i].pos.x < 0 ) {
crab[i].pos.x = 0;
crab[i].vel.x = abs(crab[i].vel.x);
hit = TRUE;
}
if( crab[i].pos.x > WBScrX ) {
crab[i].pos.x = WBScrX;
crab[i].vel.x = -abs(crab[i].vel.x);
hit = TRUE;
}
if( crab[i].pos.y < 0 ) {
crab[i].pos.y = 0;
crab[i].vel.y = abs(crab[i].vel.y);
hit = TRUE;
}
if( crab[i].pos.y > WBScrY ) {
crab[i].pos.y = WBScrY;
crab[i].vel.y = -abs(crab[i].vel.y);
hit = TRUE;
}
return (hit);
}
BOOL
TestCrab(i)
int i;
/* test the crabs image on the screen. return TRUE if corrupt */
/* invisible crabs are the background texture */
{
int j;
UBYTE *byte;
/* get crab stored on screen */
ClipBlit( &RPscreen, crab[i].pos.x, crab[i].pos.y,
&RPtemp, 0, 0, SIZE, SIZE/2, BM_SRC );
/* mask out background */
ClipBlit( &RPmask, 0, 0, &RPtemp, 0, 0,
SIZE, SIZE/2, BM_SRC & BM_DST );
/* xor with crab image */
ClipBlit( crab[i].RP, 0, 0, &RPtemp, 0, 0,
SIZE, SIZE/2, BM_SRC ^ BM_DST );
/* check the data */
byte = BMtemp.Planes[0];
for (j = RASSIZE(SIZE, SIZE/2)-1; j >= 0; j--)
if( *(byte++) )
return TRUE;
return FALSE;
}
BOOL
TestBackground(i)
int i;
/* return TRUE if crab position is not the background */
{
int j;
UBYTE *byte;
/* get screen at crab location */
ClipBlit( &RPscreen, crab[i].pos.x, crab[i].pos.y,
&RPtemp, 0, 0, SIZE, SIZE/2, BM_SRC );
/* mask out background */
ClipBlit( &RPmask, 0, 0, &RPtemp, 0, 0,
SIZE, SIZE/2, BM_SRC & BM_DST );
/* check the data */
byte = BMtemp.Planes[0];
for (j = RASSIZE(SIZE, SIZE/2)-1; j >= 0; j--)
if( *(byte++) )
return TRUE;
return FALSE;
}
void
HideCrab(i)
/* over write current crab with screen texture */
{
ClipBlit( &RPmask, 0, 0, &RPscreen, crab[i].pos.x, crab[i].pos.y,
SIZE, SIZE/2, ~BM_SRC & BM_DST );
}
void
DrawCrab(i)
int i;
/* Draw the crabs on the screen if visible */
{
HideCrab(i);
crab[i].RP = PICKMAP( crab[i].vel );
ClipBlit( crab[i].RP, 0, 0, &RPscreen, crab[i].pos.x, crab[i].pos.y,
SIZE, SIZE/2, BM_SRC | BM_DST );
}
void
NewVel(i) /* assign new velocity to crab */
int i; /* crab # */
{
crab[i].vel.x = RandInt(-MAXVEL, MAXVEL);
crab[i].vel.y = RandInt(-MAXVEL/2, MAXVEL/2);
/* Velocity (0,0) is okay since we repeatedly modify all velocities. */
}
void
ModVel(i, dv) /* randomly modify crab velocity */
int i,dv; /* crab, delta velocity */
{
int min,max; /* range of new velocity */
min=crab[i].vel.x-dv;
max=crab[i].vel.x+dv;
if ( max > MAXVEL)
max = MAXVEL;
if ( min < -MAXVEL)
min = -MAXVEL;
crab[i].vel.x = RandInt(min, max);
min=crab[i].vel.y-dv;
max=crab[i].vel.y+dv;
if ( max > MAXVEL/2)
max = MAXVEL/2;
if ( min < -MAXVEL/2)
min = -MAXVEL/2;
crab[i].vel.y = RandInt(min, max);
}
void
RandInit()
{
srand((int)time(NULL));
}
int
RandInt(lo, hi) /* generate random integer in range */
int lo, hi; /* range lo..hi inclusive */
{
return lo + (int)( (unsigned)rand() % (hi - lo +1) );
}