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