home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 412.lha / crabs / crabs.c < prev    next >
C/C++ Source or Header  |  1990-08-29  |  14KB  |  475 lines

  1. /************************************************************************/
  2. /*                                                                      */
  3. /*                                   ######################             */
  4. /*      A n t h o n y                      ##  ##  ##                   */
  5. /*                                         ##########                   */
  6. /*              T h y s s e n            ####  ##  ####                 */
  7. /*                                     ####    ##    ####               */
  8. /*                                   ####      ##      ####             */
  9. /*                                                                      */
  10. /************************************************************************/
  11.  
  12. /*
  13. **  Crabs - also for AMIGA under lattace C
  14. */
  15.  
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <intuition/intuition.h>
  19. #include <graphics/gfxmacros.h>
  20. #include <exec/exec.h>
  21. #include <proto/all.h>
  22. #define BM_SRC 0xC0      /* minterm source only */
  23. #define BM_DST 0xA0      /* minterm destination only */
  24.  
  25. #include "crabs.h"
  26.  
  27.  /* intuition variables */
  28. struct Library        *IntuitionBase = NULL, *GfxBase = NULL;
  29. struct Screen         *WBScrn = NULL;
  30. struct Window         *Window = NULL;        /* Window pointer */
  31. struct RastPort       *RPwindow = NULL;      /* windows raster port */
  32. struct Remember       *Remember = NULL;      /* memory allocation memory */
  33. struct Task           *MyTask = NULL;        /* my tasks address */
  34. struct IntuiMessage   *message = NULL;
  35. int                   WBScrX, WBScrY;        /* size of workbench screen */
  36. ULONG                 WindowSignal;          /* IDCMP window signal */
  37. struct NewWindow      NW = {
  38.         30, 200, 350, 40, 0, 1,               /* position, size and colors */
  39.         CLOSEWINDOW,                         /* IDCMP messages */
  40.         ACTIVATE| SIMPLE_REFRESH| WINDOWDEPTH|
  41.            WINDOWDRAG| WINDOWCLOSE,          /* window flags */
  42.         NULL, NULL,                          /* gadget, checkmark */
  43.         (UBYTE *) " << CRABS >> ",           /* name of window */
  44.         NULL,NULL,                           /* screen-> , BitMap-> */
  45.         0,0,0,0,                             /* min and max size (disable) */
  46.         WBENCHSCREEN                         /* screen type */
  47.         };
  48.  
  49.  
  50.    /* program varibles */
  51. typedef struct {
  52.   int             x, y;
  53. }               point;
  54.  
  55. typedef enum {
  56.     Looking,          /* crab is looking for food */
  57.     Nibbling,         /* crab took a nibble and is stepping back */
  58.     Munching          /* crab is eating the food (after step back) */
  59. } crabstatus;
  60.  
  61. static struct {
  62.   crabstatus      stat;       /* current status of crab */
  63.   point           pos;        /* upper left corner screen coords */
  64.   point           vel;        /* velocity (pixels/cycle) */
  65.   point           old;        /* last position for backward step */
  66.   int             lp;         /* life points of this crab */
  67.   struct RastPort *RP;        /* which map is the crab using */
  68. }     crab[MAXCRABS];         /* crabs' state */
  69.  
  70. int     NumCrabs = 0;         /* number of crabs on screen */
  71.  
  72. /* Crab images to be drawen to the screen using the mask */
  73. unsigned short chip   crabup[] =          /* facing up */
  74. #  include "crabup.i"
  75. #ifndef ONEIMAGE
  76. unsigned short chip   crabdown[] =        /* facing down */
  77. #  include "crabdown.i"
  78. unsigned short chip   crabright[] =       /* facing right */
  79. #  include "crabright.i"
  80. unsigned short chip   crableft[] =        /* facing left */
  81. #  include "crableft.i"
  82. #endif
  83. unsigned short chip   crabmask[] =        /* crabs mask */
  84. #  include "crabmask.i"
  85.  
  86.   /* Bitmaps and raster ports of the screens */
  87. struct BitMap   BMtemp, BMmask, BMup;
  88. struct RastPort RPtemp, RPmask, RPup, RPscreen;
  89. #ifndef ONEIMAGE
  90. struct BitMap   BMdown, BMright, BMleft;
  91. struct RastPort RPdown, RPright, RPleft;
  92. #endif
  93.  
  94.  
  95.   /* function declarations */
  96. extern void     Init(), OpenLibraries(), InitWindow(), InitRP(), Print();
  97. extern void     CrabsExit(), Cycle(), DrawCrab(), HideCrab(), ModVel(), NewVel();
  98. extern BOOL     MoveCrab(), TestCrab(), TestBackground();
  99. extern void     RandInit();
  100. extern int      RandInt();
  101.  
  102. #ifdef CBACK
  103.   /* Cback.o initializations */
  104. LONG _stack = 2000;
  105. char *_procname = "Crabs";
  106. LONG _priority = -1;
  107. LONG _BackGroundIO = 0;
  108. #endif
  109.  
  110. void
  111. _main()
  112. {
  113.   Init();
  114.  
  115.   for (;;) {
  116.     Cycle();
  117.   }
  118.   /* NOTREACHED */
  119. }
  120.  
  121. void
  122. Init()
  123. /* set up initial crab layer */
  124. {
  125.   int             i;           /* crab # */
  126.  
  127.   OpenLibraries();        /* open the various system structures */
  128.  
  129.   if( ! (Window = OpenWindow( &NW )) )
  130.     CrabsExit(NULL);
  131.   RPwindow = Window->RPort;
  132.   WindowSignal = 1<<Window->UserPort->mp_SigBit;
  133.  
  134.   InitWindow();
  135.  
  136.   MyTask = FindTask( NULL );
  137.   WBScrn = Window->WScreen;
  138.   WBScrX = WBScrn->Width -SIZE;
  139.   WBScrY = WBScrn->Height -SIZE/2;
  140.  
  141.   memcpy((char *) &RPscreen, (char *) &(WBScrn->RastPort),
  142.                                       sizeof( struct RastPort ));
  143.  
  144.   InitRP(&RPup,    &BMup,    &crabup);
  145.   InitRP(&RPmask,  &BMmask,  &crabmask);
  146.   InitRP(&RPtemp,  &BMtemp,  NULL);
  147. #ifndef ONEIMAGE
  148.   InitRP(&RPdown,  &BMdown,  &crabdown);
  149.   InitRP(&RPleft,  &BMdown,  &crableft);
  150.   InitRP(&RPright, &BMright, &crabright);
  151. #endif
  152.  
  153.   RandInit();
  154.  
  155.   /* Create initial set of crabs: */
  156.   for (NumCrabs = 0; NumCrabs < STARTCRABS; NumCrabs++) {
  157.     for (i = PLACELIM; i > 0; i--) {
  158.       crab[NumCrabs].pos.x = RandInt(0, WBScrX-1);
  159.       crab[NumCrabs].pos.y = RandInt(0, WBScrY-1);
  160.       crab[NumCrabs].old = crab[NumCrabs].pos;
  161.       if( !TestBackground(NumCrabs) )
  162.         break;                              /* space found */
  163.     }
  164.     if( !i )                           /* did we reach the placement limit */
  165.       CrabsExit("Can't place crabs! No empty space found!");
  166.     crab[NumCrabs].lp = REPROlp / 2;
  167.     crab[NumCrabs].stat = Looking;
  168.     NewVel(NumCrabs);
  169.     DrawCrab(NumCrabs);
  170.   }
  171. }
  172.  
  173. void
  174. OpenLibraries()
  175. {
  176.   if( ! (IntuitionBase = OpenLibrary( "intuition.library", 0 )) )
  177.     CrabsExit("Can't open Intuition Library");
  178.   if( ! (GfxBase = OpenLibrary( "graphics.library", 0 )) )
  179.     CrabsExit("Can't Open Graphics Library");
  180. }
  181.  
  182. void
  183. InitWindow()
  184. {
  185.   Move(RPwindow, Window->BorderLeft,
  186.           Window->BorderTop + RPwindow->TxBaseline );
  187.   SetAPen(RPwindow, 3);
  188.   Print("Reproducing Crabs by Anthony Thyssen");
  189.   SetAPen(RPwindow, 1);
  190.   Print("   Original idea from Scientific American");
  191. }
  192.  
  193. void
  194. InitRP(rp, bm, image)
  195.   struct RastPort *rp;
  196.   struct BitMap   *bm;
  197.   short           *image;
  198. {
  199.   InitBitMap(bm,  1, SIZE,SIZE/2);
  200.   if( image )
  201.     bm->Planes[0] = (PLANEPTR) image;
  202.   else
  203.     if( !(bm->Planes[0] = (PLANEPTR)
  204.          AllocRemember( &Remember, RASSIZE(SIZE,SIZE/2),
  205.              MEMF_CHIP | MEMF_CLEAR) ) ) {    /* allocate with memory */
  206.       CrabsExit("Can't alloc raster");
  207.     }
  208.   InitRastPort( rp );
  209.   rp->BitMap = bm;
  210. }
  211.  
  212. void
  213. Print(str)
  214.   char *str;
  215. {
  216.   Text( RPwindow, str, strlen(str) );
  217.   Move( RPwindow, Window->BorderLeft,
  218.       RPwindow->cp_y + RPwindow->TxHeight); /* move to next line */
  219. }
  220.  
  221. void
  222. CrabsExit(exitmessage)
  223.   char *exitmessage;
  224. /* exit crabs - remove all traces */
  225. {
  226.   int             i;
  227.  
  228.   for (i = 0; i < NumCrabs; ++i)
  229.     HideCrab(i);
  230.  
  231.   RefreshWindowFrame(Window);
  232.   InitWindow();
  233.   if( Window && exitmessage ) {
  234.     Print(exitmessage);
  235.     /*printf("%s\n", exitmessage); /* Debugging */
  236.     Delay(200);
  237.   }
  238.  
  239.   FreeRemember( &Remember, TRUE );    /* Frre all allocated memory */
  240.  
  241.   if( Window )          CloseWindow( Window );
  242.   if( GfxBase )         CloseLibrary( GfxBase );
  243.   if( IntuitionBase )   CloseLibrary( IntuitionBase );
  244.  
  245.   _exit(0);
  246. }
  247.  
  248. void
  249. Cycle()
  250.   /* one motion cycle for all crabs */
  251. {
  252.   int             i;
  253.  
  254.   /* test for window closure */
  255.   if( message = (struct IntuiMessage *)GetMsg(Window->UserPort) ) {
  256.     ReplyMsg( (struct Message *)message );
  257.     switch( message->Class ) {
  258.       case CLOSEWINDOW : /* window closed message */
  259.         CrabsExit("Crabs are Exiting");
  260.     }
  261.   } /* Message test */
  262.  
  263.   if( NumCrabs < 5 )
  264.     Delay( DELAY );         /* slow down the small number of crabs */
  265.  
  266.   for (i = 0; i < NumCrabs; i++) {
  267.  
  268.     /* did something bite the crab - image corrupted ? */
  269.     if (TestCrab(i)) {              /* if so damage the crab */
  270.       crab[i].lp -= BITElp;
  271.       NewVel(i);
  272.     }
  273.  
  274.     switch( crab[i].stat ) {        /* do the nessary move */
  275.       case Looking:
  276.         HideCrab(i);                 /* erase crab from previous position */
  277.         crab[i].old = crab[i].pos;   /* record current position */
  278.         if (MoveCrab(i))             /* find the new positioN */
  279.           crab[i].lp -= BOUNCElp;    /* crab bounced - that smarts */
  280.         if (TestBackground(i))       /* Test if crab hits an object */
  281.           crab[i].stat = Nibbling;   /* if so crab will now nibble */
  282.         crab[i].lp -= MOVElp;        /* drain movement cost from crab */
  283.         if (crab[i].lp < 0) {        /* check on starvation */
  284.           crab[i] = crab[--NumCrabs];
  285.           if (NumCrabs == 0)
  286.             CrabsExit("The last Crab just died!\n");
  287.           i--;
  288.           continue;                  /* repeat this crab as it is the next one */
  289.         }
  290.         DrawCrab(i);                 /* redraw crab here */
  291.         ModVel(i, 1);                /* very slight direction change */
  292.         break;
  293.  
  294.       case Nibbling:
  295.         HideCrab(i);                 /* erase crab from previous position */
  296.         crab[i].pos = crab[i].old;   /* move crab backwards */
  297.         DrawCrab(i);                 /* draw crab here */
  298.         crab[i].stat = Munching;     /* chew over the food */
  299.         break;
  300.  
  301.       case Munching:
  302.         crab[i].lp += FEEDlp;        /* feed the food to the crab */
  303.         ModVel(i, FEEDVEL);          /* look in roughly the same dir as before */
  304.         crab[i].stat = Looking;      /* time taken to eat - look for more */
  305.         if (crab[i].lp >= REPROlp) { /* check for reproduction */
  306.           HideCrab(i);               /* remove parent */
  307.           crab[i].lp /= 2;           /* half life force */
  308.           if (NumCrabs < MAXCRABS) { /* is a new crab is possible */
  309.             crab[NumCrabs] = crab[i]; /* child is a copy of parent */
  310.             crab[NumCrabs].vel.x = -crab[NumCrabs].vel.x; /* reverse dir */
  311.             crab[NumCrabs].vel.y = -crab[NumCrabs].vel.y;
  312.             crab[NumCrabs].lp -= BITElp; /* child is weak */
  313.             MoveCrab(i);             /* move crabs away from each other */
  314.             MoveCrab(NumCrabs++);    /* move child twice - inc number crabs */
  315.             /* leave the child undrawen and corrupted! */
  316.           }
  317.           DrawCrab(i);               /* draw parent regardless of child state */
  318.         }
  319.         break;
  320.     }
  321.   }                                 /* move next crab */
  322. }
  323.  
  324. BOOL
  325. MoveCrab(i)
  326.   int             i;
  327. /* move crab to on screen position - don't draw it */
  328. /* if the crab hits edge of screen return TRUE */
  329. {
  330.   BOOL        hit = FALSE;
  331.  
  332.   crab[i].pos.x += crab[i].vel.x;        /* motion */
  333.   crab[i].pos.y += crab[i].vel.y;
  334.   if( crab[i].pos.x < 0 ) {
  335.     crab[i].pos.x = 0;
  336.     crab[i].vel.x = abs(crab[i].vel.x);
  337.     hit = TRUE;
  338.   }
  339.   if( crab[i].pos.x > WBScrX ) {
  340.     crab[i].pos.x = WBScrX;
  341.     crab[i].vel.x = -abs(crab[i].vel.x);
  342.     hit = TRUE;
  343.   }
  344.   if( crab[i].pos.y < 0 ) {
  345.     crab[i].pos.y = 0;
  346.     crab[i].vel.y = abs(crab[i].vel.y);
  347.     hit = TRUE;
  348.   }
  349.   if( crab[i].pos.y > WBScrY ) {
  350.     crab[i].pos.y = WBScrY;
  351.     crab[i].vel.y = -abs(crab[i].vel.y);
  352.     hit = TRUE;
  353.   }
  354.   return (hit);
  355. }
  356.  
  357. BOOL
  358. TestCrab(i)
  359.   int             i;
  360. /* test the crabs image on the screen. return TRUE if corrupt */
  361. /* invisible crabs are the background texture */
  362. {
  363.   int j;
  364.   UBYTE *byte;
  365.  
  366.   /* get crab stored on screen */
  367.   ClipBlit( &RPscreen, crab[i].pos.x, crab[i].pos.y,
  368.             &RPtemp, 0, 0, SIZE, SIZE/2, BM_SRC );
  369.   /* mask out background */
  370.   ClipBlit( &RPmask, 0, 0, &RPtemp, 0, 0,
  371.             SIZE, SIZE/2, BM_SRC & BM_DST );
  372.   /* xor with crab image */
  373.   ClipBlit( crab[i].RP, 0, 0, &RPtemp, 0, 0,
  374.             SIZE, SIZE/2, BM_SRC ^ BM_DST );
  375.  
  376.   /* check the data */
  377.   byte = BMtemp.Planes[0];
  378.   for (j = RASSIZE(SIZE, SIZE/2)-1; j >= 0; j--)
  379.     if( *(byte++) )
  380.       return TRUE;
  381.  
  382.   return FALSE;
  383. }
  384.  
  385. BOOL
  386. TestBackground(i)
  387.   int             i;
  388. /* return TRUE if crab position is not the background */
  389. {
  390.   int  j;
  391.   UBYTE *byte;
  392.  
  393.   /* get screen at crab location */
  394.   ClipBlit( &RPscreen, crab[i].pos.x, crab[i].pos.y,
  395.             &RPtemp, 0, 0, SIZE, SIZE/2, BM_SRC );
  396.   /* mask out background */
  397.   ClipBlit( &RPmask, 0, 0, &RPtemp, 0, 0,
  398.             SIZE, SIZE/2, BM_SRC & BM_DST );
  399.  
  400.   /* check the data */
  401.   byte = BMtemp.Planes[0];
  402.   for (j = RASSIZE(SIZE, SIZE/2)-1; j >= 0; j--)
  403.     if( *(byte++) )
  404.       return TRUE;
  405.  
  406.   return FALSE;
  407. }
  408.  
  409. void
  410. HideCrab(i)
  411. /* over write current crab with screen texture */
  412. {
  413.   ClipBlit( &RPmask, 0, 0, &RPscreen, crab[i].pos.x, crab[i].pos.y,
  414.             SIZE, SIZE/2, ~BM_SRC & BM_DST );
  415. }
  416.  
  417. void
  418. DrawCrab(i)
  419.   int             i;
  420. /* Draw the crabs on the screen if visible */
  421. {
  422.   HideCrab(i);
  423.   crab[i].RP = PICKMAP( crab[i].vel );
  424.   ClipBlit( crab[i].RP, 0, 0, &RPscreen, crab[i].pos.x, crab[i].pos.y,
  425.             SIZE, SIZE/2, BM_SRC | BM_DST );
  426. }
  427.  
  428. void
  429. NewVel(i)                              /* assign new velocity to crab */
  430.   int             i;                   /* crab # */
  431. {
  432.   crab[i].vel.x = RandInt(-MAXVEL, MAXVEL);
  433.   crab[i].vel.y = RandInt(-MAXVEL/2, MAXVEL/2);
  434.  
  435.   /* Velocity (0,0) is okay since we repeatedly modify all velocities. */
  436. }
  437.  
  438. void
  439. ModVel(i, dv)                              /* randomly modify crab velocity */
  440.   int             i,dv;                   /* crab, delta velocity */
  441. {
  442.   int             min,max;                 /* range of new velocity */
  443.  
  444.   min=crab[i].vel.x-dv;
  445.   max=crab[i].vel.x+dv;
  446.   if ( max > MAXVEL)
  447.     max = MAXVEL;
  448.   if ( min < -MAXVEL)
  449.     min = -MAXVEL;
  450.   crab[i].vel.x = RandInt(min, max);
  451.  
  452.   min=crab[i].vel.y-dv;
  453.   max=crab[i].vel.y+dv;
  454.   if ( max > MAXVEL/2)
  455.     max = MAXVEL/2;
  456.   if ( min < -MAXVEL/2)
  457.     min = -MAXVEL/2;
  458.   crab[i].vel.y = RandInt(min, max);
  459. }
  460.  
  461. void
  462. RandInit()
  463. {
  464.   srand((int)time(NULL));
  465. }
  466.  
  467. int
  468. RandInt(lo, hi)                        /* generate random integer in range */
  469.   int             lo, hi;              /* range lo..hi inclusive */
  470. {
  471.   return lo + (int)( (unsigned)rand() % (hi - lo +1) );
  472. }
  473.  
  474.  
  475.