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