Initial import from FreeBSD RELENG_4:
[dragonfly.git] / games / worm / worm.c
CommitLineData
984263bc
MD
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
34#ifndef lint
35static const char copyright[] =
36"@(#) Copyright (c) 1980, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41#if 0
42static char sccsid[] = "@(#)worm.c 8.1 (Berkeley) 5/31/93";
43#endif
44static const char rcsid[] =
45 "$FreeBSD: src/games/worm/worm.c,v 1.9 1999/12/07 02:01:27 billf Exp $";
46#endif /* not lint */
47
48/*
49 * Worm. Written by Michael Toy
50 * UCSC
51 */
52
53#include <ctype.h>
54#include <curses.h>
55#include <signal.h>
56#include <stdlib.h>
57#include <termios.h>
58#include <unistd.h>
59
60#define newlink() (struct body *) malloc(sizeof (struct body));
61#define HEAD '@'
62#define BODY 'o'
63#define LENGTH 7
64#define RUNLEN 8
65#define CNTRL(p) (p-'A'+1)
66#if 0
67#ifndef baudrate
68# define baudrate() _tty.sg_ospeed
69#endif
70#endif
71
72WINDOW *tv;
73WINDOW *stw;
74struct body {
75 int x;
76 int y;
77 struct body *prev;
78 struct body *next;
79} *head, *tail, goody;
80int growing = 0;
81int running = 0;
82int slow = 0;
83int score = 0;
84int start_len = LENGTH;
85char lastch;
86char outbuf[BUFSIZ];
87
88void crash __P((void));
89void display __P((struct body *, char));
90void leave __P((int));
91void life __P((void));
92void newpos __P((struct body *));
93void prize __P((void));
94void process __P((char));
95long rnd __P((int));
96void setup __P((void));
97void suspend __P((int));
98void wake __P((int));
99
100int
101main(argc, argv)
102 int argc;
103 char **argv;
104{
105 char ch;
106
107 /* revoke */
108 setgid(getgid());
109
110 if (argc == 2)
111 start_len = atoi(argv[1]);
112 if ((start_len <= 0) || (start_len > 500))
113 start_len = LENGTH;
114 setbuf(stdout, outbuf);
115 srandomdev();
116 signal(SIGALRM, wake);
117 signal(SIGINT, leave);
118 signal(SIGQUIT, leave);
119 signal(SIGTSTP, suspend); /* process control signal */
120 initscr();
121 crmode();
122 noecho();
123 slow = (baudrate() <= B1200);
124 clear();
125 stw = newwin(1, COLS-1, 0, 0);
126 tv = newwin(LINES-1, COLS-1, 1, 0);
127 box(tv, '*', '*');
128 scrollok(tv, FALSE);
129 scrollok(stw, FALSE);
130 wmove(stw, 0, 0);
131 wprintw(stw, " Worm");
132 refresh();
133 wrefresh(stw);
134 wrefresh(tv);
135 life(); /* Create the worm */
136 prize(); /* Put up a goal */
137 while(1)
138 {
139 if (running)
140 {
141 running--;
142 process(lastch);
143 }
144 else
145 {
146 fflush(stdout);
147 if (read(0, &ch, 1) >= 0)
148 process(ch);
149 }
150 }
151}
152
153void
154life()
155{
156 struct body *bp, *np;
157 int i;
158
159 np = NULL;
160 head = newlink();
161 head->x = start_len+2;
162 head->y = 12;
163 head->next = NULL;
164 display(head, HEAD);
165 for (i = 0, bp = head; i < start_len; i++, bp = np) {
166 np = newlink();
167 np->next = bp;
168 bp->prev = np;
169 np->x = bp->x - 1;
170 np->y = bp->y;
171 display(np, BODY);
172 }
173 tail = np;
174 tail->prev = NULL;
175}
176
177void
178display(pos, chr)
179struct body *pos;
180char chr;
181{
182 wmove(tv, pos->y, pos->x);
183 waddch(tv, chr);
184}
185
186void
187leave(sig)
188int sig;
189{
190 endwin();
191 exit(0);
192}
193
194void
195wake(sig)
196int sig;
197{
198 signal(SIGALRM, wake);
199 fflush(stdout);
200 process(lastch);
201}
202
203long
204rnd(range)
205{
206 return random() % range;
207}
208
209void
210newpos(bp)
211struct body * bp;
212{
213 do {
214 bp->y = rnd(LINES-3)+ 2;
215 bp->x = rnd(COLS-3) + 1;
216 wmove(tv, bp->y, bp->x);
217 } while(winch(tv) != ' ');
218}
219
220void
221prize()
222{
223 int value;
224
225 value = rnd(9) + 1;
226 newpos(&goody);
227 waddch(tv, value+'0');
228 wrefresh(tv);
229}
230
231void
232process(ch)
233char ch;
234{
235 int x,y;
236 struct body *nh;
237
238 alarm(0);
239 x = head->x;
240 y = head->y;
241 switch(ch)
242 {
243 case 'h': x--; break;
244 case 'j': y++; break;
245 case 'k': y--; break;
246 case 'l': x++; break;
247 case 'H': x--; running = RUNLEN; ch = tolower(ch); break;
248 case 'J': y++; running = RUNLEN/2; ch = tolower(ch); break;
249 case 'K': y--; running = RUNLEN/2; ch = tolower(ch); break;
250 case 'L': x++; running = RUNLEN; ch = tolower(ch); break;
251 case '\f': setup(); return;
252 case CNTRL('Z'): suspend(0); return;
253 case CNTRL('C'): crash(); return;
254 case CNTRL('D'): crash(); return;
255 default: if (! running) alarm(1);
256 return;
257 }
258 lastch = ch;
259 if (growing == 0)
260 {
261 display(tail, ' ');
262 tail->next->prev = NULL;
263 nh = tail->next;
264 free(tail);
265 tail = nh;
266 }
267 else growing--;
268 display(head, BODY);
269 wmove(tv, y, x);
270 if (isdigit(ch = winch(tv)))
271 {
272 growing += ch-'0';
273 prize();
274 score += growing;
275 running = 0;
276 wmove(stw, 0, 68);
277 wprintw(stw, "Score: %3d", score);
278 wrefresh(stw);
279 }
280 else if(ch != ' ') crash();
281 nh = newlink();
282 nh->next = NULL;
283 nh->prev = head;
284 head->next = nh;
285 nh->y = y;
286 nh->x = x;
287 display(nh, HEAD);
288 head = nh;
289 if (!(slow && running))
290 wrefresh(tv);
291 if (!running)
292 alarm(1);
293}
294
295void
296crash()
297{
298 sleep(2);
299 clear();
300 move(23, 0);
301 refresh();
302 printf("Well, you ran into something and the game is over.\n");
303 printf("Your final score was %d\n", score);
304 leave(0);
305}
306
307void
308suspend(sig)
309int sig;
310{
311 move(LINES-1, 0);
312 refresh();
313 endwin();
314 fflush(stdout);
315 kill(getpid(), SIGTSTP);
316 signal(SIGTSTP, suspend);
317 crmode();
318 noecho();
319 setup();
320}
321
322void
323setup()
324{
325 clear();
326 refresh();
327 touchwin(stw);
328 wrefresh(stw);
329 touchwin(tv);
330 wrefresh(tv);
331 alarm(1);
332}