[net.sources] SunCrabs

jim@artecon.UUCP (Jim Wang) (01/03/86)

echo x - README
sed 's/^X//' >README <<'*-*-END-of-README-*-*'
X	In September, Scientific American carried an article in the
XMathematical Games section (or whatever they're calling it now) describing
X'crabs', cutesy little critters that scamper all over your graphics screen
Xeating chunks of your favorite bitmap and replacing them with their favorite
Xpattern.  And they do so with no regard for window or process boundaries,
Xmuch to the window manager's consternation!  The version described in SA
Xran on Teletype Blit terminals at Bell Labs.
X	Then, Doug Gywn of BRL (gwyn@brl-tgr.ARPA) posted a version of 'crabs'
Xfor the Blit terminal.  Not having a Blit but a Sun, I proceeded to modify
XDoug's original program using Sun pixrect commands to violate window
Xboundaries.  Just to get it working didn't take too much effort, but
Xevolution took its course and now most of the routines have changed
X(sorry, Doug) although they retain their original names.  However,
XDoug's excellent collision avoidance system (air traffic controllers
Xshould take note) is untouched.
X	The evolution means that this implementation doesn't follow
Xprecisely the description in SA.   Among the differences:
X
X	- There are six types of crabs (user selectable, of course)
X	  all of which eat in the same manner, but create different
X	  types of backgrounds.  If you start up several different
X	  types of crabs, they'll eventually cover the whole screen
X	  and start battling each other for territory.  Fascinating
X	  to watch if you have lots of time.
X
X	- Crabs can run in invisible mode.  Great for playing nasty
X	  tricks on unsuspecting console users.  Looks like bitmap
X	  rot.
X
X	- Crabs accelerate (get hungry and desparate) for each step
X	  they take in background pattern.  They're much more
X	  effective this way on sparse screens.
X	
X	- The crab image itself is different than the one in SA.
X
X	- As far as the crabs are concerned, the screen wraps
X	  around both vertically and horizontally.
X
X	Sun crabs run on Sun 2 & 3's, Release 2.x and 3.0 alpha,
Xon Models 50, 120, and 160.  Compile it with:
X
X	cc -O -o crabs crabs.c -lpixrect -DNOCOLLIDE
X
X	Coming next: (or rather, I'm hoping someone will write it)
XSunAnts, industrious insects who search for non-blank pieces of your
Xscreen, pick them up, and neatly stack them in a corner.
X
XJim Wang
X(seismo!jim, jim@seismo)
X
X
X===============
*-*-END-of-README-*-*
echo x - crabs.6
sed 's/^X//' >crabs.6 <<'*-*-END-of-crabs.6-*-*'
X.TH CRABS 6 "15 October 1985"
X.SH NAME
Xcrabs \- digital creatures which feed on screen images
X.SH SYNOPSIS
X\f3crabs\fP [\f3-g\fP\f2n\fP] [\f3-i\fP] [\f3-p\fP\f2sec\fP]
X.br
X.SH DESCRIPTION
X.LP
X\f2crabs\fP is a rather loose implementation of the ``crabs''
Xdescribed in the September 1985 issue of Scientific American.
XBasically, crabs are little digital creatures which scuttle around
Xon the Sun screen, eating pieces of the bitmap and replacing them
Xwith a pattern of their own choosing.
X.PP
XCrabs travel fast in areas of their own pattern; when they find
Xan alien pattern, they eat it, replace it with their own pattern,
Xthen wander off in a different direction in search of more food.
X.PP
XThere are different types of crabs, distinguished only by the
Xpatterns they create after digesting bits.
X.SH OPTIONS
X.LP
XThere are only three options:
X.TP
X\f3-g\fP\f2n\fP
XSelect the type of background the crabs will create: 0=white,
X1=Blit grey, 2=Suntools grey, 3=inverse Suntools grey, 4=vertical
Xstripes, and 5=black.
XWhite is useful for consoles that are not being used for graphics;
Xthe crabs will wander among the letters, eating them.
XSuntools grey is useful when Suntools is running.
XThe default is Suntools grey.
X.TP
X\f3-i\fP
XMake the crabs invisible; the only indication that they are running
Xis the deterioration of the screen image.
XThe default is for visible crabs.
X.TP
X\f3-p\fP\f2sec\fP
XSpecify the sleep interval between crab motions, in seconds.
XThe default time is 0.5 second; this is also the minimum, since
Xotherwise \f2crabs\fP can be a CPU hog.
X.SH "NOTES"
X.LP
X\f2crabs\fP runs at low priority to be nice to other users.
X.LP
X\f2crabs\fP may act differently on a Sun 160 screen because of the
Xdiscrepancy in bitmap depths.
X.SH AUTHORS
X.LP
XDoug Gywn (gwyn@brl-tgr.ARPA) Blit version.
X.br
XJim Wang (jim@seismo) Sun version.
*-*-END-of-crabs.6-*-*
echo x - crabs.c
sed 's/^X//' >crabs.c <<'*-*-END-of-crabs.c-*-*'
X#ifndef	lint
Xstatic char RCSid[] = "$Header: crabs.c,v 1.6 85/12/05 09:45:34 jim Exp $";
X#endif
X
X/*
X * $Log:	crabs.c,v $
X * Revision 1.6  85/12/05  09:45:34  jim
X * Minor cleanup.
X * 
X * Revision 1.5  85/10/01  09:27:15  jim
X * 1)	Added argument range and sensibility checking.
X * 2)	Comments cleaned up a little.
X * 3)	Changed -p option to accept floating point seconds instead of usec.
X * 
X * Revision 1.4  85/09/30  16:56:12  jim
X * Fixed XOR images and positioning using up to eight relative positions
X * 	with respect to background.
X * NOCOLLIDE option seems to work.
X * 
X * Revision 1.3  85/09/26  13:17:32  jim
X * 1)	Collision avoidance reinstated.
X * 2)	Now partially works properly with run time xor'ing.
X * 
X * Revision 1.2  85/09/26  11:32:02  jim
X * Changes from original:
X * 1)	Ability to specify different backgrounds.
X * 2)	Changed rand() to random() with seeding based on time.
X * 3)	Added crab acceleration factor for hungry crabs.
X * 4)	Added xor'ing of crabs with bg at run time instead of at compile time.
X * 5)	Collision avoidance commented out; to be reinstated.
X * 6)	Added -p flag for sleep interval (usec) and -g flag for background.
X * 7)	Wraparound screen.
X * 
X * Revision 1.1  85/09/26  11:31:16  jim
X * Initial revision
X * 
X * 
X */
X
X/* for xc:
X% cc -O -o crabs crabs.c -lpixrect -DNOCOLLIDE
X%d cc -g -o crabs crabs.c -lpixrect -DNOCOLLIDE
X%l lint -chb -DNOCOLLIDE crabs.c > lout
X*/
X
X/*
X	crabs -- see September 1985 Scientific American pages 18..23
X*/
X
X#ifndef lint
X			/* for "what" utility */
Xstatic char	SCCS_ID[] = "@(#)crabs.c	1.1 85/09/03";
X#endif
X
X#include <stdio.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X#include <pixrect/pixrect_hs.h>
X#include <sunwindow/rect.h>		/* for the rect structure */
X
X#define	ABS(x)		((x > 0) ? (x) : (0 - x))
Xtypedef int		bool;		/* Boolean data type */
X
X#define	NCRABS		8		/* total number of crabs (1..32) */
X#define	CWIDTH		8		/* crab size */
X#define	CHEIGHT		8
X
X#define	PIX_XOR		(PIX_SRC^PIX_DST)
X#define	MAXVEL		8		/* bound absolute velocity component */
X#define	MAX_SEARCH	8		/* no. of steps before new direction */
X#define	PERIOD		0.50		/* default sleep time (sec) */
X#define	MILLION		1000000.0	/* the number of usec in a sec */
X
Xstatic bool	visible;		/* true if crabs are to be shown */
X
Xtypedef	struct {			/* struct to describe a crab location */
X	int	x, y;
X	} Point;
X
X	/* The following must be at least 16 bits wide */
Xstatic short	white_image[] =			/* white texture */
X{	0x0000,					/* 1 row */
X};
X
Xstatic short	blit_grey_image[] =		/* grey as for Blit */
X{	0x4444, 0x1111,				/* 2 rows */
X};
X
Xstatic short	root_grey_image[] =		/* Suntools root grey */
X{	0x8888, 0x8888, 0x2222, 0x2222,		/* 4 rows */
X};
X
Xstatic short	inv_grey_image[] =		/* inverse root grey */
X{	0x7777, 0x7777, 0xdddd, 0xdddd,		/* 4 rows */
X};
X
Xstatic short	stripe_image[] =		/* vertical stripes */
X{	0x8888,					/* 1 row */
X};
X
Xstatic short	black_image[] =			/* solid black */
X{	0xffff,					/* 1 row */
X};
X
Xmpr_static(white, 16, 1, 1, white_image);
Xmpr_static(blit, 16, 2, 1, blit_grey_image);
Xmpr_static(root_grey, 16, 4, 1, root_grey_image);
Xmpr_static(inv_grey, 16, 4, 1, inv_grey_image);
Xmpr_static(stripe, 16, 1, 1, stripe_image);
Xmpr_static(black, 16, 1, 1, black_image);
X
Xstatic	struct	pixrect	*backgrounds[] =
X{	&white, &blit, &root_grey,
X	&inv_grey, &stripe, &black
X};
X
Xstatic	struct	pixrect	*grey;		/* the one that is finally chosen */
X
Xstatic struct
X{	Point	ulc;			/* upr left corner screen coordinates */
X	Point	vel;			/* velocity (pixels/cycle) */
X	int	search_count;		/* count of hungry steps for new dir */
X} crab[NCRABS];				/* keeps track of crabs' state */
X
Xstatic	struct	pixrect *pr;		/* the root pixrect */
X
X	/* Crab images XORed with grey texture at various offsets: */
X
X	/*
X	** We need to define eight crab images in each of four orientations
X	** relative to the background pattern.  This makes for 32
X	** total images to create (eight orientations x four positions).
X	** Create at init time rather than as static as original did,
X	** since the type of background won't be known til then.
X	** Some patterns really only require four orientations.
X	*/
X
X	/*
X	** The bitmaps for the four orientations, defined as
X	** 16 bits wide.  Only the left side is filled since the crabs
X	** are only 8 bits wide, but mpr_static requires shorts, so
X	** the right sides are all 0.
X	*/
X
Xstatic short	up_data[] = 		/* facing up */
X{		0x4200, 0xa500, 0xa500, 0x4200, 0x3c00, 0x7e00, 0xff00, 0x7e00,
X};
X
Xstatic short	down_data[] =		/* facing down */
X{		0x7e00, 0xff00, 0x7e00, 0x3c00, 0x4200, 0xa500, 0xa500, 0x4200,
X};
X
Xstatic short	right_data[] = 		/* facing right */
X{		0x2600, 0x7900, 0xf600, 0xf000, 0xf000, 0xf600, 0x7900, 0x2600,
X};
X
Xstatic short	left_data[] = 		/* facing left */
X{		0x6200, 0x9700, 0x6f00, 0x0f00, 0x0f00, 0x6f00, 0x9700, 0x6200,
X};
X
Xstatic struct	pixrect	*upmap[4][2];		/* facing up */
Xstatic struct	pixrect	*downmap[4][2];		/* facing down */
Xstatic struct	pixrect	*rightmap[4][2];	/* facing right */
Xstatic struct	pixrect	*leftmap[4][2];		/* facing left */
X
X	/*
X	** Crab "vicinities" are recorded in the following
X	** global map; see Collide() and Draw() for details:
X	*/
X
X#define	XMAX	1151			/* Sun screen size */
X#define	YMAX	899
Xstatic int	vicinity[(XMAX + 31) / 32 + 2][(YMAX + 31) / 32 + 2];
X					/* includes margins all around */
X
Xstatic void	Cycle(), DrawCrab(), HideCrabs(), Init(), ModVel(), NewVel();
Xstatic int	Collide(), RandInt();
X
Xstatic	struct	pixrect	*mem_pr;	/* static memory pixrect for backgr */
Xstatic	short		mem_im[32];	/* pixrect image */
X
Xstatic	int	sec, usec;
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	void	nap();
X
X	Init(argc, argv);		/* set up initial grey crab layer */
X	for (;;)			/* no way out! */
X	{	nap(sec, usec);		/* relinquish the processor */
X		Cycle();		/* move the crabs */
X	}
X	/*NOTREACHED*/
X}
X
X
X/* ARGSUSED */
Xstatic void
XInit(argc, argv)			/* set up initial crab layer */
Xint	argc;
Xchar	*argv[];
X{
X	register	int	i, j, max_bg;
X	double			nap_int;	/* sleep interval, sec */
X	struct	timeval		tv;		/* for random() seed */
X
X	char			*myname;
X	struct	pixrect		*up_image, *down_image;
X	struct	pixrect		*right_image, *left_image;
X
X	struct	pixrect *pr_open();
X	double		atof();
X
X	visible = 1;		/* defaults */
X	nap_int = PERIOD;
X	grey = &root_grey;
X
X	max_bg = sizeof(backgrounds)/sizeof(struct pixrect *);
X
X	myname = *argv;
X	while(*++argv)
X	{	if(**argv != '-')
X			break;
X		switch(*(*argv + 1))
X		{	case 'g':		/* background ? */
X				if(atoi(*argv + 2) < max_bg)
X					grey = backgrounds[atoi(*argv + 2)];
X				else
X					fprintf(stderr, "%s: Max -g is %0d.\n",
X						myname, max_bg);
X				break;
X			case 'i':		/* invisible ? */
X				visible = 0;
X				break;
X			case 'p':		/* sleep interval */
X				nap_int = atof(*argv + 2);
X				break;
X			default:
X				fprintf(stderr, "%s: Unknown option: %c.\n",
X					myname, *(*argv + 1));
X				break;
X		}
X	}
X
X	if(nap_int < PERIOD)		/* prevent from becoming CPU hog */
X	{	fprintf(stderr, "%s: Bad period %0.2f, reset to %0.2f sec.\n",
X			myname, nap_int, PERIOD);
X		nap_int = PERIOD;
X	}
X	sec = nap_int;
X	usec = MILLION * (nap_int - (double)sec);
X
X	if( ! (pr = pr_open("/dev/fb")))
X		exit(-1);
X
X		/* get time for random(3) seed */
X	(void) gettimeofday(&tv, NULL);
X	srandom(tv.tv_sec);
X
X		/* set up memory pixrect for background */
X	mem_pr = mem_point(CWIDTH, CHEIGHT, pr->pr_depth, (short *)mem_im);
X
X		/* set up memory pixrect for the crab images (temporary) */
X		/* mininum width is 16 for these guys */
X	up_image = mem_point(16, CHEIGHT, 1, (short *)up_data);
X	down_image = mem_point(16, CHEIGHT, 1, (short *)down_data);
X	left_image = mem_point(16, CHEIGHT, 1, (short *)left_data);
X	right_image = mem_point(16, CHEIGHT, 1, (short *)right_data);
X
X		/* set up bitmap images for the crabs XOR'ed with background */
X	for(i = 0; i < 4; i++)
X	{	for(j = 0; j < 2; j++)
X		{	upmap[i][j] = mem_create(CWIDTH, CHEIGHT, 1);
X			pr_rop(upmap[i][j], 0, 0, CWIDTH, CHEIGHT,
X				PIX_SRC, up_image, 0, 0);
X			pr_replrop(upmap[i][j], 0, 0, CWIDTH, CHEIGHT,
X				PIX_XOR, grey, i, j);
X
X			downmap[i][j] = mem_create(CWIDTH, CHEIGHT, 1);
X			pr_rop(downmap[i][j], 0, 0, CWIDTH, CHEIGHT,
X				PIX_SRC, down_image, 0, 0);
X			pr_replrop(downmap[i][j], 0, 0, CWIDTH, CHEIGHT,
X				PIX_XOR, grey, i, j);
X
X			leftmap[i][j] = mem_create(CWIDTH, CHEIGHT, 1);
X			pr_rop(leftmap[i][j], 0, 0, CWIDTH, CHEIGHT,
X				PIX_SRC, left_image, 0, 0);
X			pr_replrop(leftmap[i][j], 0, 0, CWIDTH, CHEIGHT,
X				PIX_XOR, grey, i, j);
X
X			rightmap[i][j] = mem_create(CWIDTH, CHEIGHT, 1);
X			pr_rop(rightmap[i][j], 0, 0, CWIDTH, CHEIGHT,
X				PIX_SRC, right_image, 0, 0);
X			pr_replrop(rightmap[i][j], 0, 0, CWIDTH, CHEIGHT,
X				PIX_XOR, grey, i, j);
X		}
X	} 
X
X		/* Create initial set of crabs: */
X	for ( i = 0; i < NCRABS; ++i )
X	{
X		/* Assign random position within "crabs" layer: */
X		crab[i].ulc.x = RandInt(0, pr->pr_size.x - 8);
X		crab[i].ulc.y = 0;
X
X		/* Assign random velocity: */
X		NewVel(i);
X
X		/* Draw crab at initial position (within "crabs" layer): */
X		if (visible)
X			DrawCrab(i);
X	}
X
X	pr_destroy(up_image);
X	pr_destroy(down_image);
X	pr_destroy(right_image);
X	pr_destroy(left_image);
X
X		/* be nice - lower priority to lowest */
X	(void) setpriority(PRIO_PROCESS, getpid(), 20);
X}
X
Xstatic void
XCycle()					/* one motion cycle for all crabs */
X{
X	Point		p;		/* new crab upper left corner */
X	register	int	syndrome;	/* crab collision mask */
X	register	int	i;		/* crab # */
X	register	struct	pixrect	*oldmap;
X	register	short	*sp, *end;
X
X	oldmap = mem_pr;
X
X	for (i = 0; i < NCRABS; ++i)
X	{
X		DrawCrab(i);		/* erase crab from previous position */
X
X		p.x = crab[i].ulc.x + crab[i].vel.x;	/* motion */
X		p.y = crab[i].ulc.y + crab[i].vel.y;
X
X		if(p.x < 0)
X			p.x += pr->pr_size.x;
X		else if(p.x > pr->pr_size.x)
X			p.x -= pr->pr_size.x;
X
X		if(p.y < 0)
X			p.y += pr->pr_size.y;
X		else if(p.y > pr->pr_size.y)
X			p.y -= pr->pr_size.y;
X
X		/* Check for collision with other crabs;
X		   if you don't worry about this, you get
X		   crud left behind from crab collisions
X		   (visible in Scientific American article).
X		   (Note that crab # i has been removed.) */
X
X		/* The strategy is: only undraw possibly colliding crabs.
X		   The obvious alternative, not showing any crabs until
X		   all locations have been painted, would probably cause
X		   the set of crabs to flicker or to appear too faint. */
X
X#ifdef NOCOLLIDE
X		if ( (syndrome = Collide( p )) != 0 )
X			HideCrabs( syndrome );/* save from the following code */
X#endif
X
X			/* Save old contents of new crab location: */
X		pr_rop(oldmap, 0, 0, CWIDTH, CHEIGHT, PIX_SRC, pr, p.x, p.y);
X
X			/* Paint the new location grey: */
X		pr_replrop(pr, p.x, p.y, CWIDTH, CHEIGHT,
X					PIX_SRC, grey, p.x, p.y);
X
X			/* Determine if new location used to be grey: */
X		pr_rop(oldmap, 0, 0, CWIDTH, CHEIGHT, PIX_XOR, pr, p.x, p.y);
X
X		end = ((short *)mem_im) + 4 * pr->pr_depth;
X		for (sp = (short *)mem_im; sp < end; sp++ )
X			if(*sp != 0)	break;
X
X		if(sp < end)	/* location wasn't gray before, bounce */
X		{	p = crab[i].ulc;
X			crab[i].search_count = 0;
X			NewVel( i );	/* randomly alter crab velocity */
X		}
X		else
X		{	crab[i].search_count++;
X			if(ABS(crab[i].vel.x) < MAXVEL)
X				crab[i].vel.x += (crab[i].vel.x < 0) ? -1 : 1;
X			if(ABS(crab[i].vel.y) < MAXVEL)
X				crab[i].vel.y += (crab[i].vel.y < 0) ? -1 : 1;
X		}
X
X#ifdef NOCOLLIDE
X		if (syndrome != 0)
X			HideCrabs(syndrome);	/* bring them back */
X#endif
X
X			/* Draw the crab in its new position: */
X		crab[i].ulc = p;
X
X		if(crab[i].search_count > MAX_SEARCH)
X		{	crab[i].search_count = 0;
X			ModVel( i );	/* randomly alter crab velocity */
X		}
X
X		DrawCrab( i );
X	}
X}
X
X#ifdef NOCOLLIDE
X
Xstatic int
XCollide( p )				/* return syndrome for crab collision */
XPoint	p;			/* crab upper left corner */
X{
X	int	syndrome;		/* accumulate syndrome here */
X	bool	right = p.x % 32 > 32 - 8,
X		down = p.y % 32 > 32 - 8;	/* more than one vicinity? */
X	int	x32 = p.x / 32,
X		y32 = p.y / 32;		/* vicinity array indices */
X
X	/* "Or" in crabs from overlapping vicinities: */
X
X	syndrome = vicinity[x32 + 1][y32 + 1];
X	if ( right )
X		syndrome |= vicinity[x32 + 1 + 1][y32 + 1];
X	if ( down )
X		syndrome |= vicinity[x32 + 1][y32 + 1 + 1];
X	if ( right && down )
X		syndrome |= vicinity[x32 + 1 + 1][y32 + 1 + 1];	
X
X	return syndrome;
X}
X
X
Xstatic void
XHideCrabs( syndrome )			/* draw crabs contained in syndrome */
Xint	syndrome;		/* syndrome (crab bit flags) */
X{
X	int	i;			/* indexes crab[.] */
X	int	m;			/* bit mask for crab # i */
X
X	for ( m = 1, i = 0; i < NCRABS; m <<= 1, ++i )
X		if ( (m & syndrome) != 0 )	/* crab contained in syndrome */
X			DrawCrab( i );	/* toggle crab */
X}
X
X#endif
X
Xstatic void
XDrawCrab(index)				/* draw specified crab */
Xint	index;				/* crab # (0..NCRABS-1) */
X{
X	Point	p;			/* upper left corner for crab image */
X	Point	v;			/* crab velocity */
X	register	int	i, j;	/* selects 1/8 crab offsets wrt grey */
X	int	x32, y32;		/* vicinity array indices */
X	bool	right, down;		/* more than one vicinity? */
X	int	syn_bit;		/* crab possible-occupancy bit */
X
X	if (visible)
X	{
X		p = crab[index].ulc;
X		v = crab[index].vel;
X
X		if(grey == &blit || grey == &stripe)
X		{	i = p.x % 4;
X			j = p.y % 2;
X		}
X		else if(grey == &root_grey || grey == &inv_grey)
X		{	i = ((((p.y % 4) >> 1) << 1 ) + p.x) % 4;
X			j = p.y % 2;
X		}
X		else	/* white and black */
X		{	i = 0;
X			j = 0;
X		}
X
X		if ( ABS( v.x ) >= ABS( v.y ) )
X		{	if ( v.x < 0 )
X				pr_rop(pr, p.x, p.y, CWIDTH, CHEIGHT, PIX_XOR,
X					upmap[i][j], 0, 0);
X			else
X				pr_rop(pr, p.x, p.y, CWIDTH, CHEIGHT, PIX_XOR,
X					downmap[i][j], 0, 0);
X		}
X		else
X		{	if ( v.y < 0 )
X				pr_rop(pr, p.x, p.y, CWIDTH, CHEIGHT, PIX_XOR,
X					rightmap[i][j], 0, 0);
X			else
X				pr_rop(pr, p.x, p.y, CWIDTH, CHEIGHT, PIX_XOR,
X					leftmap[i][j], 0, 0);
X		}
X
X#ifdef NOCOLLIDE
X		/* A crab's vicinities are the disjoint 32x32 regions
X		   that contain any piece of the crab's 8x8 square.
X		   On the average, 9 out of 16 crabs occupy just 1
X		   vicinity; 6 out of 16 crabs occupy 2 vicinities,
X		   and 1 out of every 16 crabs occupies 4 vicinities. */
X
X		x32 = p.x >> 5;
X		y32 = p.y >> 5;		/* coords for upper left vicinity */
X
X		right = p.x % 32 > 32 - 8;	/* also next vicinity right? */
X		down = p.y % 32 > 32 - 8;	/* also next vicinty down? */
X
X		/* Toggle crab's occupancy bit in all occupied vicinities: */
X
X		syn_bit = 1 << index;
X
X		vicinity[x32 + 1][y32 + 1] ^= syn_bit;
X		if(right)
X			vicinity[x32 + 1 + 1][y32 + 1] ^= syn_bit;
X		if(down)
X			vicinity[x32 + 1][y32 + 1 + 1] ^= syn_bit;
X		if(right && down)
X			vicinity[x32 + 1 + 1][y32 + 1 + 1] ^= syn_bit;	
X#endif
X	}
X	/* else nibble away but don't show crabs */
X}
X
Xstatic void
XNewVel(i)			/* assign new velocity to crab */
Xint	i;			/* crab index */
X{
X	crab[i].vel.x = RandInt( 0 - MAXVEL, MAXVEL );
X	crab[i].vel.y = RandInt( 0 - MAXVEL, MAXVEL );
X
X	/* Velocity (0,0) is okay since we repeatedly modify all velocities. */
X}
X
Xstatic void
XModVel( i )				/* randomly modify crab velocity */
Xint	i;			/* crab # */
X{
X	int	d;			/* increment */
X
X	if ( crab[i].vel.x >= MAXVEL - 2 )
X		d = RandInt( -4, 2 );
X	else if ( crab[i].vel.x <= 2 - MAXVEL )
X		d = RandInt( -2, 4 );
X	else
X		d = RandInt( -4, 4 );
X
X	crab[i].vel.x += d;
X
X	if ( crab[i].vel.y >= MAXVEL - 2 )
X		d = RandInt( -4, 2 );
X	else if ( crab[i].vel.y <= 2 - MAXVEL )
X		d = RandInt( -2, 4 );
X	else
X		d = RandInt( -4, 4 );
X
X	crab[i].vel.y += d;
X}
X
Xstatic int
XRandInt(lo, hi)			/* generate random integer in range */
Xint	lo, hi;			/* range lo..hi-1 */
X{
X	register	long	rn;
X	long			random();
X
X	rn = random() >> 16;
X	return(lo + ((1 << 14) + (hi - lo) * rn)/(1<<15));
X}
X
Xstatic
Xvoid
Xnap(seconds, microseconds)
Xint	seconds, microseconds;
X{
X	struct	timeval	timeout;
X
X	timeout.tv_sec = seconds;
X	timeout.tv_usec = microseconds;
X
X		/* a cheap sub-second delay */
X	(void) select(1, 0, 0, 0, &timeout);
X}
*-*-END-of-crabs.c-*-*
exit