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