Drop main() prototype. Syncs with NetBSD-8
[minix.git] / games / worm / worm.c
blob225ed0a1f6c0819bd2b9cf39dc02366da3ee5418
1 /* $NetBSD: worm.c,v 1.31 2015/08/17 17:17:01 dholland Exp $ */
3 /*
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
35 The Regents of the University of California. All rights reserved.");
36 #endif /* not lint */
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)worm.c 8.1 (Berkeley) 5/31/93";
41 #else
42 __RCSID("$NetBSD: worm.c,v 1.31 2015/08/17 17:17:01 dholland Exp $");
43 #endif
44 #endif /* not lint */
47 * Worm. Written by Michael Toy
48 * UCSC
51 #include <ctype.h>
52 #include <curses.h>
53 #include <err.h>
54 #include <signal.h>
55 #include <stdlib.h>
56 #include <termios.h>
57 #include <unistd.h>
59 #define HEAD '@'
60 #define BODY 'o'
61 #define LENGTH 7
62 #define RUNLEN 8
63 #define CNTRL(p) (p-'A'+1)
65 struct body {
66 int x;
67 int y;
68 struct body *prev;
69 struct body *next;
72 static WINDOW *tv;
73 static WINDOW *stw;
74 static struct body *head, *tail, goody;
75 static int growing = 0;
76 static int running = 0;
77 static int slow = 0;
78 static int score = 0;
79 static int start_len = LENGTH;
80 static int visible_len;
81 static int lastch;
82 static char outbuf[BUFSIZ];
84 int main(int, char **);
85 static void crash(void) __dead;
86 static void display(const struct body *, char);
87 static void leave(int) __dead;
88 static void life(void);
89 static void newpos(struct body *);
90 static void process(int);
91 static void prize(void);
92 static int rnd(int);
93 static void setup(void);
94 static void wake(int);
96 static struct body *
97 newlink(void)
99 struct body *b;
101 b = malloc(sizeof(*b));
102 if (b == NULL) {
103 err(EXIT_FAILURE, NULL);
105 return b;
109 main(int argc, char **argv)
112 /* Revoke setgid privileges */
113 setgid(getgid());
115 setbuf(stdout, outbuf);
116 srand(getpid());
117 signal(SIGALRM, wake);
118 signal(SIGINT, leave);
119 signal(SIGQUIT, leave);
120 if (!initscr())
121 errx(0, "couldn't initialize screen");
122 cbreak();
123 noecho();
124 #ifdef KEY_LEFT
125 keypad(stdscr, TRUE);
126 #endif
127 slow = (baudrate() <= 1200);
128 clear();
129 if (COLS < 18 || LINES < 5) {
131 * Insufficient room for the line with " Worm" and the
132 * score if fewer than 18 columns; insufficient room for
133 * anything much if fewer than 5 lines.
135 endwin();
136 errx(1, "screen too small");
138 if (argc == 2)
139 start_len = atoi(argv[1]);
140 if ((start_len <= 0) || (start_len > ((LINES-3) * (COLS-2)) / 3))
141 start_len = LENGTH;
142 stw = newwin(1, COLS-1, 0, 0);
143 tv = newwin(LINES-1, COLS-1, 1, 0);
144 box(tv, '*', '*');
145 scrollok(tv, FALSE);
146 scrollok(stw, FALSE);
147 wmove(stw, 0, 0);
148 wprintw(stw, " Worm");
149 refresh();
150 wrefresh(stw);
151 wrefresh(tv);
152 life(); /* Create the worm */
153 prize(); /* Put up a goal */
154 while(1)
156 if (running)
158 running--;
159 process(lastch);
161 else
163 fflush(stdout);
164 process(getch());
169 static void
170 life(void)
172 struct body *bp, *np;
173 int i, j = 1;
175 np = NULL;
176 head = newlink();
177 head->x = start_len % (COLS-5) + 2;
178 head->y = LINES / 2;
179 head->next = NULL;
180 display(head, HEAD);
181 for (i = 0, bp = head; i < start_len; i++, bp = np) {
182 np = newlink();
183 np->next = bp;
184 bp->prev = np;
185 if (((bp->x <= 2) && (j == 1)) || ((bp->x >= COLS-4) && (j == -1))) {
186 j *= -1;
187 np->x = bp->x;
188 np->y = bp->y + 1;
189 } else {
190 np->x = bp->x - j;
191 np->y = bp->y;
193 display(np, BODY);
195 tail = np;
196 tail->prev = NULL;
197 visible_len = start_len + 1;
200 static void
201 display(const struct body *pos, char chr)
203 wmove(tv, pos->y, pos->x);
204 waddch(tv, chr);
207 static void
208 leave(int dummy)
210 endwin();
212 if (dummy == 0){ /* called via crash() */
213 printf("\nWell, you ran into something and the game is over.\n");
214 printf("Your final score was %d\n\n", score);
216 exit(0);
219 static void
220 wake(int dummy)
222 signal(SIGALRM, wake);
223 fflush(stdout);
224 process(lastch);
227 static int
228 rnd(int range)
230 return abs((rand()>>5)+(rand()>>5)) % range;
233 static void
234 newpos(struct body *bp)
236 if (visible_len == (LINES-3) * (COLS-3) - 1) {
237 endwin();
239 printf("\nYou won!\n");
240 printf("Your final score was %d\n\n", score);
241 exit(0);
243 do {
244 bp->y = rnd(LINES-3)+ 1;
245 bp->x = rnd(COLS-3) + 1;
246 wmove(tv, bp->y, bp->x);
247 } while(winch(tv) != ' ');
250 static void
251 prize(void)
253 int value;
255 value = rnd(9) + 1;
256 newpos(&goody);
257 waddch(tv, value+'0');
258 wrefresh(tv);
261 static void
262 process(int ch)
264 int x,y;
265 struct body *nh;
267 alarm(0);
268 x = head->x;
269 y = head->y;
270 switch(ch)
272 #ifdef KEY_LEFT
273 case KEY_LEFT:
274 #endif
275 case 'h':
276 x--; break;
278 #ifdef KEY_DOWN
279 case KEY_DOWN:
280 #endif
281 case 'j':
282 y++; break;
284 #ifdef KEY_UP
285 case KEY_UP:
286 #endif
287 case 'k':
288 y--; break;
290 #ifdef KEY_RIGHT
291 case KEY_RIGHT:
292 #endif
293 case 'l':
294 x++; break;
296 case 'H': x--; running = RUNLEN; ch = tolower(ch); break;
297 case 'J': y++; running = RUNLEN/2; ch = tolower(ch); break;
298 case 'K': y--; running = RUNLEN/2; ch = tolower(ch); break;
299 case 'L': x++; running = RUNLEN; ch = tolower(ch); break;
300 case '\f': setup(); return;
302 case ERR:
303 case CNTRL('C'):
304 case CNTRL('D'):
305 crash();
306 return;
308 default: if (! running) alarm(1);
309 return;
311 lastch = ch;
312 if (growing == 0)
314 display(tail, ' ');
315 tail->next->prev = NULL;
316 nh = tail->next;
317 free(tail);
318 tail = nh;
319 visible_len--;
321 else growing--;
322 display(head, BODY);
323 wmove(tv, y, x);
324 if (isdigit(ch = winch(tv)))
326 growing += ch-'0';
327 prize();
328 score += growing;
329 running = 0;
330 wmove(stw, 0, COLS - 12);
331 wprintw(stw, "Score: %3d", score);
332 wrefresh(stw);
334 else if(ch != ' ') crash();
335 nh = newlink();
336 nh->next = NULL;
337 nh->prev = head;
338 head->next = nh;
339 nh->y = y;
340 nh->x = x;
341 display(nh, HEAD);
342 head = nh;
343 visible_len++;
344 if (!(slow && running))
346 wmove(tv, head->y, head->x);
347 wrefresh(tv);
349 if (!running)
350 alarm(1);
353 static void
354 crash(void)
356 leave(0);
359 static void
360 setup(void)
362 clear();
363 refresh();
364 touchwin(stw);
365 wrefresh(stw);
366 touchwin(tv);
367 wrefresh(tv);
368 alarm(1);