home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff256.lzh / BlitDemons / bdemon.c < prev    next >
C/C++ Source or Header  |  1989-10-19  |  14KB  |  425 lines

  1. echo;  /* Self-compilation stuff ala John Toebes for Lattice users:
  2. lc -M bdemon.c bdintui.c bdblit.c bdwin.c
  3. blink with bdemon.with
  4. quit
  5.  
  6. *****************************************************************************
  7. *   BlitDemons by Walter Strickler
  8. *   This program and all its source code are in the public domain and are
  9. * freely distributable and usable for any purpose, private or commercial.
  10. *
  11. *   This program is a port of a program by Loren Blaney which runs under
  12. * Apex, an unknown operating system on the Amiga.  It is based on the 
  13. * cellular automaton called 'Demons' described in the August, 1989,
  14. * issue of Scientific American.  
  15. *
  16. *   It is not my fault that it busy-waits.  This is usually inexcusable in
  17. * an Amiga program, but it is the call to WaitBlit() that causes it.  It is
  18. * really a shame, since this program should require only a small portion of
  19. * the 68000.  As it is, it hogs all of it.
  20. ****************************************************************************/
  21.  
  22.  
  23. #include <math.h>
  24. #include "bdemon.h"
  25.  
  26.  
  27. int main()
  28.     { 
  29.     int                 IntuiReturn,
  30.                         IPRet,
  31.                         RetVal;
  32.     struct BDMainStruct BDStuff;
  33.  
  34.     IntuiReturn = InitIntui();
  35.     if (IntuiReturn == INTUI_OK)
  36.         {
  37.         IPRet = InitPlanes(&BDStuff, BDWindow);
  38.         if (IPRet != PLANES_CHOKE)
  39.             {
  40.             BDStuff.BDBlitNodes = InitBlits(&BDStuff);
  41.             if (BDStuff.BDBlitNodes != NULL)
  42.                 {
  43.                 RetVal = MainLoop(&BDStuff);
  44.                 }
  45.             else
  46.                 {
  47.                 RetVal = INIT_BLIT_CHOKE;
  48.                 }
  49.             }   /* End BDStuff OK */
  50.         else
  51.             {
  52.             RetVal = PLANES_CHOKE;        
  53.             }      /* End BDStuff not OK */
  54.         KillPlanes(&BDStuff);
  55.         }   
  56.     else  /* Single entry, single exit:  so there, Guy! */
  57.         {
  58.         RetVal = IntuiReturn;   
  59.         }
  60.     CloseIntui();
  61.     ErrorMsgs(RetVal);
  62.     return RetVal;
  63.     }   /* End main() */
  64.  
  65.  
  66. void ErrorMsgs(ErrorNum)
  67.     int ErrorNum;
  68.     {
  69.     switch (ErrorNum)
  70.         {
  71.         case 0:
  72.             break;  /* A-OK */
  73.         case NO_INTUI:
  74.             printf("Couldn't open Intuition!\n");
  75.             break;
  76.         case NO_GFX:
  77.             printf("Couldn't open Graphics!\n");
  78.             break;
  79.         case NO_SCREEN:
  80.             printf("Couldn't open the Screen.\n");
  81.             break;
  82.         case NO_WIN:
  83.             printf("Couldn't open the Window.\n");
  84.             break;
  85.         case PLANES_CHOKE:
  86.             printf("Couldn't allocate the temp. bit planes.\n");
  87.             break;
  88.         case ABOUT_CHOKE:
  89.             printf("Couldn't open the about window.\n");            
  90.             break;
  91.         case INIT_BLIT_CHOKE:
  92.             printf("Couldn't allocate the blitter nodes.\n");
  93.             break;
  94.         case WBI_CHOKE:
  95.             printf("Couldn't start the blitter interrupt.\n");
  96.             break;
  97.         default:
  98.             printf("Unknown error: %d\n", ErrorNum); 
  99.             break;
  100.         }
  101.     }
  102.  
  103.  
  104. /************************************************************************/
  105. int MainLoop(BDSchtoff)
  106.     struct BDMainStruct  *BDSchtoff;
  107.  
  108.     {
  109.     int RetVal,
  110.         LeavingNow,
  111.         MsgVal,
  112.         MsgControl,
  113.         RandReturn,
  114.         First;
  115.  
  116.     RetVal = ML_OK;
  117.     LeavingNow = FALSE;
  118.     MsgControl = NO_WAIT;
  119.     First = TRUE;
  120.     while (LeavingNow == FALSE) 
  121.         {
  122.         if (First)
  123.             {
  124.             First = FALSE;  /* Do this once only */
  125.             MsgVal = NEW;  /* Hotwire MsgVal on first time through */
  126.             }   /* End First */
  127.         else
  128.             {
  129.             if (MsgControl == NO_WAIT) /* If we do WAIT, hurry up and wait! */
  130.                 {
  131.                 OneGen(BDSchtoff);
  132.                 }
  133.             MsgVal = CheckMsg(MsgControl);  
  134.             }   /* End not First */
  135.  
  136.         switch (MsgVal)
  137.             {
  138.             case CLOSE_WIN:
  139.             case QUIT:
  140.                 LeavingNow = TRUE;
  141.                 break;
  142.             case NEW:
  143.                 RandReturn = Randomize(BDSchtoff, BDWindow);
  144.                 switch (RandReturn)
  145.                     {
  146.                     case RAND_OK:
  147.                         OffStart();          /* Set menu items */
  148.                         OnStop();
  149.                         MsgControl = NO_WAIT;
  150.                         break;
  151.                     case RAND_QUIT:
  152.                         LeavingNow = TRUE;
  153.                         break;
  154.                     case RAND_ABOUT_CHOKE:
  155.                         LeavingNow = TRUE;
  156.                         RetVal = ABOUT_CHOKE;
  157.                         break;
  158.                     }
  159.                 break;
  160.             case STOP:
  161.                 MsgControl = WAIT;
  162.                 OffStop();
  163.                 OnStart();
  164.                 break;
  165.             case START:
  166.                 MsgControl = NO_WAIT;
  167.                 OffStart();
  168.                 OnStop();
  169.                 break;
  170.             case ABOUT:
  171.                 if (DisplayAbout() == DA_CHOKE)
  172.                     {
  173.                     LeavingNow = TRUE;
  174.                     RetVal = ABOUT_CHOKE;
  175.                     }
  176.                 break;
  177.             case NO_MSG:
  178.                 /* One more generation. */
  179.                 break;
  180.             default:
  181.                 assert (FALSE);  /* Shouldn't be here */
  182.                 break;
  183.             }   /* End case CheckMsg() */
  184.         }  /* End while not leaving */
  185.     return RetVal;
  186.     }   /* End MainLoop() */
  187.  
  188.  
  189.  
  190. /*******************************************************************************
  191.      InitPlanes() fills in a structure of type BDMainStruct, pointed at by
  192.    Strcut, given the pointer to a window, *Win.  Returns PLANES_CHOKE if any 
  193.    allocations weren't successful.
  194. *******************************************************************************/
  195. int InitPlanes(Struct, Win)
  196.     struct BDMainStruct *Struct;
  197.     struct Window *Win;
  198.  
  199.     {
  200.     int i,
  201.         DispStartOffset,
  202.         RetVal;
  203.  
  204.     RetVal = PLANES_OK;
  205.     /* Find the relative start of the blitfield in words */
  206.     /* Note that BorderTop and BorderBottom are 1 too large */
  207.     DispStartOffset = (((Win -> BorderTop) - 1 ) + Win -> TopEdge)
  208.      * ((Win -> WScreen -> Width) / 16) + (Win -> LeftEdge) / 16;
  209.     for (i=0; i < NUM_PLANES; i++)
  210.         {
  211.         (Struct -> Display)[i] =  DispStartOffset +
  212.          (WORD *) Win -> RPort -> BitMap -> Planes[i];  /* Whew! */
  213.         }
  214.     Struct -> XSize = Win -> Width;
  215.     Struct -> YSize = (Win -> Height) - ((Win -> BorderTop) - 1) - 
  216.      ((Win -> BorderBottom) - 1);     /* Sub. borders */
  217.     Struct -> Mod = (Win -> WScreen -> Width) - (Win -> Width);/* Blit Modulo */
  218.     /* Note that BorderLeft and BorderRight are 2 too large */
  219.     Struct -> LRBorder = max (Win -> BorderLeft - 2, Win -> BorderLeft - 2);
  220.  
  221.     /* Now allocate some bitplanes for temporaries... */
  222.     Struct -> Temp = (WORD *) AllocRaster(Struct -> XSize, Struct -> YSize);
  223.     if (Struct -> Temp == 0)
  224.         {
  225.         RetVal = PLANES_CHOKE;
  226.         }    /* End Temp Choke */
  227.     else
  228.         {
  229.         Struct -> Equal = (WORD *)AllocRaster(Struct -> XSize, Struct -> YSize);
  230.         if (Struct -> Equal == 0)
  231.             {
  232.             RetVal = PLANES_CHOKE;
  233.             }  /* End Equal choke */
  234.         else
  235.             {
  236.             i = 0;
  237.             while ((RetVal != PLANES_CHOKE) && (i < NUM_PLANES))
  238.                 {
  239.                 Struct -> Incr[i] = (WORD *) AllocRaster(Struct -> XSize, 
  240.                  Struct -> YSize);
  241.                 if (Struct -> Incr[i] == 0)
  242.                     {
  243.                     RetVal = PLANES_CHOKE;
  244.                     }
  245.                 i++;
  246.                 }  /* End While allocating Incr */
  247.         }    /* End Equal OK */
  248.         }  /* End Temp OK */
  249.     return RetVal;
  250.     } /* End InitPlanes */
  251.  
  252.  
  253. /*******************************************************************************
  254.      KillPlanes() deallocates all of the temporary bitplanes allocated
  255.    in InitPlanes.
  256. *******************************************************************************/
  257.  
  258. void KillPlanes(Struct)
  259.     struct BDMainStruct *Struct;
  260.  
  261.     {
  262.     int i;
  263.     
  264.     if (Struct -> Temp != 0)
  265.         {
  266.         FreeRaster((PLANEPTR)Struct -> Temp, Struct -> XSize, Struct -> YSize);
  267.         Struct -> Temp = 0;
  268.         }
  269.     if (Struct -> Equal != 0)
  270.         {
  271.         FreeRaster((PLANEPTR)Struct -> Equal, Struct -> XSize, Struct -> YSize);
  272.         Struct -> Equal = 0;
  273.         }
  274.     for (i = 0; i < NUM_PLANES; i++)
  275.         {
  276.         if (Struct -> Incr[i] != 0)
  277.             {
  278.             FreeRaster((PLANEPTR) Struct -> Incr[i], Struct -> XSize, 
  279.              Struct -> YSize);
  280.             Struct -> Incr[i] = NULL;
  281.             }
  282.         }
  283.     }  /* End KillPlanes() */
  284.  
  285.  
  286.  
  287. /*******************************************************************************
  288.     Randomize() sets every pixel within the borders of the window pointed
  289.    at by Win.
  290. *******************************************************************************/
  291. int Randomize(BDStuff, Win)
  292.     struct BDMainStruct *BDStuff;
  293.     struct Window       *Win;
  294.  
  295.     {
  296.     int  Left, 
  297.          Right, 
  298.          Top, 
  299.          Bottom, 
  300.          XWords,
  301.          YLines,
  302.          i,
  303.          x, 
  304.          y,
  305.          Redo,
  306.          MsgControl,
  307.          MsgVal,
  308.          LeavingNow,
  309.          PlaneNum,
  310.          RetVal;
  311.     WORD LRBorder,
  312.          LMask,
  313.          RMask,
  314.        *(Disp[NUM_PLANES]),
  315.          MyWord,
  316.          RandWord;
  317.     long Seed;
  318.     struct DateStamp *Now;
  319.  
  320.     MsgControl = NO_WAIT;
  321.     RetVal = RAND_OK;   /* Innocent until proven guilty */
  322.     LeavingNow = FALSE;
  323.     do  /* Loop if Redo gets set to TRUE by the NEW menuitem. */
  324.         {
  325.         Redo = FALSE;  /* Only one more time unless Redo gets set */
  326.         /* Seed the random number generator with number of TICK's today: */
  327.         Now = (struct DateStamp *)  malloc (sizeof (struct DateStamp));
  328.         DateStamp(Now);  /* This Lattice compiler warning is not my fault */
  329.         Seed = (Now -> ds_Tick) + ((Now -> ds_Minute) * TICKS_PER_SECOND * 60);
  330.         free(Now);
  331.         srand(Seed);
  332.         
  333.         /* Set the border masks */
  334.         LRBorder = BDStuff -> LRBorder;
  335.         LMask = 0xffff >> LRBorder;
  336.         RMask = 0xffff << LRBorder;
  337.  
  338.         /* Set the plane pointers */
  339.         for (i=0; i < NUM_PLANES; i++)
  340.             {
  341.             Disp[i] = BDStuff -> Display[i];
  342.             }        
  343.         
  344.         /* Clear the screen first */
  345.         Left = LRBorder;
  346.         Right = ((BDStuff -> XSize) -1) - LRBorder;
  347.         Top = (BDWindow -> BorderTop) -1;  /* Border off by one */
  348.         Bottom = (BDWindow -> Height) - (BDWindow -> BorderBottom);
  349.         SetAPen (BDWindow -> RPort, 0);
  350.         RectFill (BDWindow -> RPort, Left, Top, Right, Bottom);
  351.  
  352.         /* Now set pixels Randomly */
  353.         /* Sweep from top to bottom; bail out if Redo or LeavingNow gets set */
  354.         XWords = (BDStuff -> XSize) / 16;
  355.         YLines = (BDStuff -> YSize);
  356.         y = 0;
  357.         while ((y < YLines) && (!Redo) && (!LeavingNow))  
  358.             {
  359.             for (x = 0; x < XWords; x++)
  360.                 {
  361.                 for (PlaneNum = 0; PlaneNum < NUM_PLANES; PlaneNum++)
  362.                     {
  363.                     RandWord = (rand() >> 8) & 0xffff; /* Use middle 16 bits */
  364.                     /* Set MyWord given LMask and RMask */    
  365.                     if (x == 0)    /* First word */
  366.                         {
  367.                         MyWord = *(Disp[PlaneNum]) & ~LMask;
  368.                         MyWord = MyWord | (RandWord & LMask);
  369.                         }
  370.                     else if (x == (XWords -1))  /* Last word */
  371.                         {
  372.                         MyWord = *(Disp[PlaneNum]) & ~RMask;
  373.                         MyWord = MyWord | (RandWord & RMask);
  374.                         }
  375.                     else
  376.                         { 
  377.                         MyWord = RandWord;
  378.                         }
  379.                     *(Disp[PlaneNum]) = MyWord;
  380.                     (Disp[PlaneNum])++;
  381.                     }  /* End for PlaneNum */
  382.                 }  /* End for x */
  383.             MsgVal = CheckMsg(MsgControl);
  384.             switch(MsgVal)
  385.                 {
  386.                 case CLOSE_WIN:
  387.                 case QUIT:
  388.                     RetVal = RAND_QUIT;
  389.                     LeavingNow = TRUE;
  390.                     break;
  391.                 case STOP:
  392.                     MsgControl = WAIT;
  393.                     OffStop();
  394.                     OnStart();
  395.                     break;
  396.                 case START:
  397.                     MsgControl = NO_WAIT;
  398.                     OffStart();
  399.                     OnStop();
  400.                     break;
  401.                 case NEW:
  402.                     Redo = TRUE;
  403.                     MsgControl = NO_WAIT;
  404.                     OffStart();
  405.                     OnStop();
  406.                     break;
  407.                 case ABOUT:
  408.                     if (DisplayAbout() == DA_CHOKE)
  409.                         {
  410.                         LeavingNow = TRUE;   /* Let's bomb out now */
  411.                         RetVal = RAND_ABOUT_CHOKE;
  412.                         }
  413.                     break;
  414.                 case NO_MSG:
  415.                     break;
  416.                 default:
  417.                     assert (FALSE);  /* Shouldn't be here */
  418.                     break;
  419.                 }
  420.             y++;  /* Next line */
  421.             }  /* End for y */
  422.         } while (Redo);
  423.     return RetVal;
  424.     }    /* End Randomize() */
  425.