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