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