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