[comp.sources.games] v11i070: swarm - display a swarm of lines

billr@saab.CNA.TEK.COM (Bill Randle) (11/20/90)

Submitted-by: "Werner P. Keilholz" <keilholz@rrze2.rrze.uni-erlangen.de>
Posting-number: Volume 11, Issue 70
Archive-name: swarm/Part01
Environment: MS-DOS, Turbo C

	[This is a PC port of a X-windows game of the same (or similar)
	 name. The author comments that it is written in Turbo C++,
	 but it doesn't use any C++'isms and by commenting out a
	 few lines should be compilable with Turbo C.  -br]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  README swarm.c swarm.h
# Wrapped by billr@saab on Mon Nov 19 13:13:39 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1010 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X Swarm
X =====
X
X Purpose:     Display a swarm of lines.
X
X Features:    uses only integer math
X              has no redeeming social value
X
X Comments:    This code is derived from a program by Jeff Butterworth,
X              written for the UNIX XWINDOW system.
X              Like it's  predecessor, this PC version (written in
X              TURBO C[++]) has still "no redeeming social value"
X              and is really good for nothing except, maybe, practicing
X              C (in my case). But it looks nice and maybe someone
X              turnes it into some kind of game or something ...
X              I didn't spent too much time with this, so there might
X              still be some 'leftovers' from the UNIX version and,
X              of course, bugs.
X
X              Any comments, enhances, or fixes are welcome!
X
X Created:     by Jeff Butterworth on 7/11/90
X
X Updated:     by Jeff Butterworth on 8/1/90
X PC-Version:  by Werner Keilholz on 10/19/90
X                 (KEILHOLZ@CNVE.RRZE.UNI-ERLANGEN.DE)
END_OF_FILE
if test 1010 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'swarm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'swarm.c'\"
else
echo shar: Extracting \"'swarm.c'\" \(14177 characters\)
sed "s/^X//" >'swarm.c' <<'END_OF_FILE'
X/*
X** Swarm
X** =====
X**
X** Purpose:     Display a swarm of lines.
X**
X** Features:    uses only integer math
X**              has no redeeming social value
X**
X** Comments:    This code is derived from a program by Jeff Butterworth,
X**              written for the UNIX XWINDOW system.
X**              Like it's  predecessor, this PC version (written in
X**              TURBO C[++]) has still "no redeeming social value"
X**              and is really good for nothing except, maybe, practicing
X**              C (in my case). But it looks nice and maybe someone
X**              turnes it into some kind of game or something ...
X**              I didn't spent too much time with this, so there might
X**              still be some 'leftovers' from the UNIX version and,
X**              of course, bugs.
X**
X**              Any comments, enhances, or fixes are welcome!
X**
X** Created:     by Jeff Butterworth on 7/11/90
X**
X** Updated:     by Jeff Butterworth on 8/1/90
X** PC-Version:  by Werner Keilholz on 10/19/90
X**                 (KEILHOLZ@CNVE.RRZE.UNI-ERLANGEN.DE)
X*/
X
X/* Standard Includes */
X#include <stdio.h>
X#include <stdlib.h>
X
X/* Graphics Includes (TURBO C++) */
X#include <graphics.h>
X
X/* Includes for this project. */
X#include <swarm.h>
X
X/* This is needed for the kbhit function in TURBO C++ */
X#include <conio.h>
X
X
X/* Main()
X** process command line parameters, setup X stuff
X*/
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X
X{
X    /* variables used by the graphic */
X    int errorcode;
X    int graphdriver = DETECT;
X    int graphmode;
X
X
X    /* These variables are used to analyze the command line parameters. */
X    char        option[80];
X    extern int  optind;
X    extern char *optarg;
X    int i;
X
X    /*
X    printf("\n%d Arguments:\n\n",argc);
X    for (i=0; i<= argc; i++)
X    printf("Argument Nr. %d: = %s\n",i,argv[i]);
X    */
X
X    /* Check the command line. */
X
X    i=1;
X
X    while (i < argc)
X    {
X        strcpy(option,argv[i]);
X
X        i++;
X
X        switch (option[0])
X        {
X            case 'v':
X                verbose = TRUE;
X                break;
X            case 'r':
X                break;
X            case 'x':
X                xor = TRUE;
X                break;
X            case 'g':
X                break;
X            case 'b':
X                sscanf(option+1,"%d",&bees);
X                break;
X            case 'a':
X                sscanf(option+1,"%d",&bee_acc);
X                break;
X            case 's':
X                sscanf(option+1,"%d",&bee_vel);
X                break;
X            case 'A':
X                sscanf(option+1,"%d",&wasp_acc);
X                break;
X            case 'S':
X                sscanf(option+1,"%d",&wasp_vel);
X                break;
X            case 'd':
X                {
X                sscanf(option+1,"%d",&delay);
X                }
X                break;
X            case 'B':
X                sscanf(option+1,"%d",&border);
X                break;
X            case 'w':
X                sscanf(option+1,"%d",&wasp_color);
X                break;
X            case 'c':
X                sscanf(option+1,"%d",&bee_color);
X                break;
X            case 'C':
X                sscanf(option+1,"%d",&bg_color);
X                break;
X            case 'h':
X            case 'q':
X            case '?':
X                Usage(*argv);
X                break;
X            default:
X            {
X                printf("\nOption %s unknown !\n", argv[i-1]);
X
X                HandleError("The command line parameters were incorrect.",
X                    FATAL);
X                break;
X            }
X        }
X    }
X
X    /* Display the arguments. */
X    if (verbose)
X    {
X        printf("\nHere are the current settings...\n");
X        if (xor)
X            printf("Trails are not erased.\n");
X        else
X            printf("Trails are erased.\n");
X        printf("There are %d bees.\n", bees);
X        printf("Bee acceleration is %d pixels per frame.\n",bee_acc);
X        printf("Bee speed limit is %d pixels per frame.\n", bee_vel);
X        printf("Wasp acceleration is %d pixels per frame per frame.\n",
X            wasp_acc);
X        printf("Wasp speed limit is %d pixels per frame.\n", wasp_vel);
X        printf("The delay is %d millikeilholz.\n",
X            delay);
X        printf("The wasp can't go within %d pixels of the window edge.\n",
X            border);
X        if (!(wasp_color==0))
X          printf("The wasp color is \"%d\"\n", wasp_color);
X        else
X          printf("The wasp color is (default)\n");
X        if (!(bee_color==0))
X          printf("The bee color is \"%d\"\n", bee_color);
X        else
X          printf("The bee color is (default)\n");
X        if (!(bg_color==0))
X          printf("The background color is \"%d\"\n", bg_color);
X        else
X          printf("The background color is (default)\n", bg_color);
X
X        printf("\nHit a key to continue ...\n");
X        getch();
X
X    }
X
X
X    winW = winH = winX = winY = 0;
X
X    /* Open the display. */
X    initgraph(&graphdriver, &graphmode,"\\tc\\bgi");
X    errorcode = graphresult();
X
X    if (errorcode != grOk)
X    {
X        HandleError("Cannot open display.\n");
X        exit(-1);
X    }
X
X    /* Set the colors. */
X    if (!(bg_color == 0)) setbkcolor(bg_color);
X
X    /* Set up window parameters, create and map window if necessary */
X        winW = getmaxx();
X        winH = getmaxy();
X        winX = 0;
X        winY = 0;
X
X
X    /* Animate the swarm. */
X    Animate();
X
X    closegraph();
X
X    printf("\n SWARM by Jeff Butterworth and Werner Keilholz\n");
X    printf("\n type SWARM h  for options");
X
Xreturn(0);
X}
X
X
X
Xint Animate()
X{
X    register int        b;              /* bee index */
X    XSegment            *segs;          /* bee lines */
X    XSegment            *old_segs;      /* old bee lines */
X    short               *x, *y;         /* bee positions x[time][bee#] */
X    short               *xv, *yv;       /* bee velocities xv[bee#] */
X    short               wx[3], wy[3];
X    short               wxv, wyv;
X/*    XEvent            xev;  */
X    short               dx,dy,distance;
X    int                 init = TRUE;
X    int FGcolor;
X    int BGcolor;
X
X
X    /* Get the random number generator ready.
X    srandom((int) time(0) % 231); */
X
X    /* Allocate memory. */
X    segs = (XSegment *) malloc(sizeof(XSegment) * bees);
X    old_segs = (XSegment *) malloc(sizeof(XSegment) * bees);
X    x = (short *) malloc(sizeof(short) * bees * times);
X    y = (short *) malloc(sizeof(short) * bees * times);
X    xv = (short *) malloc(sizeof(short) * bees);
X    yv = (short *) malloc(sizeof(short) * bees);
X
X    /* Initialize point positions, velocities, etc. */
X
X    /* wasp */
X    wx[0] = BORDER + random(231) % (winW - 2*BORDER);
X    wy[0] = BORDER + random(231) % (winH - 2*BORDER);
X    wx[1] = wx[0];
X    wy[1] = wy[0];
X    wxv = 0;
X    wyv = 0;
X
X    /* bees */
X    for (b = 0 ; b < bees ; b++)
X    {
X        X(0,b) = random(231) % winW;
X        X(1,b) = X(0,b);
X        Y(0,b) = random(231) % winH;
X        Y(1,b) = Y(0,b);
X        xv[b] = RAND(7);
X        yv[b] = RAND(7);
X    }
X
X    /* loop until key is pressed */
X    while (!kbhit())
X    {
X        /* <=- Wasp -=> */
X        /* Age the arrays. */
X        wx[2] = wx[1];
X        wx[1] = wx[0];
X        wy[2] = wy[1];
X        wy[1] = wy[0];
X        /* Accelerate */
X        wxv += RAND(wasp_acc);
X        wyv += RAND(wasp_acc);
X
X        /* Speed Limit Checks */
X        if (wxv > wasp_vel) wxv = wasp_vel;
X        if (wxv < -wasp_vel) wxv = -wasp_vel;
X        if (wyv > wasp_vel) wyv = wasp_vel;
X        if (wyv < -wasp_vel) wyv = -wasp_vel;
X
X        /* Move */
X        wx[0] = wx[1] + wxv;
X        wy[0] = wy[1] + wyv;
X
X        /* Bounce Checks */
X        if ((wx[0] < border) || (wx[0] > winW-border-1))
X        {
X            wxv = -wxv;
X            wx[0] += wxv;
X        }
X        if ((wy[0] < border) || (wy[0] > winH-border-1))
X        {
X            wyv = -wyv;
X            wy[0] += wyv;
X        }
X
X        /* Don't let things settle down. */
X        xv[random(231) % bees] += RAND(3);
X        yv[random(231) % bees] += RAND(3);
X
X        /* <=- Bees -=> */
X        for (b = 0 ; b < bees ; b++)
X        {
X            /* Age the arrays. */
X            X(2,b) = X(1,b);
X            X(1,b) = X(0,b);
X            Y(2,b) = Y(1,b);
X            Y(1,b) = Y(0,b);
X
X            /* Accelerate */
X            dx = wx[1] - X(1,b);
X            dy = wy[1] - Y(1,b);
X            distance = abs(dx)+abs(dy); /* approximation */
X            if (distance == 0) distance = 1;
X            xv[b] += (dx*bee_acc)/distance;
X            yv[b] += (dy*bee_acc)/distance;
X
X            /* Speed Limit Checks */
X            if (xv[b] > bee_vel) xv[b] = bee_vel;
X            if (xv[b] < -bee_vel) xv[b] = -bee_vel;
X            if (yv[b] > bee_vel) yv[b] = bee_vel;
X            if (yv[b] < -bee_vel) yv[b] = -bee_vel;
X
X            /* Move */
X            X(0,b) = X(1,b) + xv[b];
X            Y(0,b) = Y(1,b) + yv[b];
X
X            /* Fill the segment lists. */
X            segs[b].x1 = X(0,b);
X            segs[b].y1 = Y(0,b);
X            segs[b].x2 = X(1,b);
X            segs[b].y2 = Y(1,b);
X            old_segs[b].x1 = X(1,b);
X            old_segs[b].y1 = Y(1,b);
X            old_segs[b].x2 = X(2,b);
X            old_segs[b].y2 = Y(2,b);
X        }
X
X        /* Erase previous, draw current, sync for smoothness. */
X
X        /* Wasp */
X        if (xor) /* xor doesn't make sense on a PC (no root window,...)
X                    therfore I slightly changed the meaning of this
X                    switch :-) */
X        {
X            if (init == FALSE)
X            {
X              if ((goodCoord(wx[1], wy[1])) && (goodCoord(wx[2],wy[2])))
X              {
X                if (!(wasp_color == 0))
X                  setcolor(wasp_color);
X                line(wx[1], wy[1], wx[2], wy[2]);
X              }
X            }
X              if ((goodCoord(wx[0], wy[0])) && (goodCoord(wx[1],wy[1])))
X              {
X                if (!(wasp_color == 0))
X                  setcolor(wasp_color);
X                line(wx[0], wy[0], wx[1], wy[1]);
X              }
X        }
X        else
X        {
X            if (init == FALSE)
X                FGcolor=getcolor();
X                BGcolor=getbkcolor();
X                setcolor(BGcolor);                /*       */
X              if ((goodCoord(wx[1], wy[1])) && (goodCoord(wx[2],wy[2])))
X                line(wx[1], wy[1], wx[2], wy[2]); /* erase */
X                setcolor(FGcolor);                /*       */
X              if ((goodCoord(wx[0], wy[0])) && (goodCoord(wx[1],wy[1])))
X              {
X                if (!(wasp_color == 0))
X                  setcolor(wasp_color);
X                line(wx[0], wy[0], wx[1], wy[1]);
X              }
X        }
X
X        /* Bees */
X        if (xor)
X        {
X            if (init == FALSE)
X               {
X                setcolor(BGcolor);                /*       */
X                DrawSegments(old_segs, bees);     /* XOR   */
X                setcolor(FGcolor);                /*       */
X               }
X            else
X                init = FALSE;
X                if (!(bee_color == 0))
X                  setcolor(bee_color);
X                DrawSegments(segs, bees);
X        }
X        else
X        {
X            if (init == FALSE)
X            {
X                setcolor(BGcolor);                /*       */
X                 DrawSegments(old_segs, bees);    /* erase */
X                 setcolor(FGcolor);                /*       */
X            }
X
X            else
X                init = FALSE;
X            DrawSegments(segs,bees);
X        }
X
X
X        /* Clean up and shut down.
X        if (stop)
X        {
X            if (xor)
X            {
X                DrawSegments(segs, bees);
X                DrawLine(wx[0], wy[0], wx[1], wy[1]);
X            }
X            else
X                XFillRectangle(display.dpy, display.win, display.erase_gc,
X                    0,0, winW, winH);
X            XSync(display.dpy, 0);
X            exit(0);
X        } */
X
X        /* Delay so we don't use all of the cpu time. */
X        if (delay != 0) nap(delay);
X    }
X  return(0);
X}
X
X
X/* nap
X**
X** put the process to sleep for a while
X*/
X
Xvoid nap(usec)
Xint usec;
X
X{
Xint i;
X
Xfor (i=1; i<usec; i++);
X
X}
X
X
Xvoid Usage(program)
Xchar *program;
X{
X
X    printf("swarm [options]  where options are listed below\n", program);
X    printf(" ! no space between option and value; e.g.: swarm b30\n");
X    printf("d delay     delay between screen updates in millikeilholz\n");
X    printf("            ( 0 <= d <= 32000 )\n");
X    printf("x           do not erase bees's and wasp's trails\n");
X    printf("b bees      number of bees\n");
X    printf("a bee_acc   bee acceleration in pixels per frame per frame\n");
X    printf("s bee_vel   bee speed limit in pixels per frame\n");
X    printf("A wasp_acc  wasp max acceleration in pixels per frame per frame\n");
X    printf("S wasp_vel  wasp speed limit in pixels per frame\n");
X    printf("B width     border width that wasp can't cross\n");
X    printf("            ( 0 <= d <= 65 )\n");
X    printf("w wasp_clr  wasp color\n");
X    printf("c bee_clr   bee color\n");
X    printf("C bg_color  background color\n");
X    printf("v           verbose\n");
X    printf("h|q|?               display this message\n");
X    printf("\nPress any key to stop the insanity.\n");
X    exit(0);
X}
X
X
Xvoid HandleError(description, degree)
Xchar    *description;
Xint     degree;
X{
X    fprintf(stderr, "An error has occurred.  The description is below...\n");
X    fprintf(stderr, "%s\n", description);
X
X    if (degree == FATAL)
X    {
X        fprintf(stderr, "Program aborting...\n");
X        exit(-1);
X    }
X}
X
X
Xvoid DrawSegments(XSegment *segments, int bees)
X
X{
X  int i;
X
X  for (i=1; i<= bees; i++)
X  {
X    if ((goodCoord(segments[i].x1, segments[i].y1) ) &&
X        (goodCoord(segments[i].x2, segments[i].y2) )     )
X        line(segments[i].x1, segments[i].y1, segments[i].x2,segments[i].y2);
X  }
X
X}
X
Xint goodCoord(int x, int y)    /* boolean */
X
X/* In TURBO C++ we need to check the boundaries ...
X   drawing lines outside the viewport would mess
X   up the display                                  */
X
X{
Xif ( (x >0) && (x <= getmaxx()) &
X     (y >0) && (y <= getmaxy())    )
X   return(true);
Xelse
X   return(false);
X
X}
X
X
END_OF_FILE
if test 14177 -ne `wc -c <'swarm.c'`; then
    echo shar: \"'swarm.c'\" unpacked with wrong size!
