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: }