home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff218.lzh / Worm / worm.c < prev    next >
C/C++ Source or Header  |  1989-06-04  |  12KB  |  429 lines

  1. /*
  2.  * worm.c
  3.  * 
  4.  * Adapted from the Scientific American article 12/87. Original for Sun UNIX.
  5.  * Original Author - Brad Taylor (sun!brad)
  6.  * Adapted to the Amiga by Chuck McManis (sun!cmcmanis)
  7.  * Basically there are five switches they are :
  8.  *    -l n Set the length of the worms to 'n' units, this defaults to 32.
  9.  *    -s n Set the size of the worm units to n X n, defaults to 1 but try
  10.  *         some larger sizes too, their kinda neat.
  11.  *    -n n Set the number of worms on the screen, defaults to 16 worms which
  12.  *         is fairly slow, 4 is pretty quick. Numbers like 3000 are neat too.
  13.  *    -r n Set the screen resolution, 0 = low res (320 X 200), 1 = medium (640 X 200)
  14.  *         and 2 = high (640 X 400)
  15.  *    -d n Set number of bitplanes, 1-5 are acceptable numbers.
  16.  *
  17.  * Note this uses a random number generator that Leo used in demo.c
  18.  * Copyright (C) 1987 by Charles McManis
  19.  * Freely Redistributable if you leave the above comment and following declaration
  20.  * intact ...
  21.  */
  22.  
  23. static char copyright[] = "Copyright (C) 1987, Charles McManis, ok to copy.";
  24.  
  25. #include <exec/types.h>
  26. #include <exec/memory.h>
  27. #include <intuition/intuition.h>
  28. #include <graphics/gfxbase.h>
  29. #include <graphics/gfx.h>
  30. #include <graphics/rastport.h>
  31. #include <devices/inputevent.h>
  32. #include <libraries/diskfont.h>
  33. #include <stdio.h>
  34. #include <math.h>
  35. #ifdef LATTICE
  36. #include <proto/dos.h>
  37. #include <proto/graphics.h>
  38. #endif
  39.  
  40.  
  41. /* Declare the required Intuition pointers */
  42. struct    IntuitionBase    *IntuitionBase;
  43. struct    GfxBase        *GfxBase;
  44. struct    DiskfontBase    *DiskfontBase;
  45.  
  46. /* Declare some global tool stuff */
  47. struct     Window        *MyWindow;
  48. struct    Menu        *MyMenu, *CurrentMenu;
  49. struct    Screen        *MyScreen;
  50. struct  TextFont    *MyFont;
  51.  
  52. /* Declare some defines that make the code a bit more readable */
  53. #define SIGBIT(w)    (1L << (w->UserPort->mp_SigBit))
  54. #define GetIntuiMessage(w) (struct IntuiMessage *)GetMsg(w->UserPort)
  55. struct TextAttr    ta = {"topaz.font",11,0,0};
  56.  
  57. #define CMSIZE         30    /* Max color map size                */
  58. #define CMFUDGE     2    /* colors needed for borders and background */
  59. #define SEGMENTS      36    /* Size of sin and cos tables            */
  60. #define MAXCOLOR    15    /* Most intense color                 */
  61.  
  62. extern char *malloc();
  63.  
  64. int wormlength = 32;
  65. int circsize = 1;
  66. int nworms = 16;
  67. int black,white;
  68. int cmsize;
  69. int sintab[SEGMENTS];
  70. int costab[SEGMENTS];
  71.  
  72.  
  73. /*
  74.  * Initialized data section. These structures are pre-initialized with 
  75.  * the values that the program knows ahead of time.
  76.  */
  77.  
  78. struct NewScreen ns = {
  79.     0,0,640,400,3,    /* (X,Y) (W,H) (bitplanes)     */
  80.     1,0,        /* Foreground, Background      */
  81.     0,        /* View Modes (defaults to none */
  82.     CUSTOMSCREEN,    /* What else is new           */
  83.     NULL,        /* Font is set up below       */
  84.     "Worms, implementation by Chuck McManis V1.0",
  85.     NULL,        /* No special Gadgets           */
  86.     NULL        /* No Custom Bitmap           */
  87.     };
  88.  
  89. struct NewWindow nw = {
  90.     0,0,640,400,    /* (X,Y) (W,H)            */
  91.     7,6,        /* Foreground, Background    */
  92.     CLOSEWINDOW+REFRESHWINDOW,
  93.     WINDOWCLOSE+SIMPLE_REFRESH+ACTIVATE,
  94.     NULL,        /* No special Gadgets        */
  95.     NULL,        /* Use the default Checkmark    */
  96.     "Squiggly Worms, Implementation by Chuck McManis",
  97.     NULL,        /* This will be our screen pointer */
  98.     NULL,        /* We'll use the Bitmap we get    */
  99.     640,400,640,400, /* No resizing going on */
  100.     CUSTOMSCREEN    /* We'll use our own screen thankyou */
  101.     };
  102.  
  103.  
  104. /*
  105.  * Some declarations for worm, 
  106.  */
  107.  
  108. USHORT    colors[32];    /* A place to create the color table */
  109. int    ScreenRes = 1;    /* Screen Resolution (0=low 2=hi)    */
  110. ULONG    MaxX, MaxY;    /* Window inside dimensions          */
  111.  
  112. struct wormstuff {
  113.     int *xcirc;
  114.     int *ycirc;
  115.     int dir;
  116.     int tail;
  117.     int x;
  118.     int y;
  119.     int id;
  120. };
  121.  
  122.  
  123. void worm_doit(),drawseg(),goaway(),usage(), color_setup();
  124. short    rnd();
  125. struct wormstuff *worm_init();
  126.  
  127. /* 
  128.  * Ok, declarations are out of the way, on with the main function 
  129.  */
  130. void main(argc,argv)
  131.  
  132. int    argc;
  133. char    *argv[];    
  134.     
  135. {
  136.   struct IntuiMessage    *im;      /* Intuimessage pointer         */
  137.   struct Window        *wp;      /* Temporary window pointer        */
  138.   ULONG            class;      /* Message Class holder        */
  139.   USHORT        code,qual;/* Message Code and qualifiers     */
  140.   SHORT            msx,msy;  /* Mouse Co-ordinates for event     */
  141.   int             i,      /* Your basic counter variable    */
  142.             xsize,ysize,
  143.             depth;      /* How many bitplanes did you want?    */
  144.   struct wormstuff     **worm;      /* Worm data                */
  145.   char             *cmd;
  146.  
  147.   cmd = argv[0];
  148.   depth = 3;        /* default depth */
  149.   rnd(0);
  150.   if (argc == 0) {     /* Started from workbench */
  151.     printf("Worm length : ");
  152.     scanf("%d",&wormlength);
  153.     printf("Number of worms [n] :");
  154.     scanf("%d",&nworms);
  155.     printf("Worm width [n] :");
  156.     scanf("%d",&circsize);
  157.     printf("Screen Resolution [0=Low, 1=Medium, 2=High] :");
  158.     scanf("%d",&ScreenRes);
  159.     printf("Number of bitplanes [1-5 for Low res, 1-4 for medium or high] :");
  160.     scanf("%d",&depth);
  161.   }
  162.   for (i = 1; i < argc; i++) {
  163.     if (i == argc - 1 || argv[i][0] != '-' || argv[i][2] != 0) {
  164.       usage(cmd);
  165.     }
  166.     switch (argv[i][1]) {
  167.       case 'l':
  168.     wormlength = atoi(argv[++i]);
  169.     break;
  170.       case 'n':
  171.     nworms = atoi(argv[++i]);
  172.     break;
  173.       case 's':
  174.     circsize = atoi(argv[++i]);
  175.     break;
  176.       case 'r':
  177.         ScreenRes = atoi(argv[++i]);
  178.     break;
  179.       case 'd':
  180.     depth = atoi(argv[++i]);
  181.     if ((depth < 1) || (depth > 5)) usage(cmd);
  182.     break;
  183.       default:
  184.         usage(cmd);
  185.     }
  186.   }
  187.   if ((ScreenRes > 0) && (depth == 5)) depth = 4; 
  188.   cmsize = (1 << depth) - CMFUDGE;
  189.   for (i = 0; i < SEGMENTS; i++) {
  190.     sintab[i] = round(circsize * sin(i * 2 * PI / SEGMENTS));
  191.     costab[i] = round(circsize * cos(i * 2 * PI / SEGMENTS));
  192.   }
  193.   /* Open the intuition library first ... */
  194.   IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
  195.   if (! IntuitionBase) goaway();
  196.  
  197.   /* Now opening the graphics library ... */
  198.   GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
  199.   if (! GfxBase) goaway();
  200.  
  201.   /* Now opening the diskfont library ... */
  202.   DiskfontBase = (struct DiskfontBase *)OpenLibrary("diskfont.library",0);
  203.   if (! DiskfontBase) goaway();
  204.  
  205.   /* This opens a custom screen to the maximum possible size ... */
  206.   ns.Depth = depth;
  207.   ns.Width = GfxBase->NormalDisplayColumns;
  208.   ns.Height = GfxBase->NormalDisplayRows;
  209.   switch (ScreenRes) {
  210.     case 0 : 
  211.       ns.Width /= 2;
  212.       ta.ta_YSize = 8;
  213.       ta.ta_Flags |= FPF_ROMFONT;
  214.       ns.Font = &ta;
  215.       break;
  216.     case 1 :
  217.       ns.ViewModes |= HIRES;
  218.       /* In medium res use Topaz 8 */
  219.       ta.ta_YSize = 8;
  220.       ta.ta_Flags |= FPF_ROMFONT;
  221.       ns.Font = &ta;
  222.       break;
  223.     case 2 :
  224.       ns.Height *= 2;
  225.       ns.ViewModes |= HIRES+LACE;
  226.       /* In Interlace mode us Topaz 11 */
  227.       ns.Font = &ta;
  228.   }
  229.  
  230.   /* Now we open the font we want so that it will be resident when the 
  231.    * OpenScreen call below needs it.
  232.    */
  233.   MyFont = (struct TextFont *) OpenDiskFont(&ta);
  234.   
  235.   MyScreen = (struct Screen *)OpenScreen(&ns);
  236.  
  237.   if (! MyScreen) goaway();
  238.   color_setup();        /* Initialize the color map */
  239.   /* OK so far, now lets open a full size window ... */
  240.   nw.Screen = MyScreen;
  241.   nw.TopEdge = 1; /* Leave a row to grab the screen drag bar */
  242.   nw.Width = ns.Width;
  243.   nw.Height = ns.Height-1;
  244.   nw.DetailPen = white;        /* initialized by color_setup() */
  245.   nw.BlockPen = black;
  246.   MyWindow = (struct Window *)OpenWindow(&nw);
  247.   if (! MyWindow) goaway();
  248.  
  249.   SetFont(MyWindow->RPort,MyFont); /* This should not be required ! */
  250.  
  251.   MaxX = xsize = MyWindow->Width-MyWindow->BorderLeft-MyWindow->BorderRight;
  252.   MaxY = ysize = MyWindow->Height-MyWindow->BorderTop-MyWindow->BorderBottom;
  253.   SetAPen(MyWindow->RPort,black);
  254.   RectFill(MyWindow->RPort, MyWindow->BorderLeft,MyWindow->BorderTop,
  255.     MyWindow->BorderLeft+xsize, MyWindow->BorderTop+ysize);
  256.   worm = (struct wormstuff **)malloc((unsigned)(sizeof(struct wormstuff *) * nworms));
  257.   for (i = 0; i < nworms; i++) {
  258.     worm[i] = worm_init(xsize, ysize, wormlength);
  259.   }
  260.   if (!cmsize) cmsize = 1;
  261.  
  262.   for (;;) {
  263.     for (i = 0; i < nworms; i++) {
  264.     worm_doit((void *)MyWindow->RPort, worm[i], xsize, ysize,
  265.           (((i * cmsize) / nworms) % cmsize));
  266.     }
  267.     /* Note: If we are running continuously we don't Wait(), this lets */
  268.     /* the program continue to update the screen until the user sends  */
  269.     /* it some form of request.                              */
  270.     while ((im = GetIntuiMessage(MyWindow)) != NULL) {
  271.       class = im->Class;    /* Extract relavent info */
  272.       code  = im->Code;        
  273.       qual  = im->Qualifier;    /* Stuff like shift down etc */
  274.       msx   = im->MouseX;    /* And the mouse position    */
  275.       msy   = im->MouseY;
  276.       wp    = im->IDCMPWindow;    /* Figure out which window sent this message */
  277.       ReplyMsg(im);        /* Reply quickly! */
  278.       switch (class) {
  279.     case CLOSEWINDOW :     /* Process a close window message. */
  280.       goaway();         /* Exit the program */
  281.     case REFRESHWINDOW :
  282.       BeginRefresh(MyWindow);
  283.       EndRefresh(MyWindow,TRUE);
  284.       break;
  285.         default : /* We choose to ignore unknown message classes */
  286.       break;
  287.       } /* switch statement */
  288.     } /* until no messages are still waiting */
  289.   }
  290. }
  291.  
  292. /*
  293.  * Utility routines used by the Worm Program...
  294.  */
  295.  
  296. /*
  297.  * Function goaway()
  298.  *
  299.  * This function shuts down after we are done. Since this can happen at 
  300.  * anytime, it checks the various global variables and those that have
  301.  * been initialized (non-null), it removes/clears etc depending on the 
  302.  * variable.
  303.  */
  304. void goaway()
  305.  
  306. {
  307.   if (MyWindow) CloseWindow(MyWindow);
  308.   if (MyScreen) CloseScreen(MyScreen);
  309.   if (GfxBase) CloseLibrary(GfxBase);
  310.   if (MyFont) CloseFont(MyFont);
  311.   if (DiskfontBase) CloseLibrary(DiskfontBase);
  312.   if (IntuitionBase) CloseLibrary(IntuitionBase);
  313.   exit(0); /* This cleans up FILE pointers and malloc'd memory */
  314. }
  315.  
  316. struct wormstuff *
  317. worm_init(xsize, ysize, wormlength)
  318.     int xsize;
  319.     int ysize;
  320.     int wormlength;
  321. {
  322.     static int thisworm = 0;
  323.     int i;
  324.     struct wormstuff *ws;
  325.  
  326.     ws = (struct wormstuff *)malloc((unsigned)sizeof(struct wormstuff));
  327.     ws->xcirc = (int *)malloc((unsigned)(wormlength * sizeof(int)));
  328.     ws->ycirc = (int *)malloc((unsigned)(wormlength * sizeof(int)));
  329.     for (i = 0; i < wormlength; i++) {
  330.         ws->xcirc[i] = xsize / 2;
  331.         ws->ycirc[i] = ysize / 2;
  332.     }
  333.     ws->dir = rnd(SEGMENTS);
  334.     ws->tail = 0;
  335.     ws->x = xsize / 2;
  336.     ws->y = ysize / 2;
  337.     ws->id = thisworm;
  338.     thisworm = (thisworm + 1) % 14;
  339.     return (ws);
  340. }
  341.  
  342. void
  343. worm_doit(h, priv, xsize, ysize, color)
  344.     void *h;
  345.     void *priv;
  346.     int xsize;
  347.     int ysize;
  348.     int color;
  349. {
  350.     int x;
  351.     int y;
  352.     struct wormstuff *ws = (struct wormstuff *)priv;
  353.  
  354.     ws->tail = (ws->tail + 1) % wormlength;
  355.     x = ws->xcirc[ws->tail];
  356.     y = ws->ycirc[ws->tail];
  357.     drawseg(h, x, y, black);
  358.     if ((rnd(32765)&(1<<ws->id)) != 0) {
  359.         ws->dir = (ws->dir + 1) % SEGMENTS;
  360.     } else {
  361.         ws->dir = (ws->dir + SEGMENTS - 1) % SEGMENTS;
  362.     }
  363.     x = (ws->x + costab[ws->dir] + xsize) % xsize;
  364.     y = (ws->y + sintab[ws->dir] + ysize) % ysize;
  365.     ws->xcirc[ws->tail] = x;
  366.     ws->ycirc[ws->tail] = y;
  367.     /* Note when using one bitplane worm_doit gets called with color == 0 */
  368.     drawseg(h, x, y, (color != black) ? color : 1);
  369.     ws->x = x;
  370.     ws->y = y;
  371. }
  372.  
  373.  
  374.  
  375. round(x)
  376.     float x;
  377. {
  378.     if (x >= 0) return ((int)(x + .5));
  379.     return ((int)(x - .5));
  380. }
  381.  
  382. /* Note that drawseg does it's own clipping... */
  383. void
  384. drawseg(priv, x, y, color)
  385.     void *priv;
  386.     int x;
  387.     int y;
  388.     int color;
  389. {
  390.     struct RastPort *gfx = (struct RastPort *)priv;
  391.     ULONG    X,Y;
  392.  
  393.     X = ((unsigned) x % (MaxX-circsize)) + MyWindow->BorderLeft;
  394.         Y = ((unsigned) y % (MaxY-circsize)) + MyWindow->BorderTop;
  395.     SetAPen(gfx,color);
  396.     if (circsize == 1) WritePixel(gfx,X,Y);
  397.     else RectFill(gfx,X,Y,X+circsize,Y+circsize);
  398. }
  399.  
  400.  
  401. /* Sets up some reasonable colors ... note CMSIZE is max colors and 
  402.  * cmsize is the actual number of colors
  403.  */
  404.  
  405. void
  406. color_setup()
  407.  
  408. {
  409.     int i;
  410.  
  411.     for (i = 0; i < cmsize; i++) {
  412.       colors[i] = rnd(4096);
  413.     }
  414.     colors[cmsize] = 0;
  415.     colors[cmsize+1] = 4095;
  416.       LoadRGB4(&(MyScreen->ViewPort),colors,cmsize+CMFUDGE); /* Load in our colors */
  417.     black = cmsize;
  418.     white = cmsize+1;
  419. }
  420.  
  421. void
  422. usage(cmd)
  423.     char *cmd;
  424. {
  425.     (void)fprintf(stderr,
  426.  "usage: %s [-l length] [-s size] [-n number] [-r resolution] [-d depth]\n", cmd);
  427.     exit(1);
  428. }
  429.