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