home *** CD-ROM | disk | FTP | other *** search
- /*
- * worm.c
- *
- * Adapted from the Scientific American article 12/87. Original for Sun UNIX.
- * Original Author - Brad Taylor (sun!brad)
- * Adapted to the Amiga by Chuck McManis (sun!cmcmanis)
- * Basically there are five switches they are :
- * -l n Set the length of the worms to 'n' units, this defaults to 32.
- * -s n Set the size of the worm units to n X n, defaults to 1 but try
- * some larger sizes too, their kinda neat.
- * -n n Set the number of worms on the screen, defaults to 16 worms which
- * is fairly slow, 4 is pretty quick. Numbers like 3000 are neat too.
- * -r n Set the screen resolution, 0 = low res (320 X 200), 1 = medium (640 X 200)
- * and 2 = high (640 X 400)
- * -d n Set number of bitplanes, 1-5 are acceptable numbers.
- *
- * Note this uses a random number generator that Leo used in demo.c
- * Copyright (C) 1987 by Charles McManis
- * Freely Redistributable if you leave the above comment and following declaration
- * intact ...
- */
-
- static char copyright[] = "Copyright (C) 1987, Charles McManis, ok to copy.";
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <intuition/intuition.h>
- #include <graphics/gfxbase.h>
- #include <graphics/gfx.h>
- #include <graphics/rastport.h>
- #include <devices/inputevent.h>
- #include <libraries/diskfont.h>
- #include <stdio.h>
- #include <math.h>
- #ifdef LATTICE
- #include <proto/dos.h>
- #include <proto/graphics.h>
- #endif
-
-
- /* Declare the required Intuition pointers */
- struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
- struct DiskfontBase *DiskfontBase;
-
- /* Declare some global tool stuff */
- struct Window *MyWindow;
- struct Menu *MyMenu, *CurrentMenu;
- struct Screen *MyScreen;
- struct TextFont *MyFont;
-
- /* Declare some defines that make the code a bit more readable */
- #define SIGBIT(w) (1L << (w->UserPort->mp_SigBit))
- #define GetIntuiMessage(w) (struct IntuiMessage *)GetMsg(w->UserPort)
- struct TextAttr ta = {"topaz.font",11,0,0};
-
- #define CMSIZE 30 /* Max color map size */
- #define CMFUDGE 2 /* colors needed for borders and background */
- #define SEGMENTS 36 /* Size of sin and cos tables */
- #define MAXCOLOR 15 /* Most intense color */
-
- extern char *malloc();
-
- int wormlength = 32;
- int circsize = 1;
- int nworms = 16;
- int black,white;
- int cmsize;
- int sintab[SEGMENTS];
- int costab[SEGMENTS];
-
-
- /*
- * Initialized data section. These structures are pre-initialized with
- * the values that the program knows ahead of time.
- */
-
- struct NewScreen ns = {
- 0,0,640,400,3, /* (X,Y) (W,H) (bitplanes) */
- 1,0, /* Foreground, Background */
- 0, /* View Modes (defaults to none */
- CUSTOMSCREEN, /* What else is new */
- NULL, /* Font is set up below */
- "Worms, implementation by Chuck McManis V1.0",
- NULL, /* No special Gadgets */
- NULL /* No Custom Bitmap */
- };
-
- struct NewWindow nw = {
- 0,0,640,400, /* (X,Y) (W,H) */
- 7,6, /* Foreground, Background */
- CLOSEWINDOW+REFRESHWINDOW,
- WINDOWCLOSE+SIMPLE_REFRESH+ACTIVATE,
- NULL, /* No special Gadgets */
- NULL, /* Use the default Checkmark */
- "Squiggly Worms, Implementation by Chuck McManis",
- NULL, /* This will be our screen pointer */
- NULL, /* We'll use the Bitmap we get */
- 640,400,640,400, /* No resizing going on */
- CUSTOMSCREEN /* We'll use our own screen thankyou */
- };
-
-
- /*
- * Some declarations for worm,
- */
-
- USHORT colors[32]; /* A place to create the color table */
- int ScreenRes = 1; /* Screen Resolution (0=low 2=hi) */
- ULONG MaxX, MaxY; /* Window inside dimensions */
-
- struct wormstuff {
- int *xcirc;
- int *ycirc;
- int dir;
- int tail;
- int x;
- int y;
- int id;
- };
-
-
- void worm_doit(),drawseg(),goaway(),usage(), color_setup();
- short rnd();
- struct wormstuff *worm_init();
-
- /*
- * Ok, declarations are out of the way, on with the main function
- */
- void main(argc,argv)
-
- int argc;
- char *argv[];
-
- {
- struct IntuiMessage *im; /* Intuimessage pointer */
- struct Window *wp; /* Temporary window pointer */
- ULONG class; /* Message Class holder */
- USHORT code,qual;/* Message Code and qualifiers */
- SHORT msx,msy; /* Mouse Co-ordinates for event */
- int i, /* Your basic counter variable */
- xsize,ysize,
- depth; /* How many bitplanes did you want? */
- struct wormstuff **worm; /* Worm data */
- char *cmd;
-
- cmd = argv[0];
- depth = 3; /* default depth */
- rnd(0);
- if (argc == 0) { /* Started from workbench */
- printf("Worm length : ");
- scanf("%d",&wormlength);
- printf("Number of worms [n] :");
- scanf("%d",&nworms);
- printf("Worm width [n] :");
- scanf("%d",&circsize);
- printf("Screen Resolution [0=Low, 1=Medium, 2=High] :");
- scanf("%d",&ScreenRes);
- printf("Number of bitplanes [1-5 for Low res, 1-4 for medium or high] :");
- scanf("%d",&depth);
- }
- for (i = 1; i < argc; i++) {
- if (i == argc - 1 || argv[i][0] != '-' || argv[i][2] != 0) {
- usage(cmd);
- }
- switch (argv[i][1]) {
- case 'l':
- wormlength = atoi(argv[++i]);
- break;
- case 'n':
- nworms = atoi(argv[++i]);
- break;
- case 's':
- circsize = atoi(argv[++i]);
- break;
- case 'r':
- ScreenRes = atoi(argv[++i]);
- break;
- case 'd':
- depth = atoi(argv[++i]);
- if ((depth < 1) || (depth > 5)) usage(cmd);
- break;
- default:
- usage(cmd);
- }
- }
- if ((ScreenRes > 0) && (depth == 5)) depth = 4;
- cmsize = (1 << depth) - CMFUDGE;
- for (i = 0; i < SEGMENTS; i++) {
- sintab[i] = round(circsize * sin(i * 2 * PI / SEGMENTS));
- costab[i] = round(circsize * cos(i * 2 * PI / SEGMENTS));
- }
- /* Open the intuition library first ... */
- IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
- if (! IntuitionBase) goaway();
-
- /* Now opening the graphics library ... */
- GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
- if (! GfxBase) goaway();
-
- /* Now opening the diskfont library ... */
- DiskfontBase = (struct DiskfontBase *)OpenLibrary("diskfont.library",0);
- if (! DiskfontBase) goaway();
-
- /* This opens a custom screen to the maximum possible size ... */
- ns.Depth = depth;
- ns.Width = GfxBase->NormalDisplayColumns;
- ns.Height = GfxBase->NormalDisplayRows;
- switch (ScreenRes) {
- case 0 :
- ns.Width /= 2;
- ta.ta_YSize = 8;
- ta.ta_Flags |= FPF_ROMFONT;
- ns.Font = &ta;
- break;
- case 1 :
- ns.ViewModes |= HIRES;
- /* In medium res use Topaz 8 */
- ta.ta_YSize = 8;
- ta.ta_Flags |= FPF_ROMFONT;
- ns.Font = &ta;
- break;
- case 2 :
- ns.Height *= 2;
- ns.ViewModes |= HIRES+LACE;
- /* In Interlace mode us Topaz 11 */
- ns.Font = &ta;
- }
-
- /* Now we open the font we want so that it will be resident when the
- * OpenScreen call below needs it.
- */
- MyFont = (struct TextFont *) OpenDiskFont(&ta);
-
- MyScreen = (struct Screen *)OpenScreen(&ns);
-
- if (! MyScreen) goaway();
- color_setup(); /* Initialize the color map */
- /* OK so far, now lets open a full size window ... */
- nw.Screen = MyScreen;
- nw.TopEdge = 1; /* Leave a row to grab the screen drag bar */
- nw.Width = ns.Width;
- nw.Height = ns.Height-1;
- nw.DetailPen = white; /* initialized by color_setup() */
- nw.BlockPen = black;
- MyWindow = (struct Window *)OpenWindow(&nw);
- if (! MyWindow) goaway();
-
- SetFont(MyWindow->RPort,MyFont); /* This should not be required ! */
-
- MaxX = xsize = MyWindow->Width-MyWindow->BorderLeft-MyWindow->BorderRight;
- MaxY = ysize = MyWindow->Height-MyWindow->BorderTop-MyWindow->BorderBottom;
- SetAPen(MyWindow->RPort,black);
- RectFill(MyWindow->RPort, MyWindow->BorderLeft,MyWindow->BorderTop,
- MyWindow->BorderLeft+xsize, MyWindow->BorderTop+ysize);
- worm = (struct wormstuff **)malloc((unsigned)(sizeof(struct wormstuff *) * nworms));
- for (i = 0; i < nworms; i++) {
- worm[i] = worm_init(xsize, ysize, wormlength);
- }
- if (!cmsize) cmsize = 1;
-
- for (;;) {
- for (i = 0; i < nworms; i++) {
- worm_doit((void *)MyWindow->RPort, worm[i], xsize, ysize,
- (((i * cmsize) / nworms) % cmsize));
- }
- /* Note: If we are running continuously we don't Wait(), this lets */
- /* the program continue to update the screen until the user sends */
- /* it some form of request. */
- while ((im = GetIntuiMessage(MyWindow)) != NULL) {
- class = im->Class; /* Extract relavent info */
- code = im->Code;
- qual = im->Qualifier; /* Stuff like shift down etc */
- msx = im->MouseX; /* And the mouse position */
- msy = im->MouseY;
- wp = im->IDCMPWindow; /* Figure out which window sent this message */
- ReplyMsg(im); /* Reply quickly! */
- switch (class) {
- case CLOSEWINDOW : /* Process a close window message. */
- goaway(); /* Exit the program */
- case REFRESHWINDOW :
- BeginRefresh(MyWindow);
- EndRefresh(MyWindow,TRUE);
- break;
- default : /* We choose to ignore unknown message classes */
- break;
- } /* switch statement */
- } /* until no messages are still waiting */
- }
- }
-
- /*
- * Utility routines used by the Worm Program...
- */
-
- /*
- * Function goaway()
- *
- * This function shuts down after we are done. Since this can happen at
- * anytime, it checks the various global variables and those that have
- * been initialized (non-null), it removes/clears etc depending on the
- * variable.
- */
- void goaway()
-
- {
- if (MyWindow) CloseWindow(MyWindow);
- if (MyScreen) CloseScreen(MyScreen);
- if (GfxBase) CloseLibrary(GfxBase);
- if (MyFont) CloseFont(MyFont);
- if (DiskfontBase) CloseLibrary(DiskfontBase);
- if (IntuitionBase) CloseLibrary(IntuitionBase);
- exit(0); /* This cleans up FILE pointers and malloc'd memory */
- }
-
- struct wormstuff *
- worm_init(xsize, ysize, wormlength)
- int xsize;
- int ysize;
- int wormlength;
- {
- static int thisworm = 0;
- int i;
- struct wormstuff *ws;
-
- ws = (struct wormstuff *)malloc((unsigned)sizeof(struct wormstuff));
- ws->xcirc = (int *)malloc((unsigned)(wormlength * sizeof(int)));
- ws->ycirc = (int *)malloc((unsigned)(wormlength * sizeof(int)));
- for (i = 0; i < wormlength; i++) {
- ws->xcirc[i] = xsize / 2;
- ws->ycirc[i] = ysize / 2;
- }
- ws->dir = rnd(SEGMENTS);
- ws->tail = 0;
- ws->x = xsize / 2;
- ws->y = ysize / 2;
- ws->id = thisworm;
- thisworm = (thisworm + 1) % 14;
- return (ws);
- }
-
- void
- worm_doit(h, priv, xsize, ysize, color)
- void *h;
- void *priv;
- int xsize;
- int ysize;
- int color;
- {
- int x;
- int y;
- struct wormstuff *ws = (struct wormstuff *)priv;
-
- ws->tail = (ws->tail + 1) % wormlength;
- x = ws->xcirc[ws->tail];
- y = ws->ycirc[ws->tail];
- drawseg(h, x, y, black);
- if ((rnd(32765)&(1<<ws->id)) != 0) {
- ws->dir = (ws->dir + 1) % SEGMENTS;
- } else {
- ws->dir = (ws->dir + SEGMENTS - 1) % SEGMENTS;
- }
- x = (ws->x + costab[ws->dir] + xsize) % xsize;
- y = (ws->y + sintab[ws->dir] + ysize) % ysize;
- ws->xcirc[ws->tail] = x;
- ws->ycirc[ws->tail] = y;
- /* Note when using one bitplane worm_doit gets called with color == 0 */
- drawseg(h, x, y, (color != black) ? color : 1);
- ws->x = x;
- ws->y = y;
- }
-
-
-
- round(x)
- float x;
- {
- if (x >= 0) return ((int)(x + .5));
- return ((int)(x - .5));
- }
-
- /* Note that drawseg does it's own clipping... */
- void
- drawseg(priv, x, y, color)
- void *priv;
- int x;
- int y;
- int color;
- {
- struct RastPort *gfx = (struct RastPort *)priv;
- ULONG X,Y;
-
- X = ((unsigned) x % (MaxX-circsize)) + MyWindow->BorderLeft;
- Y = ((unsigned) y % (MaxY-circsize)) + MyWindow->BorderTop;
- SetAPen(gfx,color);
- if (circsize == 1) WritePixel(gfx,X,Y);
- else RectFill(gfx,X,Y,X+circsize,Y+circsize);
- }
-
-
- /* Sets up some reasonable colors ... note CMSIZE is max colors and
- * cmsize is the actual number of colors
- */
-
- void
- color_setup()
-
- {
- int i;
-
- for (i = 0; i < cmsize; i++) {
- colors[i] = rnd(4096);
- }
- colors[cmsize] = 0;
- colors[cmsize+1] = 4095;
- LoadRGB4(&(MyScreen->ViewPort),colors,cmsize+CMFUDGE); /* Load in our colors */
- black = cmsize;
- white = cmsize+1;
- }
-
- void
- usage(cmd)
- char *cmd;
- {
- (void)fprintf(stderr,
- "usage: %s [-l length] [-s size] [-n number] [-r resolution] [-d depth]\n", cmd);
- exit(1);
- }
-