termite: A SUN Diversion

jpn at teddy.UUCP jpn at teddy.UUCP
Sat Jan 17 06:50:10 AEST 1987


I recently found a bug in one of my programs, so I tamed it, and made a pet
out of it.  I display him proudly instead of the standard "lockscreen".

No man page or makefile, but the comments at the top of the C source say it
all.  Sorry, folks, this is SUN specific.

-----cut-----cut-----cut-----cut-----cut-----cut-----cut-----cut-----
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	termite.c
# This archive created: Fri Jan 16 15:42:38 1987
export PATH; PATH=/bin:$PATH
echo shar: extracting "'termite.c'" '(12712 characters)'
if test -f 'termite.c'
then
	echo shar: will not over-write existing file "'termite.c'"
else
cat << \SHAR_EOF > 'termite.c'
/* termite.c	15-Jan-87 11:53 jpn added comments prior to news posting
 *		 8-Jan-86 11:54 jpn Much Code taken from bug[123].c
 *            	 6-Jan-86 17:01 jpn Author
 *
 * Compile: cc -o termite termite.c -lpixrect
 *
 * Usage: termite                   - termite leaves a trail of root grey
 *        termite -w                - termite leaves a trail of white
 *        termite -b                - termite leaves a trail of black
 *        termite -3                - runs one of each
 *
 * Description:  Termite is a program that scribbles on a Sun B/W screen.
 *    It has only been tried on sun2 and sun3 screens, and sun2 & sun3 UNIX.
 *    I have no idea if this will work on a color tube.
 *
 *    I find that "lockscreen termite -3" makes an interesting alternative
 *    to the standard lockscreen.
 *
 * Author:  John P. Nelson (decvax!genrad!teddy!jpn)
 *    Please send any enhancements or bug fixes.
 */

#include <stdio.h>
#include <signal.h>
/* #include <sys/time.h> */	/* included by something else? */
#include <sunwindow/window_hs.h>
#include <suntool/icon.h>
#include <suntool/icon_load.h>

#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3

/* configurable.   I like the way these cause the termite to behave */
#define TRAVEL 55
#define HUNGRY 11
#define SATIATED 3
#define DINNER 20
#define LOST 20

/* pixrect magic */
#define	BUG_WIDTH	16
#define	BUG_HEIGHT	16
#define PATTERN_SIZE	4
#define PIX_XOR (PIX_SRC^PIX_DST)

#define PIX_OP PIX_SRC

#define	DEFINE_BUG_FROM_IMAGE(name, image)				\
	static struct mpr_data CAT(name,_data) = {			\
	    mpr_linebytes(BUG_WIDTH,1), (short *)(image),		\
	    {0, 0}, 0, 0};						\
	extern struct pixrectops mem_ops;				\
	static struct pixrect CAT(name,_mpr) = {			\
	    &mem_ops, BUG_WIDTH, BUG_HEIGHT, 1,				\
	    (caddr_t)&CAT(name,_data)};

/* cursor images - created using icontool */

    /* termite facing UP */
static short bug1[] = {
/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
 */
	0x0000,0x0000,0x0C30,0x0660,0x03C0,0x0180,0x15A8,0x2BD4,
	0x03C0,0x17E8,0x2BD4,0x03C0,0x17E8,0x2BD4,0x0000,0x0000
};
    /* termite facing RIGHT */
static short bug2[] = {
/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
 */
	0x0000,0x0000,0x2480,0x1240,0x2484,0x124C,0x3F98,0x3FF0,
	0x3FF0,0x3F98,0x124C,0x2484,0x1240,0x2480,0x0000,0x0000
};
    /* termite facing DOWN */
static short bug3[] = {
/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
 */
	0x0000,0x0000,0x2BD4,0x17E8,0x03C0,0x2BD4,0x17E8,0x03C0,
	0x2BD4,0x15A8,0x0180,0x03C0,0x0660,0x0C30,0x0000,0x0000
};
    /* termite facing LEFT */
static short bug4[] = {
/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
 */
	0x0000,0x0000,0x0124,0x0248,0x2124,0x3248,0x19FC,0x0FFC,
	0x0FFC,0x19FC,0x3248,0x2124,0x0248,0x0124,0x0000,0x0000
};

    /* rootgrey cursor */