fi
# end of 'swarm.c'
fi
if test -f 'swarm.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'swarm.h'\"
else
echo shar: Extracting \"'swarm.h'\" \(2704 characters\)
sed "s/^X//" >'swarm.h' <<'END_OF_FILE'
X/* Constants */
X#define TRUE 1
X#define FALSE 0
X#define STD_STR 100
X#define BEES    20      /* number of bees */
X#define TIMES   3       /* number of time positions recorded */
X#define BEEACC  3       /* acceleration of bees */
X#define WASPACC 5       /* maximum acceleration of wasp */
X#define BEEVEL  11      /* maximum bee velocity */
X#define WASPVEL 12      /* maximum wasp velocity */
X#define DELAY   0       /* delay between updates */
X#define WINWIDTH 512    /* default window width */
X#define WINHEIGHT 512   /* default window height */
X#define BORDER  50      /* wasp won't go closer than this to the edges */
X#define NULL 0          /* not predefined ??? &&& */
X
X#define MaxBees 200
X
X/* Error Codes */
X#define FATAL   -1
X#define WARNING -2
X
X/* Macros */
X#define X(t,b)  (x[t*bees + b])         /* addressing into dynamic array */
X#define Y(t,b)  (y[t*bees + b])         /* addressing into dynamic array */
X#define RAND(v) ((random(v) % v) - (v/2))  /*random number around 0 */
X
X/* Type Definitions */
X
Xtypedef int Window;   /* Nonsense &&& */
Xtypedef int Display;  /* Nonsense &&& */
Xtypedef int GC;       /* Nonsense &&& */
Xtypedef int Atom;     /* Nonsense &&& */
Xtypedef Colormap;     /* Nonsense &&& */
X
X
X
Xtypedef struct _disp
X{
X        Window  win;
X        Display *dpy;
X        char    *dname;
X        long    wasp, bee, bg; /* colors */
X        GC      wasp_gc;
X        GC      bee_gc;
X        GC      erase_gc;
X        GC      wasp_xor_gc;
X        GC      bee_xor_gc;
X        Atom    kill_atom, protocol_atom;
X        Colormap cmap;
X} disp;
X
Xtypedef struct
X{
X  short x1;
X  short x2;
X  short y1;
X  short y2;
X} XSegment;
X
Xenum boolean {false, true};
X
X/* Function Prototypes */
Xvoid    nap();
Xvoid    Usage();
Xvoid    HandleError();
Xlong    GetColor();
Xvoid    DrawSegments(XSegment *segments, int bees);
Xint     goodCoord(int x, int y); /* int = boolean ? */
X
X/* Global Variables */
X
X/* X related */
Xint             winX, winY;
Xunsigned int    winW, winH;
X
X/* animation related */
Xint     times = TIMES;          /* number of time steps recorded  */
Xint     bees = BEES;            /* number of bees */
Xint     wasp_vel = WASPVEL;     /* maximum wasp speed */
Xint     bee_vel = BEEVEL;       /* maximum bee speed */
Xint     wasp_acc = WASPACC;     /* maximum wasp acceleration */
Xint     bee_acc = BEEACC;       /* bee acceleration */
Xint     delay = DELAY;          /* delay between updates, in microseconds */
Xint     border = BORDER;        /* border limiting wasp travel */
Xint     wasp_color = 0;
Xint     bee_color = 0;
Xint     bg_color = 0;
Xchar    stop = FALSE;
Xint     xor = FALSE;            /* use GXxor if TRUE */
Xint     verbose = FALSE;        /* display settings if TRUE */
X
END_OF_FILE
if test 2704 -ne `wc -c <'swarm.h'`; then
    echo shar: \"'swarm.h'\" unpacked with wrong size!
fi
# end of 'swarm.h'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0