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