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