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