1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32: #include <sys/cdefs.h>
33: #ifndef lint
34: __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
35: The Regents of the University of California. All rights reserved.\n");
36: #endif
37:
38: #ifndef lint
39: #if 0
40: static char sccsid[] = "@(#)worms.c 8.1 (Berkeley) 5/31/93";
41: #else
42: __RCSID("$NetBSD: worms.c,v 1.16 2004/09/12 04:51:32 christos Exp $");
43: #endif
44: #endif
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63: #include <sys/types.h>
64:
65: #include <curses.h>
66: #include <err.h>
67: #include <signal.h>
68: #include <stdio.h>
69: #include <stdlib.h>
70: #include <unistd.h>
71:
72: static const struct options {
73: int nopts;
74: int opts[3];
75: }
76: normal[8] = {
77: { 3, { 7, 0, 1 } },
78: { 3, { 0, 1, 2 } },
79: { 3, { 1, 2, 3 } },
80: { 3, { 2, 3, 4 } },
81: { 3, { 3, 4, 5 } },
82: { 3, { 4, 5, 6 } },
83: { 3, { 5, 6, 7 } },
84: { 3, { 6, 7, 0 } }
85: }, upper[8] = {
86: { 1, { 1, 0, 0 } },
87: { 2, { 1, 2, 0 } },
88: { 0, { 0, 0, 0 } },
89: { 0, { 0, 0, 0 } },
90: { 0, { 0, 0, 0 } },
91: { 2, { 4, 5, 0 } },
92: { 1, { 5, 0, 0 } },
93: { 2, { 1, 5, 0 } }
94: },
95: left[8] = {
96: { 0, { 0, 0, 0 } },
97: { 0, { 0, 0, 0 } },
98: { 0, { 0, 0, 0 } },
99: { 2, { 2, 3, 0 } },
100: { 1, { 3, 0, 0 } },
101: { 2, { 3, 7, 0 } },
102: { 1, { 7, 0, 0 } },
103: { 2, { 7, 0, 0 } }
104: },
105: right[8] = {
106: { 1, { 7, 0, 0 } },
107: { 2, { 3, 7, 0 } },
108: { 1, { 3, 0, 0 } },
109: { 2, { 3, 4, 0 } },
110: { 0, { 0, 0, 0 } },
111: { 0, { 0, 0, 0 } },
112: { 0, { 0, 0, 0 } },
113: { 2, { 6, 7, 0 } }
114: },
115: lower[8] = {
116: { 0, { 0, 0, 0 } },
117: { 2, { 0, 1, 0 } },
118: { 1, { 1, 0, 0 } },
119: { 2, { 1, 5, 0 } },
120: { 1, { 5, 0, 0 } },
121: { 2, { 5, 6, 0 } },
122: { 0, { 0, 0, 0 } },
123: { 0, { 0, 0, 0 } }
124: },
125: upleft[8] = {
126: { 0, { 0, 0, 0 } },
127: { 0, { 0, 0, 0 } },
128: { 0, { 0, 0, 0 } },
129: { 0, { 0, 0, 0 } },
130: { 0, { 0, 0, 0 } },
131: { 1, { 3, 0, 0 } },
132: { 2, { 1, 3, 0 } },
133: { 1, { 1, 0, 0 } }
134: },
135: upright[8] = {
136: { 2, { 3, 5, 0 } },
137: { 1, { 3, 0, 0 } },
138: { 0, { 0, 0, 0 } },
139: { 0, { 0, 0, 0 } },
140: { 0, { 0, 0, 0 } },
141: { 0, { 0, 0, 0 } },
142: { 0, { 0, 0, 0 } },
143: { 1, { 5, 0, 0 } }
144: },
145: lowleft[8] = {
146: { 3, { 7, 0, 1 } },
147: { 0, { 0, 0, 0 } },
148: { 0, { 0, 0, 0 } },
149: { 1, { 1, 0, 0 } },
150: { 2, { 1, 7, 0 } },
151: { 1, { 7, 0, 0 } },
152: { 0, { 0, 0, 0 } },
153: { 0, { 0, 0, 0 } }
154: },
155: lowright[8] = {
156: { 0, { 0, 0, 0 } },
157: { 1, { 7, 0, 0 } },
158: { 2, { 5, 7, 0 } },
159: { 1, { 5, 0, 0 } },
160: { 0, { 0, 0, 0 } },
161: { 0, { 0, 0, 0 } },
162: { 0, { 0, 0, 0 } },
163: { 0, { 0, 0, 0 } }
164: };
165:
166:
167: static const char flavor[] = {
168: 'O', '*', '#', '$', '%', '0', '@', '~'
169: };
170: static const short xinc[] = {
171: 1, 1, 1, 0, -1, -1, -1, 0
172: }, yinc[] = {
173: -1, 0, 1, 1, 1, 0, -1, -1
174: };
175: static struct worm {
176: int orientation, head;
177: short *xpos, *ypos;
178: } *worm;
179:
180: volatile sig_atomic_t sig_caught = 0;
181:
182: int main(int, char **);
183: void nomem(void) __attribute__((__noreturn__));
184: void onsig(int);
185:
186: int
187: main(argc, argv)
188: int argc;
189: char *argv[];
190: {
191: int x, y, h, n;
192: struct worm *w;
193: const struct options *op;
194: short *ip;
195: int CO, LI, last, bottom, ch, length, number, trail;
196: short **ref;
197: const char *field;
198: char *mp;
199: unsigned int delay = 0;
200:
201:
202: setregid(getgid(), getgid());
203:
204: mp = NULL;
205: length = 16;
206: number = 3;
207: trail = ' ';
208: field = NULL;
209: while ((ch = getopt(argc, argv, "d:fl:n:t")) != -1)
210: switch(ch) {
211: case 'd':
212: if ((delay = (unsigned int)strtoul(optarg, (char **)NULL, 10)) < 1 || delay > 1000)
213: errx(1, "invalid delay (1-1000)");
214: delay *= 1000;
215: break;
216: case 'f':
217: field = "WORM";
218: break;
219: case 'l':
220: if ((length = atoi(optarg)) < 2 || length > 1024) {
221: errx(1, "invalid length (%d - %d).",
222: 2, 1024);
223: }
224: break;
225: case 'n':
226: if ((number = atoi(optarg)) < 1) {
227: errx(1, "invalid number of worms.");
228: }
229: break;
230: case 't':
231: trail = '.';
232: break;
233: case '?':
234: default:
235: (void)fprintf(stderr,
236: "usage: worms [-ft] [-d delay] [-l length] [-n number]\n");
237: exit(1);
238: }
239:
240: if (!(worm = malloc((size_t)number *
241: sizeof(struct worm))) || !(mp = malloc((size_t)1024)))
242: nomem();
243: initscr();
244: curs_set(0);
245: CO = COLS;
246: LI = LINES;
247: last = CO - 1;
248: bottom = LI - 1;
249: if (!(ip = malloc((size_t)(LI * CO * sizeof(short)))))
250: nomem();
251: if (!(ref = malloc((size_t)(LI * sizeof(short *)))))
252: nomem();
253: for (n = 0; n < LI; ++n) {
254: ref[n] = ip;
255: ip += CO;
256: }
257: for (ip = ref[0], n = LI * CO; --n >= 0;)
258: *ip++ = 0;
259: for (n = number, w = &worm[0]; --n >= 0; w++) {
260: w->orientation = w->head = 0;
261: if (!(ip = malloc((size_t)(length * sizeof(short)))))
262: nomem();
263: w->xpos = ip;
264: for (x = length; --x >= 0;)
265: *ip++ = -1;
266: if (!(ip = malloc((size_t)(length * sizeof(short)))))
267: nomem();
268: w->ypos = ip;
269: for (y = length; --y >= 0;)
270: *ip++ = -1;
271: }
272:
273: (void)signal(SIGHUP, onsig);
274: (void)signal(SIGINT, onsig);
275: (void)signal(SIGQUIT, onsig);
276: (void)signal(SIGTSTP, onsig);
277: (void)signal(SIGTERM, onsig);
278:
279: if (field) {
280: const char *p = field;
281:
282: for (y = LI; --y >= 0;) {
283: for (x = CO; --x >= 0;) {
284: addch(*p++);
285: if (!*p)
286: p = field;
287: }
288: refresh();
289: }
290: }
291: for (;;) {
292: refresh();
293: if (sig_caught) {
294: endwin();
295: exit(0);
296: }
297: if (delay) {
298: if (delay % 1000000 != 0)
299: usleep(delay % 1000000);
300: if (delay >= 1000000)
301: sleep(delay / 1000000);
302: }
303: for (n = 0, w = &worm[0]; n < number; n++, w++) {
304: if ((x = w->xpos[h = w->head]) < 0) {
305: mvaddch(y = w->ypos[h] = bottom,
306: x = w->xpos[h] = 0,
307: flavor[n % sizeof(flavor)]);
308: ref[y][x]++;
309: }
310: else
311: y = w->ypos[h];
312: if (++h == length)
313: h = 0;
314: if (w->xpos[w->head = h] >= 0) {
315: int x1, y1;
316:
317: x1 = w->xpos[h];
318: y1 = w->ypos[h];
319: if (--ref[y1][x1] == 0) {
320: mvaddch(y1, x1, trail);
321: }
322: }
323: op = &(!x ? (!y ? upleft : (y == bottom ? lowleft : left)) : (x == last ? (!y ? upright : (y == bottom ? lowright : right)) : (!y ? upper : (y == bottom ? lower : normal))))[w->orientation];
324: switch (op->nopts) {
325: case 0:
326: refresh();
327: abort();
328: return(1);
329: case 1:
330: w->orientation = op->opts[0];
331: break;
332: default:
333: w->orientation =
334: op->opts[(int)random() % op->nopts];
335: }
336: mvaddch(y += yinc[w->orientation],
337: x += xinc[w->orientation],
338: flavor[n % sizeof(flavor)]);
339: ref[w->ypos[h] = y][w->xpos[h] = x]++;
340: }
341: }
342: }
343:
344: void
345: onsig(signo)
346: int signo __attribute__((__unused__));
347: {
348: sig_caught = 1;
349: }
350:
351: void
352: nomem()
353: {
354: errx(1, "not enough memory.");
355: }