1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)worm.c 5.6 (Berkeley) 08/02/89"; 26 #endif /* not lint */ 27 28 /* 29 * Worm. Written by Michael Toy 30 * UCSC 31 */ 32 33 #include <ctype.h> 34 #include <curses.h> 35 #include <signal.h> 36 37 #define newlink() (struct body *) malloc(sizeof (struct body)); 38 #define HEAD '@' 39 #define BODY 'o' 40 #define LENGTH 7 41 #define RUNLEN 8 42 #define when break;case 43 #define otherwise break;default 44 #define CNTRL(p) (p-'A'+1) 45 #ifndef baudrate 46 # define baudrate() _tty.sg_ospeed 47 #endif 48 49 WINDOW *tv; 50 WINDOW *stw; 51 struct body { 52 int x; 53 int y; 54 struct body *prev; 55 struct body *next; 56 } *head, *tail, goody; 57 int growing = 0; 58 int running = 0; 59 int slow = 0; 60 int score = 0; 61 int start_len = LENGTH; 62 char lastch; 63 char outbuf[BUFSIZ]; 64 65 main(argc, argv) 66 char **argv; 67 { 68 int leave(), wake(), suspend(); 69 char ch; 70 71 if (argc == 2) 72 start_len = atoi(argv[1]); 73 if ((start_len <= 0) || (start_len > 500)) 74 start_len = LENGTH; 75 setbuf(stdout, outbuf); 76 srand(getpid()); 77 signal(SIGALRM, wake); 78 signal(SIGINT, leave); 79 signal(SIGQUIT, leave); 80 signal(SIGTSTP, suspend); /* process control signal */ 81 initscr(); 82 crmode(); 83 noecho(); 84 slow = (baudrate() <= B1200); 85 clear(); 86 stw = newwin(1, COLS-1, 0, 0); 87 tv = newwin(LINES-1, COLS-1, 1, 0); 88 box(tv, '*', '*'); 89 scrollok(tv, FALSE); 90 scrollok(stw, FALSE); 91 wmove(stw, 0, 0); 92 wprintw(stw, " Worm"); 93 refresh(); 94 wrefresh(stw); 95 wrefresh(tv); 96 life(); /* Create the worm */ 97 prize(); /* Put up a goal */ 98 while(1) 99 { 100 if (running) 101 { 102 running--; 103 process(lastch); 104 } 105 else 106 { 107 fflush(stdout); 108 if (read(0, &ch, 1) >= 0) 109 process(ch); 110 } 111 } 112 } 113 114 life() 115 { 116 register struct body *bp, *np; 117 register int i; 118 119 head = newlink(); 120 head->x = start_len+2; 121 head->y = 12; 122 head->next = NULL; 123 display(head, HEAD); 124 for (i = 0, bp = head; i < start_len; i++, bp = np) { 125 np = newlink(); 126 np->next = bp; 127 bp->prev = np; 128 np->x = bp->x - 1; 129 np->y = bp->y; 130 display(np, BODY); 131 } 132 tail = np; 133 tail->prev = NULL; 134 } 135 136 display(pos, chr) 137 struct body *pos; 138 char chr; 139 { 140 wmove(tv, pos->y, pos->x); 141 waddch(tv, chr); 142 } 143 144 leave() 145 { 146 endwin(); 147 exit(0); 148 } 149 150 wake() 151 { 152 signal(SIGALRM, wake); 153 fflush(stdout); 154 process(lastch); 155 } 156 157 rnd(range) 158 { 159 return abs((rand()>>5)+(rand()>>5)) % range; 160 } 161 162 newpos(bp) 163 struct body * bp; 164 { 165 do { 166 bp->y = rnd(LINES-3)+ 2; 167 bp->x = rnd(COLS-3) + 1; 168 wmove(tv, bp->y, bp->x); 169 } while(winch(tv) != ' '); 170 } 171 172 prize() 173 { 174 int value; 175 176 value = rnd(9) + 1; 177 newpos(&goody); 178 waddch(tv, value+'0'); 179 wrefresh(tv); 180 } 181 182 process(ch) 183 char ch; 184 { 185 register int x,y; 186 struct body *nh; 187 188 alarm(0); 189 x = head->x; 190 y = head->y; 191 switch(ch) 192 { 193 when 'h': x--; 194 when 'j': y++; 195 when 'k': y--; 196 when 'l': x++; 197 when 'H': x--; running = RUNLEN; ch = tolower(ch); 198 when 'J': y++; running = RUNLEN/2; ch = tolower(ch); 199 when 'K': y--; running = RUNLEN/2; ch = tolower(ch); 200 when 'L': x++; running = RUNLEN; ch = tolower(ch); 201 when '\f': setup(); return; 202 when CNTRL('Z'): suspend(); return; 203 when CNTRL('C'): crash(); return; 204 when CNTRL('D'): crash(); return; 205 otherwise: if (! running) alarm(1); 206 return; 207 } 208 lastch = ch; 209 if (growing == 0) 210 { 211 display(tail, ' '); 212 tail->next->prev = NULL; 213 nh = tail->next; 214 free(tail); 215 tail = nh; 216 } 217 else growing--; 218 display(head, BODY); 219 wmove(tv, y, x); 220 if (isdigit(ch = winch(tv))) 221 { 222 growing += ch-'0'; 223 prize(); 224 score += growing; 225 running = 0; 226 wmove(stw, 0, 68); 227 wprintw(stw, "Score: %3d", score); 228 wrefresh(stw); 229 } 230 else if(ch != ' ') crash(); 231 nh = newlink(); 232 nh->next = NULL; 233 nh->prev = head; 234 head->next = nh; 235 nh->y = y; 236 nh->x = x; 237 display(nh, HEAD); 238 head = nh; 239 if (!(slow && running)) 240 wrefresh(tv); 241 if (!running) 242 alarm(1); 243 } 244 245 crash() 246 { 247 sleep(2); 248 clear(); 249 move(23, 0); 250 refresh(); 251 printf("Well, you ran into something and the game is over.\n"); 252 printf("Your final score was %d\n", score); 253 leave(); 254 } 255 256 suspend() 257 { 258 char *sh; 259 260 move(LINES-1, 0); 261 refresh(); 262 endwin(); 263 fflush(stdout); 264 kill(getpid(), SIGTSTP); 265 signal(SIGTSTP, suspend); 266 crmode(); 267 noecho(); 268 setup(); 269 } 270 271 setup() 272 { 273 clear(); 274 refresh(); 275 touchwin(stw); 276 wrefresh(stw); 277 touchwin(tv); 278 wrefresh(tv); 279 alarm(1); 280 } 281