remove .ARPA hack; breaks with domain names
[unix-history] / usr / src / games / worms / worms.c
CommitLineData
e0bbfbf9
DF
1#ifndef lint
2char copyright[] =
3"@(#) Copyright (c) 1980 Regents of the University of California.\n\
4 All rights reserved.\n";
5#endif not lint
5111e40b 6
e0bbfbf9 7#ifndef lint
78471213 8static char sccsid[] = "@(#)worms.c 5.2 (Berkeley) %G%";
e0bbfbf9 9#endif not lint
5111e40b
KM
10
11/*
12
13 @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
14 @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
15 @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
16 @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
17 @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
18 @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
19 @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
20 @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
21 @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
22
23 Eric P. Scott
24 Caltech High Energy Physics
25 October, 1980
26
27*/
28#include <stdio.h>
29#include <sgtty.h>
30#define cursor(col,row) tputs(tgoto(CM,col,row),1,outc)
31outc(c)
32{
33 putchar(c);
34}
35extern char *UP;
36extern short ospeed;
37int Wrap;
38short *ref[24];
39static char flavor[]={
40 'O', '*', '#', '$', '%', '0'
41};
42static short xinc[]={
43 1, 1, 1, 0, -1, -1, -1, 0
44}, yinc[]={
45 -1, 0, 1, 1, 1, 0, -1, -1
46};
47static struct worm {
48 int orientation, head;
49 short *xpos, *ypos;
50} worm[40];
51static char *field;
52static int length=16, number=3, trail=' ';
53static struct options {
54 int nopts;
55 int opts[3];
56} normal[8]={
57 { 3, { 7, 0, 1 } },
58 { 3, { 0, 1, 2 } },
59 { 3, { 1, 2, 3 } },
60 { 3, { 2, 3, 4 } },
61 { 3, { 3, 4, 5 } },
62 { 3, { 4, 5, 6 } },
63 { 3, { 5, 6, 7 } },
64 { 3, { 6, 7, 0 } }
65}, upper[8]={
66 { 1, { 1, 0, 0 } },
67 { 2, { 1, 2, 0 } },
68 { 0, { 0, 0, 0 } },
69 { 0, { 0, 0, 0 } },
70 { 0, { 0, 0, 0 } },
71 { 2, { 4, 5, 0 } },
72 { 1, { 5, 0, 0 } },
73 { 2, { 1, 5, 0 } }
74}, left[8]={
75 { 0, { 0, 0, 0 } },
76 { 0, { 0, 0, 0 } },
77 { 0, { 0, 0, 0 } },
78 { 2, { 2, 3, 0 } },
79 { 1, { 3, 0, 0 } },
80 { 2, { 3, 7, 0 } },
81 { 1, { 7, 0, 0 } },
82 { 2, { 7, 0, 0 } }
83}, right[8]={
84 { 1, { 7, 0, 0 } },
85 { 2, { 3, 7, 0 } },
86 { 1, { 3, 0, 0 } },
87 { 2, { 3, 4, 0 } },
88 { 0, { 0, 0, 0 } },
89 { 0, { 0, 0, 0 } },
90 { 0, { 0, 0, 0 } },
91 { 2, { 6, 7, 0 } }
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}, upleft[8]={
102 { 0, { 0, 0, 0 } },
103 { 0, { 0, 0, 0 } },
104 { 0, { 0, 0, 0 } },
105 { 0, { 0, 0, 0 } },
106 { 0, { 0, 0, 0 } },
107 { 1, { 3, 0, 0 } },
108 { 2, { 1, 3, 0 } },
109 { 1, { 1, 0, 0 } }
110}, upright[8]={
111 { 2, { 3, 5, 0 } },
112 { 1, { 3, 0, 0 } },
113 { 0, { 0, 0, 0 } },
114 { 0, { 0, 0, 0 } },
115 { 0, { 0, 0, 0 } },
116 { 0, { 0, 0, 0 } },
117 { 0, { 0, 0, 0 } },
118 { 1, { 5, 0, 0 } }
119}, lowleft[8]={
120 { 3, { 7, 0, 1 } },
121 { 0, { 0, 0, 0 } },
122 { 0, { 0, 0, 0 } },
123 { 1, { 1, 0, 0 } },
124 { 2, { 1, 7, 0 } },
125 { 1, { 7, 0, 0 } },
126 { 0, { 0, 0, 0 } },
127 { 0, { 0, 0, 0 } }
128}, lowright[8]={
129 { 0, { 0, 0, 0 } },
130 { 1, { 7, 0, 0 } },
131 { 2, { 5, 7, 0 } },
132 { 1, { 5, 0, 0 } },
133 { 0, { 0, 0, 0 } },
134 { 0, { 0, 0, 0 } },
135 { 0, { 0, 0, 0 } },
136 { 0, { 0, 0, 0 } }
137};
138main(argc,argv)
139int argc;
140char *argv[];
141{
142 extern fputchar();
143 char *malloc();
144 char *getenv();
145 char *tgetstr(), *tgoto();
146 float ranf();
147 register int x, y;
148 register int n;
149 register struct worm *w;
150 register struct options *op;
151 register int h;
152 register short *ip;
153 char *AL, *BC, *CM, *EI, *HO, *IC, *IM, *IP, *SR;
154 int CO, IN, LI, last, bottom;
155 char *tcp;
156 register char *term;
157 char tcb[100];
158 struct sgttyb sg;
159 setbuf(stdout,malloc(BUFSIZ));
160 for (x=1;x<argc;x++) {
161 register char *p;
162 p=argv[x];
163 if (*p=='-') p++;
164 switch (*p) {
165 case 'f':
166 field="WORM";
167 break;
168 case 'l':
169 if (++x==argc) goto usage;
170 if ((length=atoi(argv[x]))<2||length>1024) {
171 fprintf(stderr,"%s: Invalid length\n",*argv);
172 exit(1);
173 }
174 break;
175 case 'n':
176 if (++x==argc) goto usage;
177 if ((number=atoi(argv[x]))<1||number>40) {
178 fprintf(stderr,"%s: Invalid number of worms\n",*argv);
179 exit(1);
180 }
181 break;
182 case 't':
183 trail='.';
184 break;
185 default:
186 usage:
187 fprintf(stderr,
188 "usage: %s [-field] [-length #] [-number #] [-trail]\n",*argv);
189 exit(1);
190 break;
191 }
192 }
193 if (!(term=getenv("TERM"))) {
194 fprintf(stderr,"%s: TERM: parameter not set\n",*argv);
195 exit(1);
196 }
197 if (tgetent(malloc(1024),term)<=0) {
198 fprintf(stderr,"%s: %s: unknown terminal type\n",*argv,term);
199 exit(1);
200 }
201 tcp=tcb;
202 if (!(CM=tgetstr("cm",&tcp))) {
203 fprintf(stderr,"%s: terminal not capable of cursor motion\n",*argv);
204 exit(1);
205 }
206 AL=tgetstr("al",&tcp);
207 BC=tgetflag("bs") ? "\b" : tgetstr("bc",&tcp);
208 if ((CO=tgetnum("co"))<=0) CO=80;
209 last=CO-1;
210 EI=tgetstr("ei",&tcp);
211 HO=tgetstr("ho",&tcp);
212 IC=tgetstr("ic",&tcp);
213 IM=tgetstr("im",&tcp);
214 IN=tgetflag("in");
215 IP=tgetstr("ip",&tcp);
216 if ((LI=tgetnum("li"))<=0) LI=24;
217 bottom=LI-1;
218 SR=tgetstr("sr",&tcp);
219 UP=tgetstr("up",&tcp);
220 gtty(fileno(stdout),&sg);
221 ospeed=sg.sg_ospeed;
222 Wrap=tgetflag("am");
223 ip=(short *)malloc(LI*CO*sizeof (short));
224 for (n=0;n<LI;) {
225 ref[n++]=ip; ip+=CO;
226 }
227 for (ip=ref[0],n=LI*CO;--n>=0;) *ip++=0;
228 if (Wrap) ref[bottom][last]=1;
229 for (n=number, w= &worm[0];--n>=0;w++) {
230 w->orientation=w->head=0;
231 if (!(ip=(short *)malloc(length*sizeof (short)))) {
232 fprintf(stderr,"%s: out of memory\n",*argv);
233 exit(1);
234 }
235 w->xpos=ip;
236 for (x=length;--x>=0;) *ip++ = -1;
237 if (!(ip=(short *)malloc(length*sizeof (short)))) {
238 fprintf(stderr,"%s: out of memory\n",*argv);
239 exit(1);
240 }
241 w->ypos=ip;
242 for (y=length;--y>=0;) *ip++ = -1;
243 }
244 tputs(tgetstr("cl",&tcp),1,fputchar);
245 if (field) {
246 register char *p;
247 p=field;
248 for (y=bottom;--y>=0;) {
249 for (x=CO;--x>=0;) {
250 putchar(*p++);
251 if (!*p) p=field;
252 }
253 if (!Wrap) putchar('\n');
254 fflush(stdout);
255 }
256 if (Wrap) {
257 if (IM&&!IN) {
258 for (x=last;--x>0;) {
259 putchar(*p++);
260 if (!*p) p=field;
261 }
262 y= *p++; if (!*p) p=field;
263 putchar(*p);
264 if (BC) fputs(BC,stdout);
265 else cursor(last-1,bottom);
266 fputs(IM,stdout);
267 if (IC) tputs(IC,1,fputchar);
268 putchar(y);
269 if (IP) tputs(IP,1,fputchar);
270 fputs(EI,stdout);
271 }
272 else if (SR||AL) {
273 if (HO) fputs(HO,stdout);
274 else cursor(0,0);
275 if (SR) tputs(SR,1,fputchar);
276 else tputs(AL,LI,fputchar);
277 for (x=CO;--x>=0;) {
278 putchar(*p++);
279 if (!*p) p=field;
280 }
281 }
282 else for (x=last;--x>=0;) {
283 putchar(*p++);
284 if (!*p) p=field;
285 }
286 }
287 else for (x=CO;--x>=0;) {
288 putchar(*p++);
289 if (!*p) p=field;
290 }
291 }
292 fflush(stdout);
293 for (;;) {
294 for (n=0,w= &worm[0];n<number;n++,w++) {
295 if ((x=w->xpos[h=w->head])<0) {
296 cursor(x=w->xpos[h]=0,y=w->ypos[h]=bottom);
297 putchar(flavor[n%6]);
298 ref[y][x]++;
299 }
300 else y=w->ypos[h];
301 if (++h==length) h=0;
302 if (w->xpos[w->head=h]>=0) {
303 register int x1, y1;
304 x1=w->xpos[h]; y1=w->ypos[h];
305 if (--ref[y1][x1]==0) {
306 cursor(x1,y1); putchar(trail);
307 }
308 }
309 op= &(x==0 ? (y==0 ? upleft : (y==bottom ? lowleft : left)) :
310 (x==last ? (y==0 ? upright : (y==bottom ? lowright : right)) :
311 (y==0 ? upper : (y==bottom ? lower : normal))))[w->orientation];
312 switch (op->nopts) {
313 case 0:
314 fflush(stdout);
315 abort();
316 return;
317 case 1:
318 w->orientation=op->opts[0];
319 break;
320 default:
321 w->orientation=op->opts[(int)(ranf()*(float)op->nopts)];
322 }
323 cursor(x+=xinc[w->orientation], y+=yinc[w->orientation]);
324 if (!Wrap||x!=last||y!=bottom) putchar(flavor[n%6]);
325 ref[w->ypos[h]=y][w->xpos[h]=x]++;
326 }
327 fflush(stdout);
328 }
329}
330fputchar(c)
331char c;
332{
333 putchar(c);
334}
335float ranf() {
336 return((float)rand()/2147483647.);
337}