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