|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)worms.c 5.8 (Berkeley) 6/1/90";
28: #endif /* not lint */
29:
30: /*
31: *
32: * @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
33: * @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
34: * @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
35: * @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
36: * @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
37: * @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
38: * @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
39: * @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
40: * @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
41: *
42: * Eric P. Scott
43: * Caltech High Energy Physics
44: * October, 1980
45: *
46: */
47: #include <sys/types.h>
48: #include <stdio.h>
49: #ifdef USG
50: #include <termio.h>
51: #else
52: #include <sgtty.h>
53: #endif
54: #include <signal.h>
55:
56: static struct options {
57: int nopts;
58: int opts[3];
59: }
60: normal[8] = {
61: { 3, { 7, 0, 1 } },
62: { 3, { 0, 1, 2 } },
63: { 3, { 1, 2, 3 } },
64: { 3, { 2, 3, 4 } },
65: { 3, { 3, 4, 5 } },
66: { 3, { 4, 5, 6 } },
67: { 3, { 5, 6, 7 } },
68: { 3, { 6, 7, 0 } }
69: }, upper[8] = {
70: { 1, { 1, 0, 0 } },
71: { 2, { 1, 2, 0 } },
72: { 0, { 0, 0, 0 } },
73: { 0, { 0, 0, 0 } },
74: { 0, { 0, 0, 0 } },
75: { 2, { 4, 5, 0 } },
76: { 1, { 5, 0, 0 } },
77: { 2, { 1, 5, 0 } }
78: },
79: left[8] = {
80: { 0, { 0, 0, 0 } },
81: { 0, { 0, 0, 0 } },
82: { 0, { 0, 0, 0 } },
83: { 2, { 2, 3, 0 } },
84: { 1, { 3, 0, 0 } },
85: { 2, { 3, 7, 0 } },
86: { 1, { 7, 0, 0 } },
87: { 2, { 7, 0, 0 } }
88: },
89: right[8] = {
90: { 1, { 7, 0, 0 } },
91: { 2, { 3, 7, 0 } },
92: { 1, { 3, 0, 0 } },
93: { 2, { 3, 4, 0 } },
94: { 0, { 0, 0, 0 } },
95: { 0, { 0, 0, 0 } },
96: { 0, { 0, 0, 0 } },
97: { 2, { 6, 7, 0 } }
98: },
99: lower[8] = {
100: { 0, { 0, 0, 0 } },
101: { 2, { 0, 1, 0 } },
102: { 1, { 1, 0, 0 } },
103: { 2, { 1, 5, 0 } },
104: { 1, { 5, 0, 0 } },
105: { 2, { 5, 6, 0 } },
106: { 0, { 0, 0, 0 } },
107: { 0, { 0, 0, 0 } }
108: },
109: upleft[8] = {
110: { 0, { 0, 0, 0 } },
111: { 0, { 0, 0, 0 } },
112: { 0, { 0, 0, 0 } },
113: { 0, { 0, 0, 0 } },
114: { 0, { 0, 0, 0 } },
115: { 1, { 3, 0, 0 } },
116: { 2, { 1, 3, 0 } },
117: { 1, { 1, 0, 0 } }
118: },
119: upright[8] = {
120: { 2, { 3, 5, 0 } },
121: { 1, { 3, 0, 0 } },
122: { 0, { 0, 0, 0 } },
123: { 0, { 0, 0, 0 } },
124: { 0, { 0, 0, 0 } },
125: { 0, { 0, 0, 0 } },
126: { 0, { 0, 0, 0 } },
127: { 1, { 5, 0, 0 } }
128: },
129: lowleft[8] = {
130: { 3, { 7, 0, 1 } },
131: { 0, { 0, 0, 0 } },
132: { 0, { 0, 0, 0 } },
133: { 1, { 1, 0, 0 } },
134: { 2, { 1, 7, 0 } },
135: { 1, { 7, 0, 0 } },
136: { 0, { 0, 0, 0 } },
137: { 0, { 0, 0, 0 } }
138: },
139: lowright[8] = {
140: { 0, { 0, 0, 0 } },
141: { 1, { 7, 0, 0 } },
142: { 2, { 5, 7, 0 } },
143: { 1, { 5, 0, 0 } },
144: { 0, { 0, 0, 0 } },
145: { 0, { 0, 0, 0 } },
146: { 0, { 0, 0, 0 } },
147: { 0, { 0, 0, 0 } }
148: };
149:
150: #define cursor(c, r) tputs(tgoto(CM, c, r), 1, fputchar)
151:
152: char *tcp;
153: int fputchar();
154:
155: static char flavor[] = {
156: 'O', '*', '#', '$', '%', '0', '@', '~'
157: };
158: static short xinc[] = {
159: 1, 1, 1, 0, -1, -1, -1, 0
160: }, yinc[] = {
161: -1, 0, 1, 1, 1, 0, -1, -1
162: };
163: static struct worm {
164: int orientation, head;
165: short *xpos, *ypos;
166: } *worm;
167:
168: main(argc, argv)
169: int argc;
170: char **argv;
171: {
172: extern int optind;
173: extern short ospeed;
174: extern char *optarg, *UP;
175: register int x, y, h, n;
176: register struct worm *w;
177: register struct options *op;
178: register short *ip;
179: register char *term;
180: int CO, IN, LI, last, bottom, ch, length, number, trail, Wrap;
181: int onsig();
182: short **ref;
183: char *AL, *BC, *CM, *EI, *HO, *IC, *IM, *IP, *SR;
184: char *field, tcb[100], *mp, *malloc(), *getenv(), *tgetstr(), *tgoto();
185: long random();
186: #ifdef USG
187: struct termio sg;
188: #else
189: struct sgttyb sg;
190: #endif
191:
192: length = 16;
193: number = 3;
194: trail = ' ';
195: field = NULL;
196: while ((ch = getopt(argc, argv, "fl:n:t")) != EOF)
197: switch(ch) {
198: case 'f':
199: field = "WORM";
200: break;
201: case 'l':
202: if ((length = atoi(optarg)) < 2 || length > 1024) {
203: (void)fprintf(stderr,
204: "worms: invalid length (%d - %d).\n",
205: 2, 1024);
206: exit(1);
207: }
208: break;
209: case 'n':
210: if ((number = atoi(optarg)) < 1) {
211: (void)fprintf(stderr,
212: "worms: invalid number of worms.\n");
213: exit(1);
214: }
215: break;
216: case 't':
217: trail = '.';
218: break;
219: case '?':
220: default:
221: (void)fprintf(stderr,
222: "usage: worms [-ft] [-length #] [-number #]\n");
223: exit(1);
224: }
225:
226: if (!(term = getenv("TERM"))) {
227: (void)fprintf(stderr, "worms: no TERM environment variable.\n");
228: exit(1);
229: }
230: if (!(worm = (struct worm *)malloc((u_int)number *
231: sizeof(struct worm))) || !(mp = malloc((u_int)1024)))
232: nomem();
233: if (tgetent(mp, term) <= 0) {
234: (void)fprintf(stderr, "worms: %s: unknown terminal type.\n",
235: term);
236: exit(1);
237: }
238: tcp = tcb;
239: if (!(CM = tgetstr("cm", &tcp))) {
240: (void)fprintf(stderr,
241: "worms: terminal incapable of cursor motion.\n");
242: exit(1);
243: }
244: AL = tgetstr("al", &tcp);
245: BC = tgetflag("bs") ? "\b" : tgetstr("bc", &tcp);
246: if ((CO = tgetnum("co")) <= 0)
247: CO = 80;
248: last = CO - 1;
249: EI = tgetstr("ei", &tcp);
250: HO = tgetstr("ho", &tcp);
251: IC = tgetstr("ic", &tcp);
252: IM = tgetstr("im", &tcp);
253: IN = tgetflag("in");
254: IP = tgetstr("ip", &tcp);
255: if ((LI = tgetnum("li")) <= 0)
256: LI = 24;
257: bottom = LI - 1;
258: SR = tgetstr("sr", &tcp);
259: UP = tgetstr("up", &tcp);
260: #ifdef USG
261: ioctl(1, TCGETA, &sg);
262: ospeed = sg.c_cflag&CBAUD;
263: #else
264: gtty(1, &sg);
265: ospeed = sg.sg_ospeed;
266: #endif
267: Wrap = tgetflag("am");
268: if (!(ip = (short *)malloc((u_int)(LI * CO * sizeof(short)))))
269: nomem();
270: if (!(ref = (short **)malloc((u_int)(LI * sizeof(short *)))))
271: nomem();
272: for (n = 0; n < LI; ++n) {
273: ref[n] = ip;
274: ip += CO;
275: }
276: for (ip = ref[0], n = LI * CO; --n >= 0;)
277: *ip++ = 0;
278: if (Wrap)
279: ref[bottom][last] = 1;
280: for (n = number, w = &worm[0]; --n >= 0; w++) {
281: w->orientation = w->head = 0;
282: if (!(ip = (short *)malloc((u_int)(length * sizeof(short)))))
283: nomem();
284: w->xpos = ip;
285: for (x = length; --x >= 0;)
286: *ip++ = -1;
287: if (!(ip = (short *)malloc((u_int)(length * sizeof(short)))))
288: nomem();
289: w->ypos = ip;
290: for (y = length; --y >= 0;)
291: *ip++ = -1;
292: }
293:
294: (void)signal(SIGHUP, onsig);
295: (void)signal(SIGINT, onsig);
296: (void)signal(SIGQUIT, onsig);
297: (void)signal(SIGSTOP, onsig);
298: (void)signal(SIGTSTP, onsig);
299: (void)signal(SIGTERM, onsig);
300:
301: tputs(tgetstr("ti", &tcp), 1, fputchar);
302: tputs(tgetstr("cl", &tcp), 1, fputchar);
303: if (field) {
304: register char *p = field;
305:
306: for (y = bottom; --y >= 0;) {
307: for (x = CO; --x >= 0;) {
308: fputchar(*p++);
309: if (!*p)
310: p = field;
311: }
312: if (!Wrap)
313: fputchar('\n');
314: (void)fflush(stdout);
315: }
316: if (Wrap) {
317: if (IM && !IN) {
318: for (x = last; --x > 0;) {
319: fputchar(*p++);
320: if (!*p)
321: p = field;
322: }
323: y = *p++;
324: if (!*p)
325: p = field;
326: fputchar(*p);
327: if (BC)
328: tputs(BC, 1, fputchar);
329: else
330: cursor(last - 1, bottom);
331: tputs(IM, 1, fputchar);
332: if (IC)
333: tputs(IC, 1, fputchar);
334: fputchar(y);
335: if (IP)
336: tputs(IP, 1, fputchar);
337: tputs(EI, 1, fputchar);
338: }
339: else if (SR || AL) {
340: if (HO)
341: tputs(HO, 1, fputchar);
342: else
343: cursor(0, 0);
344: if (SR)
345: tputs(SR, 1, fputchar);
346: else
347: tputs(AL, LI, fputchar);
348: for (x = CO; --x >= 0;) {
349: fputchar(*p++);
350: if (!*p)
351: p = field;
352: }
353: }
354: else for (x = last; --x >= 0;) {
355: fputchar(*p++);
356: if (!*p)
357: p = field;
358: }
359: }
360: else for (x = CO; --x >= 0;) {
361: fputchar(*p++);
362: if (!*p)
363: p = field;
364: }
365: }
366: for (;;) {
367: (void)fflush(stdout);
368: for (n = 0, w = &worm[0]; n < number; n++, w++) {
369: if ((x = w->xpos[h = w->head]) < 0) {
370: cursor(x = w->xpos[h] = 0,
371: y = w->ypos[h] = bottom);
372: fputchar(flavor[n % sizeof(flavor)]);
373: ref[y][x]++;
374: }
375: else
376: y = w->ypos[h];
377: if (++h == length)
378: h = 0;
379: if (w->xpos[w->head = h] >= 0) {
380: register int x1, y1;
381:
382: x1 = w->xpos[h];
383: y1 = w->ypos[h];
384: if (--ref[y1][x1] == 0) {
385: cursor(x1, y1);
386: if (trail)
387: fputchar(trail);
388: }
389: }
390: op = &(!x ? (!y ? upleft : (y == bottom ? lowleft : left)) : (x == last ? (!y ? upright : (y == bottom ? lowright : right)) : (!y ? upper : (y == bottom ? lower : normal))))[w->orientation];
391: switch (op->nopts) {
392: case 0:
393: (void)fflush(stdout);
394: abort();
395: return;
396: case 1:
397: w->orientation = op->opts[0];
398: break;
399: default:
400: w->orientation =
401: op->opts[(int)random() % op->nopts];
402: }
403: cursor(x += xinc[w->orientation],
404: y += yinc[w->orientation]);
405: if (!Wrap || x != last || y != bottom)
406: fputchar(flavor[n % sizeof(flavor)]);
407: ref[w->ypos[h] = y][w->xpos[h] = x]++;
408: }
409: }
410: }
411:
412: onsig()
413: {
414: tputs(tgetstr("cl", &tcp), 1, fputchar);
415: tputs(tgetstr("te", &tcp), 1, fputchar);
416: exit(0);
417: }
418:
419: fputchar(c)
420: char c;
421: {
422: putchar(c);
423: }
424:
425: nomem()
426: {
427: (void)fprintf(stderr, "worms: not enough memory.\n");
428: exit(1);
429: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.