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