|
|
1.1 root 1: static char *sccsid = "@(#)worm.c 4.3 (Berkeley) 5/19/83";
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)
20: #ifndef attron
21: # define baudrate() _tty.sg_ospeed
22: #endif
23:
24: WINDOW *tv;
25: WINDOW *stw;
26: struct body {
27: int x;
28: int y;
29: struct body *prev;
30: struct body *next;
31: } *head, *tail, goody;
32: int growing = 0;
33: int running = 0;
34: int slow = 0;
35: int score = 0;
36: int start_len = LENGTH;
37: char lastch;
38: char outbuf[BUFSIZ];
39:
40: main(argc, argv)
41: char **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();
61: slow = (baudrate() <= B1200);
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:
91: life()
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;
111: }
112:
113: display(pos, chr)
114: struct body *pos;
115: char chr;
116: {
117: wmove(tv, pos->y, pos->x);
118: waddch(tv, chr);
119: }
120:
121: leave()
122: {
123: endwin();
124: exit(0);
125: }
126:
127: wake()
128: {
129: signal(SIGALRM, wake);
130: fflush(stdout);
131: process(lastch);
132: }
133:
134: rnd(range)
135: {
136: return abs((rand()>>5)+(rand()>>5)) % range;
137: }
138:
139: newpos(bp)
140: struct 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:
149: prize()
150: {
151: int value;
152:
153: value = rnd(9) + 1;
154: newpos(&goody);
155: waddch(tv, value+'0');
156: wrefresh(tv);
157: }
158:
159: process(ch)
160: char 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;
216: if (!(slow && running))
217: wrefresh(tv);
218: if (!running)
219: alarm(1);
220: }
221:
222: crash()
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:
233: suspend()
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:
255: setup()
256: {
257: clear();
258: refresh();
259: touchwin(stw);
260: wrefresh(stw);
261: touchwin(tv);
262: wrefresh(tv);
263: alarm(1);
264: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.