/*
@@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
@@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
@@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
@@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
@@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
@@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
@@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
Eric P. Scott
Caltech High Energy Physics
October, 1980
*/
#include <stdio.h> #include <gl/gl.h> #include <gl/device.h>
#define INCREMENT 1.0 #define MAXCOLS 100 #define MAXROWS 75 #define SEG0 20 #define SEG1 21 #define TRAIL_OBJ 22
int Wrap; short *ref[MAXROWS];
static int flavor[]={ 1, 2, 3, 4, 5, 6 };
static int segobj[]={ SEG1, SEG0, SEG0, SEG0, SEG0, SEG0 };
static short xinc[]= { 1, 1, 1, 0, -1, -1, -1, 0 },
yinc[]= {-1, 0, 1, 1, 1, 0, -1, -1 };
static struct worm {
int orientation, head;
short *xpos, *ypos;
} worm[40];
static char *field;
static int length=16, number=3, trail=' ';
static struct options {
int nopts;
int opts[3];
} nrmal[8]={
{ 3, { 7, 0, 1 } } ,
{ 3, { 0, 1, 2 } } ,
{ 3, { 1, 2, 3 } } ,
{ 3, { 2, 3, 4 } } ,
{ 3, { 3, 4, 5 } } ,
{ 3, { 4, 5, 6 } } ,
{ 3, { 5, 6, 7 } } ,
{ 3, { 6, 7, 0 } } },
upper[8]={
{ 1, { 1, 0, 0 } } ,
{ 2, { 1, 2, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 2, { 4, 5, 0 } } ,
{ 1, { 5, 0, 0 } } ,
{ 2, { 1, 5, 0 } } },
left[8]={
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 2, { 2, 3, 0 } } ,
{ 1, { 3, 0, 0 } } ,
{ 2, { 3, 7, 0 } } ,
{ 1, { 7, 0, 0 } } ,
{ 2, { 7, 0, 0 } }},
right[8]={
{ 1, { 7, 0, 0 } } ,
{ 2, { 3, 7, 0 } } ,
{ 1, { 3, 0, 0 } } ,
{ 2, { 3, 4, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 2, { 6, 7, 0 } }},
lower[8]={
{ 0, { 0, 0, 0 } } ,
{ 2, { 0, 1, 0 } } ,
{ 1, { 1, 0, 0 } } ,
{ 2, { 1, 5, 0 } } ,
{ 1, { 5, 0, 0 } } ,
{ 2, { 5, 6, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } }},
upleft[8]={
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 1, { 3, 0, 0 } } ,
{ 2, { 1, 3, 0 } } ,
{ 1, { 1, 0, 0 } }},
upright[8]={
{ 2, { 3, 5, 0 } } ,
{ 1, { 3, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 1, { 5, 0, 0 } }},
lowleft[8]={
{ 3, { 7, 0, 1 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 1, { 1, 0, 0 } } ,
{ 2, { 1, 7, 0 } } ,
{ 1, { 7, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } }},
lowright[8]={
{ 0, { 0, 0, 0 } } ,
{ 1, { 7, 0, 0 } } ,
{ 2, { 5, 7, 0 } } ,
{ 1, { 5, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } ,
{ 0, { 0, 0, 0 } } };
int m1, m2, m3; int coffset; int slowmode; int bigblox; int CO, LI;
main(argc,argv)
int argc;
char *argv[];
{
float ranf(); register int x, y; register int n; register struct worm *w; register struct options *op; register int h; register short *ip; int last, bottom; char *tcp; register char *term; char tcb[100];
srand(getpid()); CO = MAXCOLS; LI = MAXROWS; CO = 60; LI = 45; bottom = LI-1; last = CO-1;
/* make a work area */
keepaspect(400,300);
prefposition(XMAXSCREEN/4,XMAXSCREEN*3/4,YMAXSCREEN/4,
YMAXSCREEN*3/4);
winopen("worms");
makeframe();
makeobjects();
qdevice(RIGHTMOUSE);
qdevice(MIDDLEMOUSE);
qdevice(LEFTMOUSE);
for (x=1;x<argc;x++) {
register char *p;
p=argv[x];
if (*p=='-') p++;
switch (*p) {
case 'f':
field="WORM";
break;
case 'l':
if (++x==argc) goto usage;
if ((length=atoi(argv[x]))<2||length>1024) {
fprintf(stderr,"%s: Invalid length\n",*argv);
exit(1);
}
break;
case 'n':
if (++x==argc) goto usage;
if ((number=atoi(argv[x]))<1||number>40) {
fprintf(stderr,"%s: Invalid number of worms\n",*argv);
exit(1);
}
break;
case 't':
trail='.';
break;
default:
usage:
fprintf(stderr,
"Usage: %s [-field] [-length #] [-number #] [-trail]\n",
*argv);
exit(1);
break;
}
}
ip=(short *)malloc(LI*CO*sizeof (short));
for (n=0;n<LI;) {
ref[n++]=ip;
ip+=CO;
}
for (ip=ref[0],n=LI*CO;--n>=0;)
*ip++=0;
if (Wrap) ref[bottom][last]=1;
for (n=number, w= &worm[0];--n>=0;w++) {
w->orientation=w->head=0;
if (!(ip=(short *)malloc(length*sizeof (short)))) {
fprintf(stderr,"%s: out of memory\n",*argv);
exit(1);
}
w->xpos=ip;
for (x=length;--x>=0;) *ip++ = -1;
if (!(ip=(short *)malloc(length*sizeof (short)))) {
fprintf(stderr,"%s: out of memory\n",*argv);
exit(1);
}
w->ypos=ip;
for (y=length;--y>=0;) *ip++ = -1;
}
if (field) {
register char *p;
pushmatrix();
p=field;
for (y=bottom;--y>=0;) {
pushmatrix();
for (x=CO;--x>=0;) {
putfield();
translate(INCREMENT,0.0,0.0);
}
popmatrix();
translate(0.0,INCREMENT,0.0);
}
popmatrix(); }
for (;;) {
checkmouse();
for (n=0,w= &worm[0];n<number;n++,w++) {
if ((x=w->xpos[h=w->head])<0) {
x=w->xpos[h]=0;
y=w->ypos[h]=bottom;
pushmatrix();
translate((float)x,(float)y,0.0);
if(bigblox)
scale(2.0,2.0,1.0);
putsegment(flavor[n%6],segobj[n%6]);
popmatrix();
ref[y][x]++;
}
else y=w->ypos[h];
if (++h==length) h=0;
if (w->xpos[w->head=h]>=0) {
register int x1, y1;
x1=w->xpos[h];
y1=w->ypos[h];
if (--ref[y1][x1]==0) {
pushmatrix();
translate((float)x1,(float)y1,0.0);
puttrail();
popmatrix();
}
}
op= &(x==0 ? (y==0 ? upleft : (y==bottom ? lowleft :
left)) :
(x==last ? (y==0 ? upright :
(y==bottom ? lowright : right)) :
(y==0 ? upper : (y==bottom ? lower :
nrmal))))[w->orientation];
switch (op->nopts) {
case 0:
fflush(stdout);
abort();
return;
case 1:
w->orientation=op->opts[0];
break;
default:
w->orientation=op->opts[
(int)(ranf()*(float)op->nopts)];
}
x+=xinc[w->orientation];
y+=yinc[w->orientation];
if (!Wrap||x!=last||y!=bottom) {
pushmatrix();
translate((float)x,(float)y,0.0);
if(bigblox)
scale(2.0,2.0,1.0);
putsegment(flavor[n%6],segobj[n%6]);
popmatrix();
}
ref[w->ypos[h]=y][w->xpos[h]=x]++;
}
}
}
checkmouse()
{
short dev, val; static int upcount;
if(upcount++ != 20)
return;
if(slowmode)
sleep(2);
upcount = 0;
gsync();
while(qtest()) {
dev = qread(&val);
switch(dev) {
case RIGHTMOUSE:
m1 = val;
coffset++;
break;
case MIDDLEMOUSE:
m2 = val;
if(val)
slowmode = 1-slowmode;
break;
case LEFTMOUSE:
m3 = val;
if(val)
bigblox = 1-bigblox;
break;
case REDRAW:
reshapeviewport();
makeframe();
break;
}
if(m1 && m3) {
color(0);
clear();
}
}
}
float ranf() {
return ((rand()>>1) % 10000)/10000.0;
}
putfield()
{
color(3);
callobj(SEG0);
}
putsegment(col,obj)
int col;
int obj;
{
color((col+coffset)%8);
callobj(obj);
}
puttrail()
{
callobj(TRAIL_OBJ);
}
makeobjects()
{
makeobj(SEG0);
rectf(-INCREMENT/3.0, -INCREMENT/3.0, INCREMENT/3.0,
INCREMENT/3.0);
closeobj();
makeobj(SEG1);
rectf(-INCREMENT/3.0, -INCREMENT/3.0, INCREMENT/3.0,
INCREMENT/3.0);
closeobj();
makeobj(TRAIL_OBJ);
color(7);
rectf(-INCREMENT/3.0, -INCREMENT/3.0, INCREMENT/3.0,
INCREMENT/3.0);
closeobj();
}
makeframe()
{
color(0);
clear();
ortho2(-1.5,CO+0.5,-1.5,LI+0.5);
color(7);
recti(-1,-1,CO,LI);
}
The gsync subroutine.