static short grey[] = {
/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
 */
	0x8888,0x8888,0x2222,0x2222,0x8888,0x8888,0x2222,0x2222,
	0x8888,0x8888,0x2222,0x2222,0x8888,0x8888,0x2222,0x2222
};

    /* empty storage - used to read screen */
static short zero[] = {
/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
 */
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};

    /* white cursor */
static short white[] = {
/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
 */
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};

    /* black cursor */
static short black[] = {
/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
 */
	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF
};

/* the following are vertical and horizontal slices (of various colors)
 * which are used to compare against the slice read from the screen.
 * This comparison is used to control the speed of the termite
 */
static short vgrey[] = { 0x8888, 0x8888, 0x2222, 0x2222 };
static short hgrey[] = {
    0x8000, 0x8000, 0x2000, 0x2000, 0x8000, 0x8000, 0x2000, 0x2000, 
    0x8000, 0x8000, 0x2000, 0x2000, 0x8000, 0x8000, 0x2000, 0x2000, 
};

static short vblack[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
static short hblack[] = {
    0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000,
    0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 
};

static short vwhite[] = { 0x0000, 0x0000, 0x0000, 0x0000 };
static short hwhite[] = {
    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};

    /* This gives the gray backround which is xor'ed into a grey
     * termite to give the effect of a static backround
     */
static short biggrey[] = {
/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
 */
	0x8888,0x8888,0x8888,0x8888,0x2222,0x2222,0x2222,0x2222,
	0x8888,0x8888,0x8888,0x8888,0x2222,0x2222,0x2222,0x2222,
	0x8888,0x8888,0x8888,0x8888,0x2222,0x2222,0x2222,0x2222,
	0x8888,0x8888,0x8888,0x8888,0x2222,0x2222,0x2222,0x2222,
	0x8888,0x8888,0x8888,0x8888,0x2222,0x2222,0x2222,0x2222,
	0x8888,0x8888,0x8888,0x8888,0x2222,0x2222,0x2222,0x2222,
	0x8888,0x8888,0x8888,0x8888,0x2222,0x2222,0x2222,0x2222,
	0x8888,0x8888,0x8888,0x8888,0x2222,0x2222,0x2222,0x2222,
};
static short *vmatch, *hmatch;

/* generate memory pixrect handles for all the cursor images, above */
DEFINE_BUG_FROM_IMAGE(up, bug1);
DEFINE_BUG_FROM_IMAGE(right, bug2);
DEFINE_BUG_FROM_IMAGE(down, bug3);
DEFINE_BUG_FROM_IMAGE(left, bug4);
DEFINE_BUG_FROM_IMAGE(root, grey);
DEFINE_BUG_FROM_IMAGE(root2, black);
DEFINE_BUG_FROM_IMAGE(root3, white);
DEFINE_BUG_FROM_IMAGE(empty, zero);

static struct mpr_data big_data = {
	    mpr_linebytes(BUG_WIDTH * 2,1), (short *)(biggrey),
	    {0, 0}, 0, 0};
static struct pixrect big_mpr = {
	    &mem_ops, BUG_WIDTH * 2, BUG_HEIGHT * 2, 1,
	    (caddr_t)&big_data};
/* mpr_static(big_mpr, (2*BUG_WIDTH), (2*BUG_HEIGHT), (4*BUG_WIDTH*BUG_HEIGHT), biggrey); */

/* this array corresponds the "dir" direction to termite images */
struct pixrect *mprs[] = {&up_mpr, &right_mpr, &down_mpr, &left_mpr};

static int dir;				/* current direction of travel */
static int xlimit, ylimit;		/* maximum x and y coordinates */
static int chance = TRAVEL;		/* behavior variable */
static int speed  = 1;			/* current distance per tick */
static struct pixrect *window;		/* points to screen */
static int blackmode = 0;		/* select type of termite */
static int ppid = 0;			/* for termite -3, parent pid */

main(argc, argv)
int argc;
char **argv;
    {
    register int i;
    struct pixrect *pr;			/* current termite image */
    struct pixrect *gr;			/* backround image */
    int x, y;				/* current x, y location */
    struct pixrect *mt;			/* pointer to empty pixrect */
    long time();

    gr = &root_mpr;
    mt = &empty_mpr;
    hmatch = hgrey;
    vmatch = vgrey;

    /* parse command line */
    if (argc > 1)
	{
	if (!strcmp (argv[1], "-b"))
	    {
	    blackmode = 1;
	    gr = &root2_mpr;
	    hmatch = hblack;
	    vmatch = vblack;
	    }
	else if (!strcmp(argv[1], "-w"))
	    {
	    gr = &root3_mpr;
	    hmatch = hwhite;
	    vmatch = vwhite;
	    }
	else if (!strcmp(argv[1], "-3"))
	    {
	    ppid = getpid();
	    if (fork())
		{
		/* im the parent */
		gr = &root3_mpr;
		hmatch = hwhite;
		vmatch = vwhite;
		ppid = 0;
		}
	    else if (fork())
		{
		sleep(2);
		blackmode = 1;
		gr = &root2_mpr;
		hmatch = hblack;
		vmatch = vblack;
		}
	    else
		sleep(4);
	    }
	}

    /* open the raw screen device */
    window = pr_open("/dev/fb");

    xlimit = window->pr_size.x - BUG_WIDTH;
    ylimit = window->pr_size.y - BUG_HEIGHT;
    pr = &right_mpr;

    /* initialize the bug */
    x = 0; y = 0;
    dir = RIGHT;
    srandom((int) time((long *)0));
    napinit();

    /* go */
    while(1)
	{
	while (changedir(x,y))
	    ;				/* check for direction change */
	checkspeed(x,y);		/* check for speed change */
	if (ppid) checkdie();		/* check for termination */
	pr = mprs[dir];			/* image to use by direction */

	/* put down backround where we have already been */
	switch(dir)
	    {
	case UP:
	    i = y+BUG_HEIGHT-speed;
	    pr_rop(window, x, i, BUG_WIDTH, speed, PIX_SRC, gr, 0,i%BUG_HEIGHT);
	    y -= speed;
	    break;
	case RIGHT:
	    i = x;
	    pr_rop(window, i, y, speed, BUG_HEIGHT, PIX_SRC, gr, i%BUG_WIDTH,0);
	    x += speed;
	    break;
	case DOWN:
	    i = y;
	    pr_rop(window, x, i, BUG_WIDTH, speed, PIX_SRC, gr, 0,i%BUG_HEIGHT);
	    y += speed;
	    break;
	case LEFT:
	    i = x+BUG_WIDTH-speed;
	    pr_rop(window, i, y, speed, BUG_HEIGHT, PIX_SRC, gr, i%BUG_WIDTH,0);
	    x -= speed;
	    break;
	    }

	if (gr == &root_mpr)		/* grey mode */
	    {
	    pr_rop(mt, 0, 0, BUG_WIDTH, BUG_HEIGHT, PIX_SRC, pr, 0, 0);
	    pr_rop(mt, 0, 0, BUG_WIDTH, BUG_HEIGHT, PIX_SRC|PIX_DST, &big_mpr,
		    x % BUG_WIDTH, y % BUG_HEIGHT);
	    pr_rop(window, x, y, BUG_WIDTH, BUG_HEIGHT, PIX_OP,mt,0,0);
	    }

	else if (blackmode)		/* black mode */
	    pr_rop(window, x, y, BUG_WIDTH, BUG_HEIGHT, PIX_NOT(PIX_OP),pr,0,0);

	else				/* white mode */
	    pr_rop(window, x, y, BUG_WIDTH, BUG_HEIGHT, PIX_OP,pr,0,0);

	/* quick sleep - makes sun2 and sun3 go at same speed! */
	quicknap();
	}
    }

/* if at a PATTERN_SIZE nexus, check for a direction change. */
changedir(x,y)
int x,y;
    {
    long random();

    if ((x & (PATTERN_SIZE - 1)) || (y & (PATTERN_SIZE - 1)))
	return 0;
    
    if ((x >= xlimit && dir == RIGHT) || (y >= ylimit && dir == DOWN)
	  || (x == 0 && dir == LEFT) || (y == 0 && dir == UP)
	  || (random() % chance == 0))
	{
	if (random() & 1)
	    dir = (dir + 1) % 4;
	else
	    dir = (dir + 3) % 4;
	return 1;
	}
    return 0;
    }

/* if in termite -3 mode, check for parent death */
checkdie()
    {
    /* if parent died, then we die too */
    static int foo = 0;
    if ((++foo & 0xFF) == 0)
	{
	if (kill(ppid, 0) < 0)
	    exit(0);
	foo = 0;
	}
    }

/* if at a PATTERN_SIZE nexus, check for a speed change.  This function
 * attempts to determine what sort of backround the termite is plowing
 * through, and this affects it's future "behavier".
 */
checkspeed(x,y)
int x,y;
    {
    int height, width;
    int xfrom, yfrom;
    int isgrey;
    static int iseat = 0;
    static int eatcount = 0;
    static int movecount = 0;

    if ((x & (PATTERN_SIZE - 1)) || (y & (PATTERN_SIZE - 1)))
	return;
    switch (dir)
	{
	case UP:
	    height = PATTERN_SIZE; width = BUG_WIDTH;
	    xfrom = x + 0; yfrom = y -PATTERN_SIZE;
	    break;
	case RIGHT:
	    height = BUG_HEIGHT; width = PATTERN_SIZE;
	    xfrom = x + BUG_WIDTH; yfrom = y + 0;
	    break;
	case DOWN:
	    height = PATTERN_SIZE; width = BUG_WIDTH;
	    xfrom = x + 0; yfrom = y + BUG_WIDTH;
	    break;
	case LEFT:
	    height = BUG_HEIGHT; width = PATTERN_SIZE;
	    xfrom = x - PATTERN_SIZE; yfrom = y + 0;
	    break;
	}
	
    bzero(zero, 32);
    pr_rop(&empty_mpr, 0, 0, width, height, PIX_SRC, window, xfrom, yfrom);

    isgrey = 0;
    switch (dir)
	{
	case UP:
	case DOWN:
	    if (!bcmp(zero, vmatch, sizeof(vgrey)))
		isgrey = 1;
	case RIGHT:
	case LEFT:
	    if (!bcmp(zero, hmatch, sizeof(hgrey)))
		isgrey = 1;
	}

    /* what follows is a complex set of condiitions which defines
    ** the bug's behavior */
    if (isgrey)
	{
	if (iseat)
	    {
	    iseat = 0;
	    movecount = 0;
	    }

	if (++movecount < LOST)
	    chance = SATIATED;		/* stay near food */
	else
	    chance = TRAVEL;		/* travel, look for food */

	speed = PATTERN_SIZE;
	}
    else
	{
	if (iseat == 0)
	    {
	    iseat = 1;
	    if (movecount > LOST || eatcount < DINNER)
		eatcount = 0;
	    }

	if (++eatcount > DINNER)
	    chance = SATIATED;	/* more likely to change direction */
	else
	    chance = HUNGRY;	/* keep eating */

	speed = 1;
	}
    }

/* set up a continuous ticker, so that we can implement a fast sleep
 * by calling sigpause.  If we miss one, no sweat, we'll just catch
 * the next one.  Using the ticker this way leads to relatively smooth
 * movement of the termite even if other tasks are running, and it
 * also provides similar movement on both sun2 and sun3 machines
 */

#define bit(_a) (1<<((_a)-1))
static struct itimerval nap;
static tick()
    {
    }

napinit()
    {
    signal(SIGALRM, tick);
    timerclear(&(nap.it_interval));
    timerclear(&(nap.it_value));
    nap.it_value.tv_usec = 20000;	/* 1/50 sec */
    nap.it_interval.tv_usec = 20000;	/* 1/50 sec */
    setitimer(ITIMER_REAL, &nap, (struct itimerval *) 0);
    }

quicknap()
    {
    sigpause(0);
    }
SHAR_EOF
if test 12712 -ne "`wc -c < 'termite.c'`"
then
	echo shar: error transmitting "'termite.c'" '(should have been 12712 characters)'
fi
fi
exit 0
#	End of shell archive



More information about the Comp.sources.unix mailing list