1*8873Smckusick 2*8873Smckusick static char sccsid[] = " worms.c 4.1 82/10/24 "; 3*8873Smckusick 4*8873Smckusick /* 5*8873Smckusick 6*8873Smckusick @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@ 7*8873Smckusick @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@ 8*8873Smckusick @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@ 9*8873Smckusick @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ 10*8873Smckusick @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ 11*8873Smckusick @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ 12*8873Smckusick @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ 13*8873Smckusick @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@ 14*8873Smckusick @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@ 15*8873Smckusick 16*8873Smckusick Eric P. Scott 17*8873Smckusick Caltech High Energy Physics 18*8873Smckusick October, 1980 19*8873Smckusick 20*8873Smckusick */ 21*8873Smckusick #include <stdio.h> 22*8873Smckusick #include <sgtty.h> 23*8873Smckusick #define cursor(col,row) tputs(tgoto(CM,col,row),1,outc) 24*8873Smckusick outc(c) 25*8873Smckusick { 26*8873Smckusick putchar(c); 27*8873Smckusick } 28*8873Smckusick extern char *UP; 29*8873Smckusick extern short ospeed; 30*8873Smckusick int Wrap; 31*8873Smckusick short *ref[24]; 32*8873Smckusick static char flavor[]={ 33*8873Smckusick 'O', '*', '#', '$', '%', '0' 34*8873Smckusick }; 35*8873Smckusick static short xinc[]={ 36*8873Smckusick 1, 1, 1, 0, -1, -1, -1, 0 37*8873Smckusick }, yinc[]={ 38*8873Smckusick -1, 0, 1, 1, 1, 0, -1, -1 39*8873Smckusick }; 40*8873Smckusick static struct worm { 41*8873Smckusick int orientation, head; 42*8873Smckusick short *xpos, *ypos; 43*8873Smckusick } worm[40]; 44*8873Smckusick static char *field; 45*8873Smckusick static int length=16, number=3, trail=' '; 46*8873Smckusick static struct options { 47*8873Smckusick int nopts; 48*8873Smckusick int opts[3]; 49*8873Smckusick } normal[8]={ 50*8873Smckusick { 3, { 7, 0, 1 } }, 51*8873Smckusick { 3, { 0, 1, 2 } }, 52*8873Smckusick { 3, { 1, 2, 3 } }, 53*8873Smckusick { 3, { 2, 3, 4 } }, 54*8873Smckusick { 3, { 3, 4, 5 } }, 55*8873Smckusick { 3, { 4, 5, 6 } }, 56*8873Smckusick { 3, { 5, 6, 7 } }, 57*8873Smckusick { 3, { 6, 7, 0 } } 58*8873Smckusick }, upper[8]={ 59*8873Smckusick { 1, { 1, 0, 0 } }, 60*8873Smckusick { 2, { 1, 2, 0 } }, 61*8873Smckusick { 0, { 0, 0, 0 } }, 62*8873Smckusick { 0, { 0, 0, 0 } }, 63*8873Smckusick { 0, { 0, 0, 0 } }, 64*8873Smckusick { 2, { 4, 5, 0 } }, 65*8873Smckusick { 1, { 5, 0, 0 } }, 66*8873Smckusick { 2, { 1, 5, 0 } } 67*8873Smckusick }, left[8]={ 68*8873Smckusick { 0, { 0, 0, 0 } }, 69*8873Smckusick { 0, { 0, 0, 0 } }, 70*8873Smckusick { 0, { 0, 0, 0 } }, 71*8873Smckusick { 2, { 2, 3, 0 } }, 72*8873Smckusick { 1, { 3, 0, 0 } }, 73*8873Smckusick { 2, { 3, 7, 0 } }, 74*8873Smckusick { 1, { 7, 0, 0 } }, 75*8873Smckusick { 2, { 7, 0, 0 } } 76*8873Smckusick }, right[8]={ 77*8873Smckusick { 1, { 7, 0, 0 } }, 78*8873Smckusick { 2, { 3, 7, 0 } }, 79*8873Smckusick { 1, { 3, 0, 0 } }, 80*8873Smckusick { 2, { 3, 4, 0 } }, 81*8873Smckusick { 0, { 0, 0, 0 } }, 82*8873Smckusick { 0, { 0, 0, 0 } }, 83*8873Smckusick { 0, { 0, 0, 0 } }, 84*8873Smckusick { 2, { 6, 7, 0 } } 85*8873Smckusick }, lower[8]={ 86*8873Smckusick { 0, { 0, 0, 0 } }, 87*8873Smckusick { 2, { 0, 1, 0 } }, 88*8873Smckusick { 1, { 1, 0, 0 } }, 89*8873Smckusick { 2, { 1, 5, 0 } }, 90*8873Smckusick { 1, { 5, 0, 0 } }, 91*8873Smckusick { 2, { 5, 6, 0 } }, 92*8873Smckusick { 0, { 0, 0, 0 } }, 93*8873Smckusick { 0, { 0, 0, 0 } } 94*8873Smckusick }, upleft[8]={ 95*8873Smckusick { 0, { 0, 0, 0 } }, 96*8873Smckusick { 0, { 0, 0, 0 } }, 97*8873Smckusick { 0, { 0, 0, 0 } }, 98*8873Smckusick { 0, { 0, 0, 0 } }, 99*8873Smckusick { 0, { 0, 0, 0 } }, 100*8873Smckusick { 1, { 3, 0, 0 } }, 101*8873Smckusick { 2, { 1, 3, 0 } }, 102*8873Smckusick { 1, { 1, 0, 0 } } 103*8873Smckusick }, upright[8]={ 104*8873Smckusick { 2, { 3, 5, 0 } }, 105*8873Smckusick { 1, { 3, 0, 0 } }, 106*8873Smckusick { 0, { 0, 0, 0 } }, 107*8873Smckusick { 0, { 0, 0, 0 } }, 108*8873Smckusick { 0, { 0, 0, 0 } }, 109*8873Smckusick { 0, { 0, 0, 0 } }, 110*8873Smckusick { 0, { 0, 0, 0 } }, 111*8873Smckusick { 1, { 5, 0, 0 } } 112*8873Smckusick }, lowleft[8]={ 113*8873Smckusick { 3, { 7, 0, 1 } }, 114*8873Smckusick { 0, { 0, 0, 0 } }, 115*8873Smckusick { 0, { 0, 0, 0 } }, 116*8873Smckusick { 1, { 1, 0, 0 } }, 117*8873Smckusick { 2, { 1, 7, 0 } }, 118*8873Smckusick { 1, { 7, 0, 0 } }, 119*8873Smckusick { 0, { 0, 0, 0 } }, 120*8873Smckusick { 0, { 0, 0, 0 } } 121*8873Smckusick }, lowright[8]={ 122*8873Smckusick { 0, { 0, 0, 0 } }, 123*8873Smckusick { 1, { 7, 0, 0 } }, 124*8873Smckusick { 2, { 5, 7, 0 } }, 125*8873Smckusick { 1, { 5, 0, 0 } }, 126*8873Smckusick { 0, { 0, 0, 0 } }, 127*8873Smckusick { 0, { 0, 0, 0 } }, 128*8873Smckusick { 0, { 0, 0, 0 } }, 129*8873Smckusick { 0, { 0, 0, 0 } } 130*8873Smckusick }; 131*8873Smckusick main(argc,argv) 132*8873Smckusick int argc; 133*8873Smckusick char *argv[]; 134*8873Smckusick { 135*8873Smckusick extern fputchar(); 136*8873Smckusick char *malloc(); 137*8873Smckusick char *getenv(); 138*8873Smckusick char *tgetstr(), *tgoto(); 139*8873Smckusick float ranf(); 140*8873Smckusick register int x, y; 141*8873Smckusick register int n; 142*8873Smckusick register struct worm *w; 143*8873Smckusick register struct options *op; 144*8873Smckusick register int h; 145*8873Smckusick register short *ip; 146*8873Smckusick char *AL, *BC, *CM, *EI, *HO, *IC, *IM, *IP, *SR; 147*8873Smckusick int CO, IN, LI, last, bottom; 148*8873Smckusick char *tcp; 149*8873Smckusick register char *term; 150*8873Smckusick char tcb[100]; 151*8873Smckusick struct sgttyb sg; 152*8873Smckusick setbuf(stdout,malloc(BUFSIZ)); 153*8873Smckusick for (x=1;x<argc;x++) { 154*8873Smckusick register char *p; 155*8873Smckusick p=argv[x]; 156*8873Smckusick if (*p=='-') p++; 157*8873Smckusick switch (*p) { 158*8873Smckusick case 'f': 159*8873Smckusick field="WORM"; 160*8873Smckusick break; 161*8873Smckusick case 'l': 162*8873Smckusick if (++x==argc) goto usage; 163*8873Smckusick if ((length=atoi(argv[x]))<2||length>1024) { 164*8873Smckusick fprintf(stderr,"%s: Invalid length\n",*argv); 165*8873Smckusick exit(1); 166*8873Smckusick } 167*8873Smckusick break; 168*8873Smckusick case 'n': 169*8873Smckusick if (++x==argc) goto usage; 170*8873Smckusick if ((number=atoi(argv[x]))<1||number>40) { 171*8873Smckusick fprintf(stderr,"%s: Invalid number of worms\n",*argv); 172*8873Smckusick exit(1); 173*8873Smckusick } 174*8873Smckusick break; 175*8873Smckusick case 't': 176*8873Smckusick trail='.'; 177*8873Smckusick break; 178*8873Smckusick default: 179*8873Smckusick usage: 180*8873Smckusick fprintf(stderr, 181*8873Smckusick "usage: %s [-field] [-length #] [-number #] [-trail]\n",*argv); 182*8873Smckusick exit(1); 183*8873Smckusick break; 184*8873Smckusick } 185*8873Smckusick } 186*8873Smckusick if (!(term=getenv("TERM"))) { 187*8873Smckusick fprintf(stderr,"%s: TERM: parameter not set\n",*argv); 188*8873Smckusick exit(1); 189*8873Smckusick } 190*8873Smckusick if (tgetent(malloc(1024),term)<=0) { 191*8873Smckusick fprintf(stderr,"%s: %s: unknown terminal type\n",*argv,term); 192*8873Smckusick exit(1); 193*8873Smckusick } 194*8873Smckusick tcp=tcb; 195*8873Smckusick if (!(CM=tgetstr("cm",&tcp))) { 196*8873Smckusick fprintf(stderr,"%s: terminal not capable of cursor motion\n",*argv); 197*8873Smckusick exit(1); 198*8873Smckusick } 199*8873Smckusick AL=tgetstr("al",&tcp); 200*8873Smckusick BC=tgetflag("bs") ? "\b" : tgetstr("bc",&tcp); 201*8873Smckusick if ((CO=tgetnum("co"))<=0) CO=80; 202*8873Smckusick last=CO-1; 203*8873Smckusick EI=tgetstr("ei",&tcp); 204*8873Smckusick HO=tgetstr("ho",&tcp); 205*8873Smckusick IC=tgetstr("ic",&tcp); 206*8873Smckusick IM=tgetstr("im",&tcp); 207*8873Smckusick IN=tgetflag("in"); 208*8873Smckusick IP=tgetstr("ip",&tcp); 209*8873Smckusick if ((LI=tgetnum("li"))<=0) LI=24; 210*8873Smckusick bottom=LI-1; 211*8873Smckusick SR=tgetstr("sr",&tcp); 212*8873Smckusick UP=tgetstr("up",&tcp); 213*8873Smckusick gtty(fileno(stdout),&sg); 214*8873Smckusick ospeed=sg.sg_ospeed; 215*8873Smckusick Wrap=tgetflag("am"); 216*8873Smckusick ip=(short *)malloc(LI*CO*sizeof (short)); 217*8873Smckusick for (n=0;n<LI;) { 218*8873Smckusick ref[n++]=ip; ip+=CO; 219*8873Smckusick } 220*8873Smckusick for (ip=ref[0],n=LI*CO;--n>=0;) *ip++=0; 221*8873Smckusick if (Wrap) ref[bottom][last]=1; 222*8873Smckusick for (n=number, w= &worm[0];--n>=0;w++) { 223*8873Smckusick w->orientation=w->head=0; 224*8873Smckusick if (!(ip=(short *)malloc(length*sizeof (short)))) { 225*8873Smckusick fprintf(stderr,"%s: out of memory\n",*argv); 226*8873Smckusick exit(1); 227*8873Smckusick } 228*8873Smckusick w->xpos=ip; 229*8873Smckusick for (x=length;--x>=0;) *ip++ = -1; 230*8873Smckusick if (!(ip=(short *)malloc(length*sizeof (short)))) { 231*8873Smckusick fprintf(stderr,"%s: out of memory\n",*argv); 232*8873Smckusick exit(1); 233*8873Smckusick } 234*8873Smckusick w->ypos=ip; 235*8873Smckusick for (y=length;--y>=0;) *ip++ = -1; 236*8873Smckusick } 237*8873Smckusick tputs(tgetstr("cl",&tcp),1,fputchar); 238*8873Smckusick if (field) { 239*8873Smckusick register char *p; 240*8873Smckusick p=field; 241*8873Smckusick for (y=bottom;--y>=0;) { 242*8873Smckusick for (x=CO;--x>=0;) { 243*8873Smckusick putchar(*p++); 244*8873Smckusick if (!*p) p=field; 245*8873Smckusick } 246*8873Smckusick if (!Wrap) putchar('\n'); 247*8873Smckusick fflush(stdout); 248*8873Smckusick } 249*8873Smckusick if (Wrap) { 250*8873Smckusick if (IM&&!IN) { 251*8873Smckusick for (x=last;--x>0;) { 252*8873Smckusick putchar(*p++); 253*8873Smckusick if (!*p) p=field; 254*8873Smckusick } 255*8873Smckusick y= *p++; if (!*p) p=field; 256*8873Smckusick putchar(*p); 257*8873Smckusick if (BC) fputs(BC,stdout); 258*8873Smckusick else cursor(last-1,bottom); 259*8873Smckusick fputs(IM,stdout); 260*8873Smckusick if (IC) tputs(IC,1,fputchar); 261*8873Smckusick putchar(y); 262*8873Smckusick if (IP) tputs(IP,1,fputchar); 263*8873Smckusick fputs(EI,stdout); 264*8873Smckusick } 265*8873Smckusick else if (SR||AL) { 266*8873Smckusick if (HO) fputs(HO,stdout); 267*8873Smckusick else cursor(0,0); 268*8873Smckusick if (SR) tputs(SR,1,fputchar); 269*8873Smckusick else tputs(AL,LI,fputchar); 270*8873Smckusick for (x=CO;--x>=0;) { 271*8873Smckusick putchar(*p++); 272*8873Smckusick if (!*p) p=field; 273*8873Smckusick } 274*8873Smckusick } 275*8873Smckusick else for (x=last;--x>=0;) { 276*8873Smckusick putchar(*p++); 277*8873Smckusick if (!*p) p=field; 278*8873Smckusick } 279*8873Smckusick } 280*8873Smckusick else for (x=CO;--x>=0;) { 281*8873Smckusick putchar(*p++); 282*8873Smckusick if (!*p) p=field; 283*8873Smckusick } 284*8873Smckusick } 285*8873Smckusick fflush(stdout); 286*8873Smckusick for (;;) { 287*8873Smckusick for (n=0,w= &worm[0];n<number;n++,w++) { 288*8873Smckusick if ((x=w->xpos[h=w->head])<0) { 289*8873Smckusick cursor(x=w->xpos[h]=0,y=w->ypos[h]=bottom); 290*8873Smckusick putchar(flavor[n%6]); 291*8873Smckusick ref[y][x]++; 292*8873Smckusick } 293*8873Smckusick else y=w->ypos[h]; 294*8873Smckusick if (++h==length) h=0; 295*8873Smckusick if (w->xpos[w->head=h]>=0) { 296*8873Smckusick register int x1, y1; 297*8873Smckusick x1=w->xpos[h]; y1=w->ypos[h]; 298*8873Smckusick if (--ref[y1][x1]==0) { 299*8873Smckusick cursor(x1,y1); putchar(trail); 300*8873Smckusick } 301*8873Smckusick } 302*8873Smckusick op= &(x==0 ? (y==0 ? upleft : (y==bottom ? lowleft : left)) : 303*8873Smckusick (x==last ? (y==0 ? upright : (y==bottom ? lowright : right)) : 304*8873Smckusick (y==0 ? upper : (y==bottom ? lower : normal))))[w->orientation]; 305*8873Smckusick switch (op->nopts) { 306*8873Smckusick case 0: 307*8873Smckusick fflush(stdout); 308*8873Smckusick abort(); 309*8873Smckusick return; 310*8873Smckusick case 1: 311*8873Smckusick w->orientation=op->opts[0]; 312*8873Smckusick break; 313*8873Smckusick default: 314*8873Smckusick w->orientation=op->opts[(int)(ranf()*(float)op->nopts)]; 315*8873Smckusick } 316*8873Smckusick cursor(x+=xinc[w->orientation], y+=yinc[w->orientation]); 317*8873Smckusick if (!Wrap||x!=last||y!=bottom) putchar(flavor[n%6]); 318*8873Smckusick ref[w->ypos[h]=y][w->xpos[h]=x]++; 319*8873Smckusick } 320*8873Smckusick fflush(stdout); 321*8873Smckusick } 322*8873Smckusick } 323*8873Smckusick fputchar(c) 324*8873Smckusick char c; 325*8873Smckusick { 326*8873Smckusick putchar(c); 327*8873Smckusick } 328*8873Smckusick float ranf() { 329*8873Smckusick return((float)rand()/2147483647.); 330*8873Smckusick } 331