|
|
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.