|
|
1.1 root 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
8: char 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
14: static char sccsid[] = "@(#)worm.c 5.2 (Berkeley) 6/25/85";
15: #endif not lint
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)
34: #ifndef baudrate
35: # define baudrate() _tty.sg_ospeed
36: #endif
37:
38: WINDOW *tv;
39: WINDOW *stw;
40: struct body {
41: int x;
42: int y;
43: struct body *prev;
44: struct body *next;
45: } *head, *tail, goody;
46: int growing = 0;
47: int running = 0;
48: int slow = 0;
49: int score = 0;
50: int start_len = LENGTH;
51: char lastch;
52: char outbuf[BUFSIZ];
53:
54: main(argc, argv)
55: char **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();
75: slow = (baudrate() <= B1200);
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:
105: life()
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;
125: }
126:
127: display(pos, chr)
128: struct body *pos;
129: char chr;
130: {
131: wmove(tv, pos->y, pos->x);
132: waddch(tv, chr);
133: }
134:
135: leave()
136: {
137: endwin();
138: exit(0);
139: }
140:
141: wake()
142: {
143: signal(SIGALRM, wake);
144: fflush(stdout);
145: process(lastch);
146: }
147:
148: rnd(range)
149: {
150: return abs((rand()>>5)+(rand()>>5)) % range;
151: }
152:
153: newpos(bp)
154: struct 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:
163: prize()
164: {
165: int value;
166:
167: value = rnd(9) + 1;
168: newpos(&goody);
169: waddch(tv, value+'0');
170: wrefresh(tv);
171: }
172:
173: process(ch)
174: char 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;
230: if (!(slow && running))
231: wrefresh(tv);
232: if (!running)
233: alarm(1);
234: }
235:
236: crash()
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:
247: suspend()
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:
269: setup()
270: {
271: clear();
272: refresh();
273: touchwin(stw);
274: wrefresh(stw);
275: touchwin(tv);
276: wrefresh(tv);
277: alarm(1);
278: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.