Bring in some CAM bug fixes from FreeBSD.
[dragonfly.git] / games / worm / worm.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
34 * @(#)worm.c 8.1 (Berkeley) 5/31/93
35 * $FreeBSD: src/games/worm/worm.c,v 1.9 1999/12/07 02:01:27 billf Exp $
36 * $DragonFly: src/games/worm/worm.c,v 1.3 2003/11/12 14:53:54 eirikn Exp $
37 */
38
39/*
40 * Worm. Written by Michael Toy
41 * UCSC
42 */
43
44#include <ctype.h>
45#include <curses.h>
46#include <signal.h>
47#include <stdlib.h>
48#include <termios.h>
49#include <unistd.h>
50
51#define newlink() (struct body *) malloc(sizeof (struct body));
52#define HEAD '@'
53#define BODY 'o'
54#define LENGTH 7
55#define RUNLEN 8
56#define CNTRL(p) (p-'A'+1)
57#if 0
58#ifndef baudrate
59# define baudrate() _tty.sg_ospeed
60#endif
61#endif
62
63WINDOW *tv;
64WINDOW *stw;
65struct body {
66 int x;
67 int y;
68 struct body *prev;
69 struct body *next;
70} *head, *tail, goody;
71int growing = 0;
72int running = 0;
73int slow = 0;
74int score = 0;
75int start_len = LENGTH;
76char lastch;
77char outbuf[BUFSIZ];
78
79void crash (void);
80void display (struct body *, char);
81void leave (int);
82void life (void);
83void newpos (struct body *);
84void prize (void);
85void process (char);
86long rnd (int);
87void setup (void);
88void suspend (int);
89void wake (int);
90
91int
92main(argc, argv)
93 int argc;
94 char **argv;
95{
96 char ch;
97
98 /* revoke */
99 setgid(getgid());
100
101 if (argc == 2)
102 start_len = atoi(argv[1]);
103 if ((start_len <= 0) || (start_len > 500))
104 start_len = LENGTH;
105 setbuf(stdout, outbuf);
106 srandomdev();
107 signal(SIGALRM, wake);
108 signal(SIGINT, leave);
109 signal(SIGQUIT, leave);
110 signal(SIGTSTP, suspend); /* process control signal */
111 initscr();
112 crmode();
113 noecho();
114 slow = (baudrate() <= B1200);
115 clear();
116 stw = newwin(1, COLS-1, 0, 0);
117 tv = newwin(LINES-1, COLS-1, 1, 0);
118 box(tv, '*', '*');
119 scrollok(tv, FALSE);
120 scrollok(stw, FALSE);
121 wmove(stw, 0, 0);
122 wprintw(stw, " Worm");
123 refresh();
124 wrefresh(stw);
125 wrefresh(tv);
126 life(); /* Create the worm */
127 prize(); /* Put up a goal */
128 while(1)
129 {
130 if (running)
131 {
132 running--;
133 process(lastch);
134 }
135 else
136 {
137 fflush(stdout);
138 if (read(0, &ch, 1) >= 0)
139 process(ch);
140 }
141 }
142}
143
144void
145life()
146{
147 struct body *bp, *np;
148 int i;
149
150 np = NULL;
151 head = newlink();
152 head->x = start_len+2;
153 head->y = 12;
154 head->next = NULL;
155 display(head, HEAD);
156 for (i = 0, bp = head; i < start_len; i++, bp = np) {
157 np = newlink();
158 np->next = bp;
159 bp->prev = np;
160 np->x = bp->x - 1;
161 np->y = bp->y;
162 display(np, BODY);
163 }
164 tail = np;
165 tail->prev = NULL;
166}
167
168void
169display(pos, chr)
170struct body *pos;
171char chr;
172{
173 wmove(tv, pos->y, pos->x);
174 waddch(tv, chr);
175}
176
177void
178leave(sig)
179int sig;
180{
181 endwin();
182 exit(0);
183}
184
185void
186wake(sig)
187int sig;
188{
189 signal(SIGALRM, wake);
190 fflush(stdout);
191 process(lastch);
192}
193
194long
195rnd(range)
196{
197 return random() % range;
198}
199
200void
201newpos(bp)
202struct body * bp;
203{
204 do {
205 bp->y = rnd(LINES-3)+ 2;
206 bp->x = rnd(COLS-3) + 1;
207 wmove(tv, bp->y, bp->x);
208 } while(winch(tv) != ' ');
209}
210
211void
212prize()
213{
214 int value;
215
216 value = rnd(9) + 1;
217 newpos(&goody);
218 waddch(tv, value+'0');
219 wrefresh(tv);
220}
221
222void
223process(ch)
224char ch;
225{
226 int x,y;
227 struct body *nh;
228
229 alarm(0);
230 x = head->x;
231 y = head->y;
232 switch(ch)
233 {
234 case 'h': x--; break;
235 case 'j': y++; break;
236 case 'k': y--; break;
237 case 'l': x++; break;
238 case 'H': x--; running = RUNLEN; ch = tolower(ch); break;
239 case 'J': y++; running = RUNLEN/2; ch = tolower(ch); break;
240 case 'K': y--; running = RUNLEN/2; ch = tolower(ch); break;
241 case 'L': x++; running = RUNLEN; ch = tolower(ch); break;
242 case '\f': setup(); return;
243 case CNTRL('Z'): suspend(0); return;
244 case CNTRL('C'): crash(); return;
245 case CNTRL('D'): crash(); return;
246 default: if (! running) alarm(1);
247 return;
248 }
249 lastch = ch;
250 if (growing == 0)
251 {
252 display(tail, ' ');
253 tail->next->prev = NULL;
254 nh = tail->next;
255 free(tail);
256 tail = nh;
257 }
258 else growing--;
259 display(head, BODY);
260 wmove(tv, y, x);
261 if (isdigit(ch = winch(tv)))
262 {
263 growing += ch-'0';
264 prize();
265 score += growing;
266 running = 0;
267 wmove(stw, 0, 68);
268 wprintw(stw, "Score: %3d", score);
269 wrefresh(stw);
270 }
271 else if(ch != ' ') crash();
272 nh = newlink();
273 nh->next = NULL;
274 nh->prev = head;
275 head->next = nh;
276 nh->y = y;
277 nh->x = x;
278 display(nh, HEAD);
279 head = nh;
280 if (!(slow && running))
281 wrefresh(tv);
282 if (!running)
283 alarm(1);
284}
285
286void
287crash()
288{
289 sleep(2);
290 clear();
291 move(23, 0);
292 refresh();
293 printf("Well, you ran into something and the game is over.\n");
294 printf("Your final score was %d\n", score);
295 leave(0);
296}
297
298void
299suspend(sig)
300int sig;
301{
302 move(LINES-1, 0);
303 refresh();
304 endwin();
305 fflush(stdout);
306 kill(getpid(), SIGTSTP);
307 signal(SIGTSTP, suspend);
308 crmode();
309 noecho();
310 setup();
311}
312
313void
314setup()
315{
316 clear();
317 refresh();
318 touchwin(stw);
319 wrefresh(stw);
320 touchwin(tv);
321 wrefresh(tv);
322 alarm(1);
323}