date and time created 90/06/01 13:17:44 by bostic
[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
fd35ae3d 25static char sccsid[] = "@(#)worm.c 5.6 (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);
c4e6edfa 80 signal(SIGTSTP, suspend); /* process control signal */
c4e6edfa
KM
81 initscr();
82 crmode();
83 noecho();
73ead3d6 84 slow = (baudrate() <= B1200);
c4e6edfa
KM
85 clear();
86 stw = newwin(1, COLS-1, 0, 0);
87 tv = newwin(LINES-1, COLS-1, 1, 0);
88 box(tv, '*', '*');
89 scrollok(tv, FALSE);
90 scrollok(stw, FALSE);
91 wmove(stw, 0, 0);
92 wprintw(stw, " Worm");
93 refresh();
94 wrefresh(stw);
95 wrefresh(tv);
96 life(); /* Create the worm */
97 prize(); /* Put up a goal */
98 while(1)
99 {
100 if (running)
101 {
102 running--;
103 process(lastch);
104 }
105 else
106 {
107 fflush(stdout);
108 if (read(0, &ch, 1) >= 0)
109 process(ch);
110 }
111 }
112}
113
114life()
115{
116 register struct body *bp, *np;
117 register int i;
118
119 head = newlink();
120 head->x = start_len+2;
121 head->y = 12;
122 head->next = NULL;
123 display(head, HEAD);
124 for (i = 0, bp = head; i < start_len; i++, bp = np) {
125 np = newlink();
126 np->next = bp;
127 bp->prev = np;
128 np->x = bp->x - 1;
129 np->y = bp->y;
130 display(np, BODY);
131 }
132 tail = np;
133 tail->prev = NULL;
c4e6edfa
KM
134}
135
136display(pos, chr)
137struct body *pos;
138char chr;
139{
140 wmove(tv, pos->y, pos->x);
141 waddch(tv, chr);
142}
143
144leave()
145{
146 endwin();
147 exit(0);
148}
149
150wake()
151{
152 signal(SIGALRM, wake);
153 fflush(stdout);
154 process(lastch);
155}
156
157rnd(range)
158{
159 return abs((rand()>>5)+(rand()>>5)) % range;
160}
161
162newpos(bp)
163struct body * bp;
164{
165 do {
166 bp->y = rnd(LINES-3)+ 2;
167 bp->x = rnd(COLS-3) + 1;
168 wmove(tv, bp->y, bp->x);
169 } while(winch(tv) != ' ');
170}
171
172prize()
173{
174 int value;
175
176 value = rnd(9) + 1;
177 newpos(&goody);
178 waddch(tv, value+'0');
179 wrefresh(tv);
180}
181
182process(ch)
183char ch;
184{
185 register int x,y;
186 struct body *nh;
187
188 alarm(0);
189 x = head->x;
190 y = head->y;
191 switch(ch)
192 {
193 when 'h': x--;
194 when 'j': y++;
195 when 'k': y--;
196 when 'l': x++;
197 when 'H': x--; running = RUNLEN; ch = tolower(ch);
198 when 'J': y++; running = RUNLEN/2; ch = tolower(ch);
199 when 'K': y--; running = RUNLEN/2; ch = tolower(ch);
200 when 'L': x++; running = RUNLEN; ch = tolower(ch);
201 when '\f': setup(); return;
3831612d
KB
202 when CNTRL('Z'): suspend(); return;
203 when CNTRL('C'): crash(); return;
204 when CNTRL('D'): crash(); return;
c4e6edfa
KM
205 otherwise: if (! running) alarm(1);
206 return;
207 }
208 lastch = ch;
209 if (growing == 0)
210 {
211 display(tail, ' ');
212 tail->next->prev = NULL;
213 nh = tail->next;
214 free(tail);
215 tail = nh;
216 }
217 else growing--;
218 display(head, BODY);
219 wmove(tv, y, x);
220 if (isdigit(ch = winch(tv)))
221 {
222 growing += ch-'0';
223 prize();
224 score += growing;
225 running = 0;
226 wmove(stw, 0, 68);
227 wprintw(stw, "Score: %3d", score);
228 wrefresh(stw);
229 }
230 else if(ch != ' ') crash();
231 nh = newlink();
232 nh->next = NULL;
233 nh->prev = head;
234 head->next = nh;
235 nh->y = y;
236 nh->x = x;
237 display(nh, HEAD);
238 head = nh;
73ead3d6
KA
239 if (!(slow && running))
240 wrefresh(tv);
241 if (!running)
242 alarm(1);
c4e6edfa
KM
243}
244
245crash()
246{
247 sleep(2);
248 clear();
249 move(23, 0);
250 refresh();
fd35ae3d 251 printf("Well, you ran into something and the game is over.\n");
c4e6edfa
KM
252 printf("Your final score was %d\n", score);
253 leave();
254}
255
256suspend()
257{
258 char *sh;
259
260 move(LINES-1, 0);
261 refresh();
262 endwin();
263 fflush(stdout);
c4e6edfa
KM
264 kill(getpid(), SIGTSTP);
265 signal(SIGTSTP, suspend);
c4e6edfa
KM
266 crmode();
267 noecho();
268 setup();
269}
270
271setup()
272{
273 clear();
274 refresh();
275 touchwin(stw);
276 wrefresh(stw);
277 touchwin(tv);
278 wrefresh(tv);
279 alarm(1);
280}