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