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