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