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