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