1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)worm.c 5.10 (Berkeley) 02/03/93"; 16 #endif /* not lint */ 17 18 /* 19 * Worm. Written by Michael Toy 20 * UCSC 21 */ 22 23 #include <ctype.h> 24 #include <curses.h> 25 #include <signal.h> 26 #include <termios.h> 27 28 #define newlink() (struct body *) malloc(sizeof (struct body)); 29 #define HEAD '@' 30 #define BODY 'o' 31 #define LENGTH 7 32 #define RUNLEN 8 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 void leave(), wake(), suspend(); 55 56 main(argc, argv) 57 int argc; 58 char **argv; 59 { 60 char ch; 61 62 if (argc == 2) 63 start_len = atoi(argv[1]); 64 if ((start_len <= 0) || (start_len > 500)) 65 start_len = LENGTH; 66 setbuf(stdout, outbuf); 67 srand(getpid()); 68 signal(SIGALRM, wake); 69 signal(SIGINT, leave); 70 signal(SIGQUIT, leave); 71 signal(SIGTSTP, suspend); /* process control signal */ 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 void 136 leave() 137 { 138 endwin(); 139 exit(0); 140 } 141 142 void 143 wake() 144 { 145 signal(SIGALRM, wake); 146 fflush(stdout); 147 process(lastch); 148 } 149 150 rnd(range) 151 { 152 return abs((rand()>>5)+(rand()>>5)) % range; 153 } 154 155 newpos(bp) 156 struct body * bp; 157 { 158 do { 159 bp->y = rnd(LINES-3)+ 2; 160 bp->x = rnd(COLS-3) + 1; 161 wmove(tv, bp->y, bp->x); 162 } while(winch(tv) != ' '); 163 } 164 165 prize() 166 { 167 int value; 168 169 value = rnd(9) + 1; 170 newpos(&goody); 171 waddch(tv, value+'0'); 172 wrefresh(tv); 173 } 174 175 process(ch) 176 char ch; 177 { 178 register int x,y; 179 struct body *nh; 180 181 alarm(0); 182 x = head->x; 183 y = head->y; 184 switch(ch) 185 { 186 case 'h': x--; break; 187 case 'j': y++; break; 188 case 'k': y--; break; 189 case 'l': x++; break; 190 case 'H': x--; running = RUNLEN; ch = tolower(ch); break; 191 case 'J': y++; running = RUNLEN/2; ch = tolower(ch); break; 192 case 'K': y--; running = RUNLEN/2; ch = tolower(ch); break; 193 case 'L': x++; running = RUNLEN; ch = tolower(ch); break; 194 case '\f': setup(); return; 195 case CNTRL('Z'): suspend(); return; 196 case CNTRL('C'): crash(); return; 197 case CNTRL('D'): crash(); return; 198 default: if (! running) alarm(1); 199 return; 200 } 201 lastch = ch; 202 if (growing == 0) 203 { 204 display(tail, ' '); 205 tail->next->prev = NULL; 206 nh = tail->next; 207 free(tail); 208 tail = nh; 209 } 210 else growing--; 211 display(head, BODY); 212 wmove(tv, y, x); 213 if (isdigit(ch = winch(tv))) 214 { 215 growing += ch-'0'; 216 prize(); 217 score += growing; 218 running = 0; 219 wmove(stw, 0, 68); 220 wprintw(stw, "Score: %3d", score); 221 wrefresh(stw); 222 } 223 else if(ch != ' ') crash(); 224 nh = newlink(); 225 nh->next = NULL; 226 nh->prev = head; 227 head->next = nh; 228 nh->y = y; 229 nh->x = x; 230 display(nh, HEAD); 231 head = nh; 232 if (!(slow && running)) 233 wrefresh(tv); 234 if (!running) 235 alarm(1); 236 } 237 238 crash() 239 { 240 sleep(2); 241 clear(); 242 move(23, 0); 243 refresh(); 244 printf("Well, you ran into something and the game is over.\n"); 245 printf("Your final score was %d\n", score); 246 leave(); 247 } 248 249 void 250 suspend() 251 { 252 char *sh; 253 254 move(LINES-1, 0); 255 refresh(); 256 endwin(); 257 fflush(stdout); 258 kill(getpid(), SIGTSTP); 259 signal(SIGTSTP, suspend); 260 crmode(); 261 noecho(); 262 setup(); 263 } 264 265 setup() 266 { 267 clear(); 268 refresh(); 269 touchwin(stw); 270 wrefresh(stw); 271 touchwin(tv); 272 wrefresh(tv); 273 alarm(1); 274 } 275