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