Commit | Line | Data |
---|---|---|
5111e40b KM |
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 | } |