cleanup, add manual page
[unix-history] / usr / src / games / worm / worm.c
CommitLineData
e0bbfbf9
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
c54d1a23
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
f4f66d2c
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
e0bbfbf9
DF
16 */
17
18#ifndef lint
19char copyright[] =
20"@(#) Copyright (c) 1980 Regents of the University of California.\n\
21 All rights reserved.\n";
c54d1a23 22#endif /* not lint */
e0bbfbf9
DF
23
24#ifndef lint
f4f66d2c 25static char sccsid[] = "@(#)worm.c 5.5 (Berkeley) %G%";
c54d1a23 26#endif /* not lint */
c4e6edfa
KM
27
28/*
29 * Worm. Written by Michael Toy
30 * UCSC
31 */
32
33#include <ctype.h>
34#include <curses.h>
35#include <signal.h>
36
37#define newlink() (struct body *) malloc(sizeof (struct body));
38#define HEAD '@'
39#define BODY 'o'
40#define LENGTH 7
41#define RUNLEN 8
42#define when break;case
43#define otherwise break;default
3831612d 44#define CNTRL(p) (p-'A'+1)
aba3284a 45#ifndef baudrate
73ead3d6
KA
46# define baudrate() _tty.sg_ospeed
47#endif
c4e6edfa
KM
48
49WINDOW *tv;
50WINDOW *stw;
51struct body {
52 int x;
53 int y;
54 struct body *prev;
55 struct body *next;
56} *head, *tail, goody;
57int growing = 0;
58int running = 0;
73ead3d6 59int slow = 0;
c4e6edfa
KM
60int score = 0;
61int start_len = LENGTH;
62char lastch;
63char outbuf[BUFSIZ];
64
65main(argc, argv)
66char **argv;
67{
68 int leave(), wake(), suspend();
69 char ch;
70
71 if (argc == 2)
72 start_len = atoi(argv[1]);
73 if ((start_len <= 0) || (start_len > 500))
74 start_len = LENGTH;
75 setbuf(stdout, outbuf);
76 srand(getpid());
77 signal(SIGALRM, wake);
78 signal(SIGINT, leave);
79 signal(SIGQUIT, leave);
80#ifdef SIGTSTP
81 signal(SIGTSTP, suspend); /* process control signal */
82#endif
83 initscr();
84 crmode();
85 noecho();
73ead3d6 86 slow = (baudrate() <= B1200);
c4e6edfa
KM
87 clear();
88 stw = newwin(1, COLS-1, 0, 0);
89 tv = newwin(LINES-1, COLS-1, 1, 0);
90 box(tv, '*', '*');
91 scrollok(tv, FALSE);
92 scrollok(stw, FALSE);
93 wmove(stw, 0, 0);
94 wprintw(stw, " Worm");
95 refresh();
96 wrefresh(stw);
97 wrefresh(tv);
98 life(); /* Create the worm */
99 prize(); /* Put up a goal */
100 while(1)
101 {
102 if (running)
103 {
104 running--;
105 process(lastch);
106 }
107 else
108 {
109 fflush(stdout);
110 if (read(0, &ch, 1) >= 0)
111 process(ch);
112 }
113 }
114}
115
116life()
117{
118 register struct body *bp, *np;
119 register int i;
120
121 head = newlink();
122 head->x = start_len+2;
123 head->y = 12;
124 head->next = NULL;
125 display(head, HEAD);
126 for (i = 0, bp = head; i < start_len; i++, bp = np) {
127 np = newlink();
128 np->next = bp;
129 bp->prev = np;
130 np->x = bp->x - 1;
131 np->y = bp->y;
132 display(np, BODY);
133 }
134 tail = np;
135 tail->prev = NULL;
c4e6edfa
KM
136}
137
138display(pos, chr)
139struct body *pos;
140char chr;
141{
142 wmove(tv, pos->y, pos->x);
143 waddch(tv, chr);
144}
145
146leave()
147{
148 endwin();
149 exit(0);
150}
151
152wake()
153{
154 signal(SIGALRM, wake);
155 fflush(stdout);
156 process(lastch);
157}
158
159rnd(range)
160{
161 return abs((rand()>>5)+(rand()>>5)) % range;
162}
163
164newpos(bp)
165struct body * bp;
166{
167 do {
168 bp->y = rnd(LINES-3)+ 2;
169 bp->x = rnd(COLS-3) + 1;
170 wmove(tv, bp->y, bp->x);
171 } while(winch(tv) != ' ');
172}
173
174prize()
175{
176 int value;
177
178 value = rnd(9) + 1;
179 newpos(&goody);
180 waddch(tv, value+'0');
181 wrefresh(tv);
182}
183
184process(ch)
185char ch;
186{
187 register int x,y;
188 struct body *nh;
189
190 alarm(0);
191 x = head->x;
192 y = head->y;
193 switch(ch)
194 {
195 when 'h': x--;
196 when 'j': y++;
197 when 'k': y--;
198 when 'l': x++;
199 when 'H': x--; running = RUNLEN; ch = tolower(ch);
200 when 'J': y++; running = RUNLEN/2; ch = tolower(ch);
201 when 'K': y--; running = RUNLEN/2; ch = tolower(ch);
202 when 'L': x++; running = RUNLEN; ch = tolower(ch);
203 when '\f': setup(); return;
3831612d
KB
204 when CNTRL('Z'): suspend(); return;
205 when CNTRL('C'): crash(); return;
206 when CNTRL('D'): crash(); return;
c4e6edfa
KM
207 otherwise: if (! running) alarm(1);
208 return;
209 }
210 lastch = ch;
211 if (growing == 0)
212 {
213 display(tail, ' ');
214 tail->next->prev = NULL;
215 nh = tail->next;
216 free(tail);
217 tail = nh;
218 }
219 else growing--;
220 display(head, BODY);
221 wmove(tv, y, x);
222 if (isdigit(ch = winch(tv)))
223 {
224 growing += ch-'0';
225 prize();
226 score += growing;
227 running = 0;
228 wmove(stw, 0, 68);
229 wprintw(stw, "Score: %3d", score);
230 wrefresh(stw);
231 }
232 else if(ch != ' ') crash();
233 nh = newlink();
234 nh->next = NULL;
235 nh->prev = head;
236 head->next = nh;
237 nh->y = y;
238 nh->x = x;
239 display(nh, HEAD);
240 head = nh;
73ead3d6
KA
241 if (!(slow && running))
242 wrefresh(tv);
243 if (!running)
244 alarm(1);
c4e6edfa
KM
245}
246
247crash()
248{
249 sleep(2);
250 clear();
251 move(23, 0);
252 refresh();
253 printf("Well you ran into something and the game is over.\n");
254 printf("Your final score was %d\n", score);
255 leave();
256}
257
258suspend()
259{
260 char *sh;
261
262 move(LINES-1, 0);
263 refresh();
264 endwin();
265 fflush(stdout);
266#ifdef SIGTSTP
267 kill(getpid(), SIGTSTP);
268 signal(SIGTSTP, suspend);
269#else
270 sh = getenv("SHELL");
271 if (sh == NULL)
272 sh = "/bin/sh";
273 system(sh);
274#endif
275 crmode();
276 noecho();
277 setup();
278}
279
280setup()
281{
282 clear();
283 refresh();
284 touchwin(stw);
285 wrefresh(stw);
286 touchwin(tv);
287 wrefresh(tv);
288 alarm(1);
289}