Commit | Line | Data |
---|---|---|
b6f0a7e4 DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
a825d20f KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
65c7d3b6 KB |
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. | |
b6f0a7e4 DF |
16 | */ |
17 | ||
18 | #ifndef lint | |
19 | char copyright[] = | |
20 | "@(#) Copyright (c) 1980 Regents of the University of California.\n\ | |
21 | All rights reserved.\n"; | |
a825d20f | 22 | #endif /* not lint */ |
b6f0a7e4 | 23 | |
384a101e | 24 | #ifndef lint |
65c7d3b6 | 25 | static char sccsid[] = "@(#)snake.c 5.6 (Berkeley) %G%"; |
a825d20f | 26 | #endif /* not lint */ |
384a101e SL |
27 | |
28 | /* | |
29 | * snake - crt hack game. | |
30 | * | |
31 | * You move around the screen with arrow keys trying to pick up money | |
32 | * without getting eaten by the snake. hjkl work as in vi in place of | |
33 | * arrow keys. You can leave at the exit any time. | |
34 | * | |
35 | * compile as follows: | |
36 | * cc -O snake.c move.c -o snake -lm -ltermlib | |
37 | */ | |
38 | ||
3f63e290 | 39 | #include <sys/param.h> |
384a101e | 40 | #include <pwd.h> |
3f63e290 | 41 | #include "snake.h" |
384a101e SL |
42 | |
43 | /* | |
44 | * This is the data file for scorekeeping. | |
45 | */ | |
46 | #ifndef SNAKERAWSCORES | |
47 | #define SNAKERAWSCORES "/usr/games/lib/snakerawscores" | |
48 | #endif | |
49 | ||
50 | /* | |
51 | * If it exists, a log is kept here. Otherwise it isn't. | |
52 | */ | |
53 | #ifndef LOGFILE | |
54 | #define LOGFILE "/usr/games/lib/snake.log" | |
55 | #endif | |
56 | ||
57 | #define PENALTY 10 /* % penalty for invoking spacewarp */ | |
58 | ||
59 | #define EOT '\004' | |
60 | #define LF '\n' | |
61 | #define DEL '\177' | |
62 | ||
63 | #define ME 'I' | |
64 | #define SNAKEHEAD 'S' | |
65 | #define SNAKETAIL 's' | |
66 | #define TREASURE '$' | |
67 | #define GOAL '#' | |
68 | ||
69 | #define BSIZE 80 | |
70 | ||
71 | struct point you; | |
72 | struct point money; | |
73 | struct point finish; | |
74 | struct point snake[6]; | |
75 | ||
76 | int loot, penalty; | |
77 | int long tl, tm=0L; | |
384a101e | 78 | int moves; |
384a101e SL |
79 | char stri[BSIZE]; |
80 | char *p; | |
81 | char ch, savec; | |
82 | char *kl, *kr, *ku, *kd; | |
83 | int fast=1; | |
84 | int repeat=1; | |
85 | long tv; | |
86 | char *tn; | |
87 | ||
88 | main(argc,argv) | |
89 | int argc; | |
90 | char **argv; | |
91 | { | |
3f63e290 KB |
92 | extern char *optarg; |
93 | extern int optind; | |
94 | int ch, i, j, k; | |
95 | time_t time(); | |
96 | long atol(); | |
384a101e | 97 | int stop(); |
384a101e | 98 | |
3f63e290 KB |
99 | (void)time(&tv); |
100 | srandom((int)tv); | |
384a101e | 101 | |
3f63e290 KB |
102 | while ((ch = getopt(argc, argv, "l:w:")) != EOF) |
103 | switch((char)ch) { | |
104 | #ifdef notdef | |
384a101e | 105 | case 'd': |
3f63e290 | 106 | tv = atol(optarg); |
384a101e | 107 | break; |
3f63e290 | 108 | #endif |
384a101e | 109 | case 'w': /* width */ |
3f63e290 | 110 | ccnt = atoi(optarg); |
384a101e SL |
111 | break; |
112 | case 'l': /* length */ | |
3f63e290 | 113 | lcnt = atoi(optarg); |
384a101e | 114 | break; |
3f63e290 | 115 | case '?': |
384a101e | 116 | default: |
3f63e290 KB |
117 | fputs("usage: snake [-d seed] [-w width] [-l length]\n", stderr); |
118 | exit(1); | |
384a101e | 119 | } |
384a101e | 120 | |
3f63e290 KB |
121 | penalty = loot = 0; |
122 | getcap(); | |
123 | ||
124 | i = MIN(lcnt, ccnt); | |
384a101e | 125 | if (i < 4) { |
3f63e290 KB |
126 | cook(); |
127 | printf("snake: screen too small for a fair game.\n"); | |
128 | exit(1); | |
384a101e | 129 | } |
3f63e290 | 130 | |
384a101e SL |
131 | /* |
132 | * chunk is the amount of money the user gets for each $. | |
133 | * The formula below tries to be fair for various screen sizes. | |
134 | * We only pay attention to the smaller of the 2 edges, since | |
135 | * that seems to be the bottleneck. | |
136 | * This formula is a hyperbola which includes the following points: | |
137 | * (24, $25) (original scoring algorithm) | |
138 | * (12, $40) (experimentally derived by the "feel") | |
139 | * (48, $15) (a guess) | |
140 | * This will give a 4x4 screen $99/shot. We don't allow anything | |
141 | * smaller than 4x4 because there is a 3x3 game where you can win | |
142 | * an infinite amount of money. | |
143 | */ | |
144 | if (i < 12) i = 12; /* otherwise it isn't fair */ | |
145 | /* | |
146 | * Compensate for border. This really changes the game since | |
147 | * the screen is two squares smaller but we want the default | |
148 | * to be $25, and the high scores on small screens were a bit | |
149 | * much anyway. | |
150 | */ | |
151 | i += 2; | |
152 | chunk = (675.0 / (i+6)) + 2.5; /* min screen edge */ | |
153 | ||
154 | signal (SIGINT, stop); | |
155 | putpad(TI); /* String to begin programs that use cm */ | |
156 | putpad(KS); /* Put terminal in keypad transmit mode */ | |
157 | ||
3f63e290 KB |
158 | snrand(&finish); |
159 | snrand(&you); | |
160 | snrand(&money); | |
161 | snrand(&snake[0]); | |
384a101e SL |
162 | |
163 | if ((orig.sg_ospeed < B9600) || | |
164 | ((! CM) && (! TA))) fast=0; | |
165 | for(i=1;i<6;i++) | |
166 | chase (&snake[i], &snake[i-1]); | |
167 | setup(); | |
168 | mainloop(); | |
169 | } | |
170 | ||
171 | /* Main command loop */ | |
172 | mainloop() | |
173 | { | |
174 | int j, k; | |
175 | ||
176 | for (;;) { | |
177 | int c,lastc,match; | |
178 | ||
179 | move(&you); | |
180 | fflush(stdout); | |
181 | if (((c = getchar() & 0177) <= '9') && (c >= '0')) { | |
182 | ungetc(c,stdin); | |
183 | j = scanf("%d",&repeat); | |
184 | c = getchar() & 0177; | |
185 | } else { | |
186 | if (c != '.') repeat = 1; | |
187 | } | |
188 | if (c == '.') { | |
189 | c = lastc; | |
190 | } | |
191 | if ((Klength > 0) && | |
192 | (c == *KL || c == *KR || c == *KU || c == *KD)) { | |
193 | savec = c; | |
194 | match = 0; | |
195 | kl = KL; | |
196 | kr = KR; | |
197 | ku = KU; | |
198 | kd = KD; | |
199 | for (j=Klength;j>0;j--){ | |
200 | if (match != 1) { | |
201 | match = 0; | |
202 | if (*kl++ == c) { | |
203 | ch = 'h'; | |
204 | match++; | |
205 | } | |
206 | if (*kr++ == c) { | |
207 | ch = 'l'; | |
208 | match++; | |
209 | } | |
210 | if (*ku++ == c) { | |
211 | ch = 'k'; | |
212 | match++; | |
213 | } | |
214 | if (*kd++ == c) { | |
215 | ch = 'j'; | |
216 | match++; | |
217 | } | |
218 | if (match == 0) { | |
219 | ungetc(c,stdin); | |
220 | ch = savec; | |
221 | /* Oops! | |
222 | * This works if we figure it out on second character. | |
223 | */ | |
224 | break; | |
225 | } | |
226 | } | |
227 | savec = c; | |
228 | if(j != 1) c = getchar() & 0177; | |
229 | } | |
230 | c = ch; | |
231 | } | |
232 | if (!fast) flushi(); | |
233 | lastc = c; | |
234 | switch (c){ | |
36c966f5 | 235 | case CTRL('z'): |
384a101e SL |
236 | suspend(); |
237 | continue; | |
238 | case EOT: | |
239 | case 'x': | |
240 | case 0177: /* del or end of file */ | |
241 | ll(); | |
242 | length(moves); | |
243 | logit("quit"); | |
244 | done(); | |
36c966f5 | 245 | case CTRL('l'): |
384a101e SL |
246 | setup(); |
247 | winnings(cashvalue); | |
248 | continue; | |
249 | case 'p': | |
250 | case 'd': | |
251 | snap(); | |
252 | continue; | |
253 | case 'w': | |
254 | spacewarp(0); | |
255 | continue; | |
256 | case 'A': | |
257 | repeat = you.col; | |
258 | c = 'h'; | |
259 | break; | |
260 | case 'H': | |
261 | case 'S': | |
262 | repeat = you.col - money.col; | |
263 | c = 'h'; | |
264 | break; | |
265 | case 'T': | |
266 | repeat = you.line; | |
267 | c = 'k'; | |
268 | break; | |
269 | case 'K': | |
270 | case 'E': | |
271 | repeat = you.line - money.line; | |
272 | c = 'k'; | |
273 | break; | |
274 | case 'P': | |
275 | repeat = ccnt - 1 - you.col; | |
276 | c = 'l'; | |
277 | break; | |
278 | case 'L': | |
279 | case 'F': | |
280 | repeat = money.col - you.col; | |
281 | c = 'l'; | |
282 | break; | |
283 | case 'B': | |
284 | repeat = lcnt - 1 - you.line; | |
285 | c = 'j'; | |
286 | break; | |
287 | case 'J': | |
288 | case 'C': | |
289 | repeat = money.line - you.line; | |
290 | c = 'j'; | |
291 | break; | |
292 | } | |
293 | for(k=1;k<=repeat;k++){ | |
294 | moves++; | |
295 | switch(c) { | |
296 | case 's': | |
297 | case 'h': | |
298 | case '\b': | |
299 | if (you.col >0) { | |
300 | if((fast)||(k == 1)) | |
301 | pchar(&you,' '); | |
302 | you.col--; | |
303 | if((fast) || (k == repeat) || | |
304 | (you.col == 0)) | |
305 | pchar(&you,ME); | |
306 | } | |
307 | break; | |
308 | case 'f': | |
309 | case 'l': | |
310 | case ' ': | |
311 | if (you.col < ccnt-1) { | |
312 | if((fast)||(k == 1)) | |
313 | pchar(&you,' '); | |
314 | you.col++; | |
315 | if((fast) || (k == repeat) || | |
316 | (you.col == ccnt-1)) | |
317 | pchar(&you,ME); | |
318 | } | |
319 | break; | |
36c966f5 | 320 | case CTRL('p'): |
384a101e SL |
321 | case 'e': |
322 | case 'k': | |
323 | case 'i': | |
324 | if (you.line > 0) { | |
325 | if((fast)||(k == 1)) | |
326 | pchar(&you,' '); | |
327 | you.line--; | |
328 | if((fast) || (k == repeat) || | |
329 | (you.line == 0)) | |
330 | pchar(&you,ME); | |
331 | } | |
332 | break; | |
36c966f5 | 333 | case CTRL('n'): |
384a101e SL |
334 | case 'c': |
335 | case 'j': | |
336 | case LF: | |
337 | case 'm': | |
338 | if (you.line+1 < lcnt) { | |
339 | if((fast)||(k == 1)) | |
340 | pchar(&you,' '); | |
341 | you.line++; | |
342 | if((fast) || (k == repeat) || | |
343 | (you.line == lcnt-1)) | |
344 | pchar(&you,ME); | |
345 | } | |
346 | break; | |
347 | } | |
348 | ||
349 | if (same(&you,&money)) | |
350 | { | |
351 | char xp[20]; | |
352 | struct point z; | |
353 | loot += 25; | |
354 | if(k < repeat) | |
355 | pchar(&you,' '); | |
356 | do { | |
3f63e290 | 357 | snrand(&money); |
384a101e SL |
358 | } while (money.col == finish.col && money.line == finish.line || |
359 | money.col < 5 && money.line == 0 || | |
360 | money.col == you.col && money.line == you.line); | |
361 | pchar(&money,TREASURE); | |
362 | winnings(cashvalue); | |
363 | continue; | |
364 | } | |
365 | if (same(&you,&finish)) | |
366 | { | |
367 | win(&finish); | |
368 | ll(); | |
369 | cook(); | |
370 | printf("You have won with $%d.\n",cashvalue); | |
371 | fflush(stdout); | |
372 | logit("won"); | |
373 | post(cashvalue,0); | |
374 | length(moves); | |
3f63e290 | 375 | done(); |
384a101e SL |
376 | } |
377 | if (pushsnake())break; | |
378 | } | |
379 | fflush(stdout); | |
380 | } | |
381 | } | |
382 | ||
383 | setup(){ /* | |
384 | * setup the board | |
385 | */ | |
386 | int i; | |
387 | ||
388 | clear(); | |
389 | pchar(&you,ME); | |
390 | pchar(&finish,GOAL); | |
391 | pchar(&money,TREASURE); | |
392 | for(i=1; i<6; i++) { | |
393 | pchar(&snake[i],SNAKETAIL); | |
394 | } | |
395 | pchar(&snake[0], SNAKEHEAD); | |
396 | drawbox(); | |
397 | fflush(stdout); | |
398 | } | |
399 | ||
400 | drawbox() | |
401 | { | |
402 | register int i; | |
403 | struct point p; | |
404 | ||
405 | p.line = -1; | |
406 | for (i= 0; i<ccnt; i++) { | |
407 | p.col = i; | |
408 | pchar(&p, '-'); | |
409 | } | |
410 | p.col = ccnt; | |
411 | for (i= -1; i<=lcnt; i++) { | |
412 | p.line = i; | |
413 | pchar(&p, '|'); | |
414 | } | |
415 | p.col = -1; | |
416 | for (i= -1; i<=lcnt; i++) { | |
417 | p.line = i; | |
418 | pchar(&p, '|'); | |
419 | } | |
420 | p.line = lcnt; | |
421 | for (i= 0; i<ccnt; i++) { | |
422 | p.col = i; | |
423 | pchar(&p, '-'); | |
424 | } | |
425 | } | |
426 | ||
3f63e290 | 427 | snrand(sp) |
384a101e SL |
428 | struct point *sp; |
429 | { | |
384a101e SL |
430 | struct point p; |
431 | register int i; | |
432 | ||
3f63e290 KB |
433 | for (;;) { |
434 | p.col = random() % ccnt; | |
435 | p.line = random() % lcnt; | |
384a101e SL |
436 | |
437 | /* make sure it's not on top of something else */ | |
3f63e290 KB |
438 | if (p.line == 0 && p.col < 5) |
439 | continue; | |
440 | if (same(&p, &you)) | |
441 | continue; | |
442 | if (same(&p, &money)) | |
443 | continue; | |
444 | if (same(&p, &finish)) | |
445 | continue; | |
446 | for (i = 0; i < 5; i++) | |
447 | if (same(&p, &snake[i])) | |
448 | break; | |
449 | if (i < 5) | |
450 | continue; | |
451 | break; | |
452 | } | |
384a101e SL |
453 | *sp = p; |
454 | } | |
455 | ||
7cfc1f81 S |
456 | post(iscore, flag) |
457 | int iscore, flag; | |
384a101e | 458 | { |
7cfc1f81 | 459 | short score = iscore; |
384a101e | 460 | int rawscores; |
7cfc1f81 | 461 | short uid; |
384a101e SL |
462 | short oldbest=0; |
463 | short allbwho=0, allbscore=0; | |
464 | struct passwd *p, *getpwuid(); | |
465 | ||
466 | /* | |
467 | * Neg uid, 0, and 1 cannot have scores recorded. | |
468 | */ | |
469 | if ((uid=getuid()) > 1 && (rawscores=open(SNAKERAWSCORES,2))>=0) { | |
470 | /* Figure out what happened in the past */ | |
471 | read(rawscores, &allbscore, sizeof(short)); | |
472 | read(rawscores, &allbwho, sizeof(short)); | |
473 | lseek(rawscores, ((long)uid)*sizeof(short), 0); | |
474 | read(rawscores, &oldbest, sizeof(short)); | |
475 | if (flag) return (score > oldbest ? 1 : 0); | |
476 | ||
477 | /* Update this jokers best */ | |
478 | if (score > oldbest) { | |
479 | lseek(rawscores, ((long)uid)*sizeof(short), 0); | |
480 | write(rawscores, &score, sizeof(short)); | |
481 | printf("You bettered your previous best of $%d\n", oldbest); | |
482 | } else | |
483 | printf("Your best to date is $%d\n", oldbest); | |
484 | ||
485 | /* See if we have a new champ */ | |
486 | p = getpwuid(allbwho); | |
487 | if (p == NULL || score > allbscore) { | |
488 | lseek(rawscores, (long)0, 0); | |
489 | write(rawscores, &score, sizeof(short)); | |
490 | write(rawscores, &uid, sizeof(short)); | |
491 | if (p != NULL) | |
492 | printf("You beat %s's old record of $%d!\n", p->pw_name, allbscore); | |
493 | else | |
494 | printf("You set a new record!\n"); | |
495 | } else | |
496 | printf("The highest is %s with $%d\n", p->pw_name, allbscore); | |
497 | close(rawscores); | |
498 | } else | |
499 | if (!flag) | |
500 | printf("Unable to post score.\n"); | |
501 | return (1); | |
502 | } | |
503 | ||
504 | /* | |
505 | * Flush typeahead to keep from buffering a bunch of chars and then | |
506 | * overshooting. This loses horribly at 9600 baud, but works nicely | |
507 | * if the terminal gets behind. | |
508 | */ | |
509 | flushi() | |
510 | { | |
511 | stty(0, &new); | |
512 | } | |
513 | int mx [8] = { | |
514 | 0, 1, 1, 1, 0,-1,-1,-1}; | |
515 | int my [8] = { | |
516 | -1,-1, 0, 1, 1, 1, 0,-1}; | |
517 | float absv[8]= { | |
518 | 1, 1.4, 1, 1.4, 1, 1.4, 1, 1.4 | |
519 | }; | |
520 | int oldw=0; | |
521 | chase (np, sp) | |
522 | struct point *sp, *np; | |
523 | { | |
524 | /* this algorithm has bugs; otherwise the | |
525 | snake would get too good */ | |
526 | struct point d; | |
527 | int w, i, wt[8]; | |
528 | double sqrt(), v1, v2, vp, max; | |
529 | point(&d,you.col-sp->col,you.line-sp->line); | |
530 | v1 = sqrt( (double) (d.col*d.col + d.line*d.line) ); | |
531 | w=0; | |
532 | max=0; | |
533 | for(i=0; i<8; i++) | |
534 | { | |
535 | vp = d.col*mx[i] + d.line*my[i]; | |
536 | v2 = absv[i]; | |
537 | if (v1>0) | |
538 | vp = ((double)vp)/(v1*v2); | |
539 | else vp=1.0; | |
540 | if (vp>max) | |
541 | { | |
542 | max=vp; | |
543 | w=i; | |
544 | } | |
545 | } | |
546 | for(i=0; i<8; i++) | |
547 | { | |
548 | point(&d,sp->col+mx[i],sp->line+my[i]); | |
549 | wt[i]=0; | |
550 | if (d.col<0 || d.col>=ccnt || d.line<0 || d.line>=lcnt) | |
551 | continue; | |
3f63e290 KB |
552 | /* |
553 | * Change to allow snake to eat you if you're on the money, | |
554 | * otherwise, you can just crouch there until the snake goes | |
555 | * away. Not positive it's right. | |
556 | * | |
557 | * if (d.line == 0 && d.col < 5) continue; | |
558 | */ | |
384a101e SL |
559 | if (same(&d,&money)) continue; |
560 | if (same(&d,&finish)) continue; | |
561 | wt[i]= i==w ? loot/10 : 1; | |
562 | if (i==oldw) wt [i] += loot/20; | |
563 | } | |
564 | for(w=i=0; i<8; i++) | |
565 | w+= wt[i]; | |
566 | vp = (( rand() >> 6 ) & 01777) %w; | |
567 | for(i=0; i<8; i++) | |
568 | if (vp <wt[i]) | |
569 | break; | |
570 | else | |
571 | vp -= wt[i]; | |
572 | if (i==8) { | |
573 | printf("failure\n"); | |
574 | i=0; | |
575 | while (wt[i]==0) i++; | |
576 | } | |
577 | oldw=w=i; | |
578 | point(np,sp->col+mx[w],sp->line+my[w]); | |
579 | } | |
580 | ||
581 | spacewarp(w) | |
582 | int w;{ | |
583 | struct point p; | |
584 | int j; | |
3f63e290 KB |
585 | char *str; |
586 | ||
587 | snrand(&you); | |
384a101e SL |
588 | point(&p,COLUMNS/2 - 8,LINES/2 - 1); |
589 | if (p.col < 0) | |
590 | p.col = 0; | |
591 | if (p.line < 0) | |
592 | p.line = 0; | |
593 | if (w) { | |
3f63e290 | 594 | str = "BONUS!!!"; |
384a101e SL |
595 | loot = loot - penalty; |
596 | penalty = 0; | |
597 | } else { | |
3f63e290 | 598 | str = "SPACE WARP!!!"; |
384a101e SL |
599 | penalty += loot/PENALTY; |
600 | } | |
601 | for(j=0;j<3;j++){ | |
602 | clear(); | |
603 | delay(5); | |
604 | aprintf(&p,str); | |
605 | delay(10); | |
606 | } | |
607 | setup(); | |
608 | winnings(cashvalue); | |
609 | } | |
610 | snap() | |
611 | { | |
612 | struct point p; | |
613 | int i; | |
614 | ||
615 | if(you.line < 3){ | |
616 | pchar(point(&p,you.col,0),'-'); | |
617 | } | |
618 | if(you.line > lcnt-4){ | |
619 | pchar(point(&p,you.col,lcnt-1),'_'); | |
620 | } | |
621 | if(you.col < 10){ | |
622 | pchar(point(&p,0,you.line),'('); | |
623 | } | |
624 | if(you.col > ccnt-10){ | |
625 | pchar(point(&p,ccnt-1,you.line),')'); | |
626 | } | |
627 | if (! stretch(&money)) if (! stretch(&finish)) delay(10); | |
628 | if(you.line < 3){ | |
629 | point(&p,you.col,0); | |
630 | remove(&p); | |
631 | } | |
632 | if(you.line > lcnt-4){ | |
633 | point(&p,you.col,lcnt-1); | |
634 | remove(&p); | |
635 | } | |
636 | if(you.col < 10){ | |
637 | point(&p,0,you.line); | |
638 | remove(&p); | |
639 | } | |
640 | if(you.col > ccnt-10){ | |
641 | point(&p,ccnt-1,you.line); | |
642 | remove(&p); | |
643 | } | |
644 | fflush(stdout); | |
645 | } | |
646 | stretch(ps) | |
647 | struct point *ps;{ | |
648 | struct point p; | |
3f63e290 | 649 | |
384a101e SL |
650 | point(&p,you.col,you.line); |
651 | if(abs(ps->col-you.col) < 6){ | |
652 | if(you.line < ps->line){ | |
653 | for (p.line = you.line+1;p.line <= ps->line;p.line++) | |
654 | pchar(&p,'v'); | |
655 | delay(10); | |
656 | for (;p.line > you.line;p.line--) | |
657 | remove(&p); | |
658 | } else { | |
659 | for (p.line = you.line-1;p.line >= ps->line;p.line--) | |
660 | pchar(&p,'^'); | |
661 | delay(10); | |
662 | for (;p.line < you.line;p.line++) | |
663 | remove(&p); | |
664 | } | |
665 | return(1); | |
666 | } else if(abs(ps->line-you.line) < 3){ | |
667 | p.line = you.line; | |
668 | if(you.col < ps->col){ | |
669 | for (p.col = you.col+1;p.col <= ps->col;p.col++) | |
670 | pchar(&p,'>'); | |
671 | delay(10); | |
672 | for (;p.col > you.col;p.col--) | |
673 | remove(&p); | |
674 | } else { | |
675 | for (p.col = you.col-1;p.col >= ps->col;p.col--) | |
676 | pchar(&p,'<'); | |
677 | delay(10); | |
678 | for (;p.col < you.col;p.col++) | |
679 | remove(&p); | |
680 | } | |
681 | return(1); | |
682 | } | |
683 | return(0); | |
684 | } | |
685 | ||
686 | surround(ps) | |
687 | struct point *ps;{ | |
688 | struct point x; | |
689 | int i,j; | |
690 | ||
691 | if(ps->col == 0)ps->col++; | |
692 | if(ps->line == 0)ps->line++; | |
693 | if(ps->line == LINES -1)ps->line--; | |
694 | if(ps->col == COLUMNS -1)ps->col--; | |
695 | aprintf(point(&x,ps->col-1,ps->line-1),"/*\\\r* *\r\\*/"); | |
696 | for (j=0;j<20;j++){ | |
697 | pchar(ps,'@'); | |
698 | delay(1); | |
699 | pchar(ps,' '); | |
700 | delay(1); | |
701 | } | |
702 | if (post(cashvalue,1)) { | |
703 | aprintf(point(&x,ps->col-1,ps->line-1)," \ro.o\r\\_/"); | |
704 | delay(6); | |
705 | aprintf(point(&x,ps->col-1,ps->line-1)," \ro.-\r\\_/"); | |
706 | delay(6); | |
707 | } | |
708 | aprintf(point(&x,ps->col-1,ps->line-1)," \ro.o\r\\_/"); | |
709 | } | |
710 | win(ps) | |
711 | struct point *ps; | |
712 | { | |
713 | struct point x; | |
714 | int j,k; | |
715 | int boxsize; /* actually diameter of box, not radius */ | |
716 | ||
717 | boxsize = fast ? 10 : 4; | |
718 | point(&x,ps->col,ps->line); | |
719 | for(j=1;j<boxsize;j++){ | |
720 | for(k=0;k<j;k++){ | |
721 | pchar(&x,'#'); | |
722 | x.line--; | |
723 | } | |
724 | for(k=0;k<j;k++){ | |
725 | pchar(&x,'#'); | |
726 | x.col++; | |
727 | } | |
728 | j++; | |
729 | for(k=0;k<j;k++){ | |
730 | pchar(&x,'#'); | |
731 | x.line++; | |
732 | } | |
733 | for(k=0;k<j;k++){ | |
734 | pchar(&x,'#'); | |
735 | x.col--; | |
736 | } | |
737 | } | |
738 | fflush(stdout); | |
739 | } | |
740 | ||
741 | pushsnake() | |
742 | { | |
743 | int i, bonus; | |
744 | int issame = 0; | |
745 | ||
746 | /* | |
747 | * My manual says times doesn't return a value. Furthermore, the | |
748 | * snake should get his turn every time no matter if the user is | |
749 | * on a fast terminal with typematic keys or not. | |
750 | * So I have taken the call to times out. | |
751 | */ | |
752 | for(i=4; i>=0; i--) | |
753 | if (same(&snake[i], &snake[5])) | |
754 | issame++; | |
755 | if (!issame) | |
756 | pchar(&snake[5],' '); | |
757 | for(i=4; i>=0; i--) | |
758 | snake[i+1]= snake[i]; | |
759 | chase(&snake[0], &snake[1]); | |
760 | pchar(&snake[1],SNAKETAIL); | |
761 | pchar(&snake[0],SNAKEHEAD); | |
762 | for(i=0; i<6; i++) | |
763 | { | |
764 | if (same(&snake[i],&you)) | |
765 | { | |
766 | surround(&you); | |
767 | i = (cashvalue) % 10; | |
768 | bonus = ((rand()>>8) & 0377)% 10; | |
769 | ll(); | |
770 | printf("%d\n", bonus); | |
771 | delay(30); | |
772 | if (bonus == i) { | |
773 | spacewarp(1); | |
774 | logit("bonus"); | |
775 | flushi(); | |
776 | return(1); | |
777 | } | |
778 | if ( loot >= penalty ){ | |
779 | printf("You and your $%d have been eaten\n",cashvalue); | |
780 | } else { | |
781 | printf("The snake ate you. You owe $%d.\n",-cashvalue); | |
782 | } | |
783 | logit("eaten"); | |
784 | length(moves); | |
785 | done(); | |
786 | } | |
787 | } | |
788 | return(0); | |
789 | } | |
790 | ||
791 | remove(sp) | |
792 | struct point *sp; | |
793 | { | |
794 | int j; | |
795 | ||
796 | if (same(sp,&money)) { | |
797 | pchar(sp,TREASURE); | |
798 | return(2); | |
799 | } | |
800 | if (same(sp,&finish)) { | |
801 | pchar(sp,GOAL); | |
802 | return(3); | |
803 | } | |
804 | if (same(sp,&snake[0])) { | |
805 | pchar(sp,SNAKEHEAD); | |
806 | return(4); | |
807 | } | |
808 | for(j=1;j<6;j++){ | |
809 | if(same(sp,&snake[j])){ | |
810 | pchar(sp,SNAKETAIL); | |
811 | return(4); | |
812 | } | |
813 | } | |
814 | if ((sp->col < 4) && (sp->line == 0)){ | |
815 | winnings(cashvalue); | |
816 | if((you.line == 0) && (you.col < 4)) pchar(&you,ME); | |
817 | return(5); | |
818 | } | |
819 | if (same(sp,&you)) { | |
820 | pchar(sp,ME); | |
821 | return(1); | |
822 | } | |
823 | pchar(sp,' '); | |
824 | return(0); | |
825 | } | |
826 | winnings(won) | |
827 | int won; | |
828 | { | |
829 | struct point p; | |
830 | ||
831 | p.line = p.col = 1; | |
832 | if(won>0){ | |
833 | move(&p); | |
834 | printf("$%d",won); | |
835 | } | |
836 | } | |
837 | ||
838 | stop(){ | |
839 | signal(SIGINT,1); | |
840 | ll(); | |
841 | length(moves); | |
842 | done(); | |
843 | } | |
844 | ||
845 | suspend() | |
846 | { | |
847 | char *sh; | |
848 | ||
3f63e290 | 849 | ll(); |
384a101e | 850 | cook(); |
384a101e | 851 | kill(getpid(), SIGTSTP); |
384a101e SL |
852 | raw(); |
853 | setup(); | |
854 | winnings(cashvalue); | |
855 | } | |
856 | ||
857 | length(num) | |
858 | int num; | |
859 | { | |
860 | printf("You made %d moves.\n",num); | |
861 | } | |
862 | ||
863 | logit(msg) | |
864 | char *msg; | |
865 | { | |
866 | FILE *logfile; | |
867 | long t; | |
868 | ||
869 | if ((logfile=fopen(LOGFILE, "a")) != NULL) { | |
870 | time(&t); | |
871 | fprintf(logfile, "%s $%d %dx%d %s %s", getlogin(), cashvalue, lcnt, ccnt, msg, ctime(&t)); | |
872 | fclose(logfile); | |
873 | } | |
874 | } |