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