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