xref: /original-bsd/games/worms/worms.c (revision 8ac030d2)
1 
2 static 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)
24 outc(c)
25 {
26 	putchar(c);
27 }
28 extern char *UP;
29 extern short ospeed;
30 int Wrap;
31 short *ref[24];
32 static char flavor[]={
33     'O', '*', '#', '$', '%', '0'
34 };
35 static short xinc[]={
36      1,  1,  1,  0, -1, -1, -1,  0
37 }, yinc[]={
38     -1,  0,  1,  1,  1,  0, -1, -1
39 };
40 static struct worm {
41     int orientation, head;
42     short *xpos, *ypos;
43 } worm[40];
44 static char *field;
45 static int length=16, number=3, trail=' ';
46 static 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 };
131 main(argc,argv)
132 int argc;
133 char *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 }
323 fputchar(c)
324 char c;
325 {
326     putchar(c);
327 }
328 float ranf() {
329     return((float)rand()/2147483647.);
330 }
331