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