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