]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - games/snake/snake/snake.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.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$";
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, j, k;
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
178         snrand(&finish);
179         snrand(&you);
180         snrand(&money);
181         snrand(&snake[0]);
182
183         if ((orig.sg_ospeed < B9600) ||
184             ((! CM) && (! TA))) fast=0;
185         for(i=1;i<6;i++)
186                 chase (&snake[i], &snake[i-1]);
187         setup();
188         mainloop();
189 }
190
191 /* Main command loop */
192 mainloop()
193 {
194         int j, k;
195
196         for (;;) {
197                 int c,lastc,match;
198
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 != '.') repeat = 1;
207                 }
208                 if (c == '.') {
209                         c = lastc;
210                 }
211                 if ((Klength > 0) &&
212                     (c == *KL || c == *KR || c == *KU || c == *KD)) {
213                         savec = c;
214                         match = 0;
215                         kl = KL;
216                         kr = KR;
217                         ku = KU;
218                         kd = KD;
219                         for (j=Klength;j>0;j--){
220                                 if (match != 1) {
221                                 match = 0;
222                                         if (*kl++ == c) {
223                                                 ch = 'h';
224                                                 match++;
225                                         }
226                                         if (*kr++ == c) {
227                                                 ch = 'l';
228                                                 match++;
229                                         }
230                                         if (*ku++ == c) {
231                                                 ch = 'k';
232                                                 match++;
233                                         }
234                                         if (*kd++ == c) {
235                                                 ch = 'j';
236                                                 match++;
237                                         }
238                                         if (match == 0) {
239                                                 ungetc(c,stdin);
240                                                 ch = savec;
241                 /* Oops!
242                  * This works if we figure it out on second character.
243                  */
244                                                 break;
245                                         }
246                                 }
247                                 savec = c;
248                                 if(j != 1) c = getchar() & 0177;
249                         }
250                         c = ch;
251                 }
252                 if (!fast) flushi();
253                 lastc = c;
254                 switch (c){
255                 case CTRL('z'):
256                         suspend();
257                         continue;
258                 case EOT:
259                 case 'x':
260                 case 0177:      /* del or end of file */
261                         ll();
262                         length(moves);
263                         logit("quit");
264                         done();
265                 case CTRL('l'):
266                         setup();
267                         winnings(cashvalue);
268                         continue;
269                 case 'p':
270                 case 'd':
271                         snap();
272                         continue;
273                 case 'w':
274                         spacewarp(0);
275                         continue;
276                 case 'A':
277                         repeat = you.col;
278                         c = 'h';
279                         break;
280                 case 'H':
281                 case 'S':
282                         repeat = you.col - money.col;
283                         c = 'h';
284                         break;
285                 case 'T':
286                         repeat = you.line;
287                         c = 'k';
288                         break;
289                 case 'K':
290                 case 'E':
291                         repeat = you.line - money.line;
292                         c = 'k';
293                         break;
294                 case 'P':
295                         repeat = ccnt - 1 - you.col;
296                         c = 'l';
297                         break;
298                 case 'L':
299                 case 'F':
300                         repeat = money.col - you.col;
301                         c = 'l';
302                         break;
303                 case 'B':
304                         repeat = lcnt - 1 - you.line;
305                         c = 'j';
306                         break;
307                 case 'J':
308                 case 'C':
309                         repeat = money.line - you.line;
310                         c = 'j';
311                         break;
312                 }
313                 for(k=1;k<=repeat;k++){
314                         moves++;
315                         switch(c) {
316                         case 's':
317                         case 'h':
318                         case '\b':
319                                 if (you.col >0) {
320                                         if((fast)||(k == 1))
321                                                 pchar(&you,' ');
322                                         you.col--;
323                                         if((fast) || (k == repeat) ||
324                                            (you.col == 0))
325                                                 pchar(&you,ME);
326                                 }
327                                 break;
328                         case 'f':
329                         case 'l':
330                         case ' ':
331                                 if (you.col < ccnt-1) {
332                                         if((fast)||(k == 1))
333                                                 pchar(&you,' ');
334                                         you.col++;
335                                         if((fast) || (k == repeat) ||
336                                            (you.col == ccnt-1))
337                                                 pchar(&you,ME);
338                                 }
339                                 break;
340                         case CTRL('p'):
341                         case 'e':
342                         case 'k':
343                         case 'i':
344                                 if (you.line > 0) {
345                                         if((fast)||(k == 1))
346                                                 pchar(&you,' ');
347                                         you.line--;
348                                         if((fast) || (k == repeat) ||
349                                           (you.line == 0))
350                                                 pchar(&you,ME);
351                                 }
352                                 break;
353                         case CTRL('n'):
354                         case 'c':
355                         case 'j':
356                         case LF:
357                         case 'm':
358                                 if (you.line+1 < lcnt) {
359                                         if((fast)||(k == 1))
360                                                 pchar(&you,' ');
361                                         you.line++;
362                                         if((fast) || (k == repeat) ||
363                                           (you.line == lcnt-1))
364                                                 pchar(&you,ME);
365                                 }
366                                 break;
367                         }
368
369                         if (same(&you,&money))
370                         {
371                                 char xp[20];
372                                 struct point z;
373                                 loot += 25;
374                                 if(k < repeat)
375                                         pchar(&you,' ');
376                                 do {
377                                         snrand(&money);
378                                 } while (money.col == finish.col && money.line == finish.line ||
379                                          money.col < 5 && money.line == 0 ||
380                                          money.col == you.col && money.line == you.line);
381                                 pchar(&money,TREASURE);
382                                 winnings(cashvalue);
383                                 continue;
384                         }
385                         if (same(&you,&finish))
386                         {
387                                 win(&finish);
388                                 ll();
389                                 cook();
390                                 pr("You have won with $%d.\n",cashvalue);
391                                 fflush(stdout);
392                                 logit("won");
393                                 post(cashvalue,1);
394                                 length(moves);
395                                 done();
396                         }
397                         if (pushsnake())break;
398                 }
399                 fflush(stdout);
400         }
401 }
402
403 setup(){        /*
404                  * setup the board
405                  */
406         int i;
407
408         clear();
409         pchar(&you,ME);
410         pchar(&finish,GOAL);
411         pchar(&money,TREASURE);
412         for(i=1; i<6; i++) {
413                 pchar(&snake[i],SNAKETAIL);
414         }
415         pchar(&snake[0], SNAKEHEAD);
416         drawbox();
417         fflush(stdout);
418 }
419
420 drawbox()
421 {
422         int i;
423         struct point p;
424
425         p.line = -1;
426         for (i= 0; i<ccnt; i++) {
427                 p.col = i;
428                 pchar(&p, '-');
429         }
430         p.col = ccnt;
431         for (i= -1; i<=lcnt; i++) {
432                 p.line = i;
433                 pchar(&p, '|');
434         }
435         p.col = -1;
436         for (i= -1; i<=lcnt; i++) {
437                 p.line = i;
438                 pchar(&p, '|');
439         }
440         p.line = lcnt;
441         for (i= 0; i<ccnt; i++) {
442                 p.col = i;
443                 pchar(&p, '-');
444         }
445 }
446
447 snrand(sp)
448 struct point *sp;
449 {
450         struct point p;
451         int i;
452
453         for (;;) {
454                 p.col = random() % ccnt;
455                 p.line = random() % lcnt;
456
457                 /* make sure it's not on top of something else */
458                 if (p.line == 0 && p.col < 5)
459                         continue;
460                 if (same(&p, &you))
461                         continue;
462                 if (same(&p, &money))
463                         continue;
464                 if (same(&p, &finish))
465                         continue;
466                 for (i = 0; i < 5; i++)
467                         if (same(&p, &snake[i]))
468                                 break;
469                 if (i < 5)
470                         continue;
471                 break;
472         }
473         *sp = p;
474 }
475
476 post(iscore, flag)
477 int     iscore, flag;
478 {
479         short   score = iscore;
480         short   uid;
481         short   oldbest=0;
482         short   allbwho=0, allbscore=0;
483         struct  passwd *p;
484
485         /*
486          * Neg uid, 0, and 1 cannot have scores recorded.
487          */
488         if ((uid = getuid()) <= 1) {
489                 pr("No saved scores for uid %d.\n", uid);
490                 return(1);
491         }
492         if (rawscores == -1) {
493                 pr("No score file %s: %s.\n", _PATH_RAWSCORES,
494                     strerror(errno));
495                 return(1);
496         }
497         /* Figure out what happened in the past */
498         read(rawscores, &allbscore, sizeof(short));
499         read(rawscores, &allbwho, sizeof(short));
500         lseek(rawscores, ((off_t)uid)*sizeof(short), 0);
501         read(rawscores, &oldbest, sizeof(short));
502         if (!flag)
503                 return (score > oldbest ? 1 : 0);
504
505         /* Update this jokers best */
506         if (score > oldbest) {
507                 lseek(rawscores, ((off_t)uid)*sizeof(short), 0);
508                 write(rawscores, &score, sizeof(short));
509                 pr("You bettered your previous best of $%d\n", oldbest);
510         } else
511                 pr("Your best to date is $%d\n", oldbest);
512
513         /* See if we have a new champ */
514         p = getpwuid(allbwho);
515         if (p == NULL || score > allbscore) {
516                 lseek(rawscores, (off_t)0, 0);
517                 write(rawscores, &score, sizeof(short));
518                 write(rawscores, &uid, sizeof(short));
519                 if (allbwho)
520                         pr("You beat %s's old record of $%d!\n",
521                             p->pw_name, allbscore);
522                 else
523                         pr("You set a new record!\n");
524         } else
525                 pr("The highest is %s with $%d\n", p->pw_name, allbscore);
526         close(rawscores);
527         return (1);
528 }
529
530 /*
531  * Flush typeahead to keep from buffering a bunch of chars and then
532  * overshooting.  This loses horribly at 9600 baud, but works nicely
533  * if the terminal gets behind.
534  */
535 flushi()
536 {
537         stty(0, &new);
538 }
539 int mx [8] = {
540         0, 1, 1, 1, 0,-1,-1,-1};
541 int my [8] = {
542         -1,-1, 0, 1, 1, 1, 0,-1};
543 float absv[8]= {
544         1, 1.4, 1, 1.4, 1, 1.4, 1, 1.4
545 };
546 int oldw=0;
547 chase (np, sp)
548 struct point *sp, *np;
549 {
550         /* this algorithm has bugs; otherwise the
551            snake would get too good */
552         struct point d;
553         int w, i, wt[8];
554         double v1, v2, vp, max;
555         point(&d,you.col-sp->col,you.line-sp->line);
556         v1 = sqrt( (double) (d.col*d.col + d.line*d.line) );
557         w=0;
558         max=0;
559         for(i=0; i<8; i++)
560         {
561                 vp = d.col*mx[i] + d.line*my[i];
562                 v2 = absv[i];
563                 if (v1>0)
564                         vp = ((double)vp)/(v1*v2);
565                 else vp=1.0;
566                 if (vp>max)
567                 {
568                         max=vp;
569                         w=i;
570                 }
571         }
572         for(i=0; i<8; i++)
573         {
574                 point(&d,sp->col+mx[i],sp->line+my[i]);
575                 wt[i]=0;
576                 if (d.col<0 || d.col>=ccnt || d.line<0 || d.line>=lcnt)
577                         continue;
578                 /*
579                  * Change to allow snake to eat you if you're on the money,
580                  * otherwise, you can just crouch there until the snake goes
581                  * away.  Not positive it's right.
582                  *
583                  * if (d.line == 0 && d.col < 5) continue;
584                  */
585                 if (same(&d,&money)) continue;
586                 if (same(&d,&finish)) continue;
587                 wt[i]= i==w ? loot/10 : 1;
588                 if (i==oldw) wt [i] += loot/20;
589         }
590         for(w=i=0; i<8; i++)
591                 w+= wt[i];
592         vp = random() % w;
593         for(i=0; i<8; i++)
594                 if (vp <wt[i])
595                         break;
596                 else
597                         vp -= wt[i];
598         if (i==8) {
599                 pr("failure\n");
600                 i=0;
601                 while (wt[i]==0) i++;
602         }
603         oldw=w=i;
604         point(np,sp->col+mx[w],sp->line+my[w]);
605 }
606
607 spacewarp(w)
608 int w;{
609         struct point p;
610         int j;
611         char *str;
612
613         snrand(&you);
614         point(&p,COLUMNS/2 - 8,LINES/2 - 1);
615         if (p.col < 0)
616                 p.col = 0;
617         if (p.line < 0)
618                 p.line = 0;
619         if (w) {
620                 str = "BONUS!!!";
621                 loot = loot - penalty;
622                 penalty = 0;
623         } else {
624                 str = "SPACE WARP!!!";
625                 penalty += loot/PENALTY;
626         }
627         for(j=0;j<3;j++){
628                 clear();
629                 delay(5);
630                 apr(&p,str);
631                 delay(10);
632         }
633         setup();
634         winnings(cashvalue);
635 }
636 snap()
637 {
638         struct point p;
639         int i;
640
641         if(you.line < 3){
642                 pchar(point(&p,you.col,0),'-');
643         }
644         if(you.line > lcnt-4){
645                 pchar(point(&p,you.col,lcnt-1),'_');
646         }
647         if(you.col < 10){
648                 pchar(point(&p,0,you.line),'(');
649         }
650         if(you.col > ccnt-10){
651                 pchar(point(&p,ccnt-1,you.line),')');
652         }
653         if (! stretch(&money)) if (! stretch(&finish)) delay(10);
654         if(you.line < 3){
655                 point(&p,you.col,0);
656                 chk(&p);
657         }
658         if(you.line > lcnt-4){
659                 point(&p,you.col,lcnt-1);
660                 chk(&p);
661         }
662         if(you.col < 10){
663                 point(&p,0,you.line);
664                 chk(&p);
665         }
666         if(you.col > ccnt-10){
667                 point(&p,ccnt-1,you.line);
668                 chk(&p);
669         }
670         fflush(stdout);
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 i,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 win(ps)
737 struct point *ps;
738 {
739         struct point x;
740         int j,k;
741         int boxsize;    /* actually diameter of box, not radius */
742
743         boxsize = fast ? 10 : 4;
744         point(&x,ps->col,ps->line);
745         for(j=1;j<boxsize;j++){
746                 for(k=0;k<j;k++){
747                         pchar(&x,'#');
748                         x.line--;
749                 }
750                 for(k=0;k<j;k++){
751                         pchar(&x,'#');
752                         x.col++;
753                 }
754                 j++;
755                 for(k=0;k<j;k++){
756                         pchar(&x,'#');
757                         x.line++;
758                 }
759                 for(k=0;k<j;k++){
760                         pchar(&x,'#');
761                         x.col--;
762                 }
763         }
764         fflush(stdout);
765 }
766
767 pushsnake()
768 {
769         int i, bonus;
770         int issame = 0;
771
772         /*
773          * My manual says times doesn't return a value.  Furthermore, the
774          * snake should get his turn every time no matter if the user is
775          * on a fast terminal with typematic keys or not.
776          * So I have taken the call to times out.
777          */
778         for(i=4; i>=0; i--)
779                 if (same(&snake[i], &snake[5]))
780                         issame++;
781         if (!issame)
782                 pchar(&snake[5],' ');
783         for(i=4; i>=0; i--)
784                 snake[i+1]= snake[i];
785         chase(&snake[0], &snake[1]);
786         pchar(&snake[1],SNAKETAIL);
787         pchar(&snake[0],SNAKEHEAD);
788         for(i=0; i<6; i++)
789         {
790                 if (same(&snake[i],&you))
791                 {
792                         surround(&you);
793                         i = (cashvalue) % 10;
794                         bonus = random() % 10;
795                         ll();
796                         pr("%d\n", bonus);
797                         delay(30);
798                         if (bonus == i) {
799                                 spacewarp(1);
800                                 logit("bonus");
801                                 flushi();
802                                 return(1);
803                         }
804                         if ( loot >= penalty ){
805                                 pr("You and your $%d have been eaten\n",
806                                     cashvalue);
807                         } else {
808                                 pr("The snake ate you.  You owe $%d.\n",
809                                     -cashvalue);
810                         }
811                         logit("eaten");
812                         length(moves);
813                         done();
814                 }
815         }
816         return(0);
817 }
818
819 chk(sp)
820 struct point *sp;
821 {
822         int j;
823
824         if (same(sp,&money)) {
825                 pchar(sp,TREASURE);
826                 return(2);
827         }
828         if (same(sp,&finish)) {
829                 pchar(sp,GOAL);
830                 return(3);
831         }
832         if (same(sp,&snake[0])) {
833                 pchar(sp,SNAKEHEAD);
834                 return(4);
835         }
836         for(j=1;j<6;j++){
837                 if(same(sp,&snake[j])){
838                         pchar(sp,SNAKETAIL);
839                         return(4);
840                 }
841         }
842         if ((sp->col < 4) && (sp->line == 0)){
843                 winnings(cashvalue);
844                 if((you.line == 0) && (you.col < 4)) pchar(&you,ME);
845                 return(5);
846         }
847         if (same(sp,&you)) {
848                 pchar(sp,ME);
849                 return(1);
850         }
851         pchar(sp,' ');
852         return(0);
853 }
854 winnings(won)
855 int won;
856 {
857         struct point p;
858
859         p.line = p.col = 1;
860         if(won>0){
861                 move(&p);
862                 pr("$%d",won);
863         }
864 }
865
866 void
867 stop(){
868         signal(SIGINT,SIG_IGN);
869         ll();
870         length(moves);
871         done();
872 }
873
874 suspend()
875 {
876         char *sh;
877
878         ll();
879         cook();
880         kill(getpid(), SIGTSTP);
881         raw();
882         setup();
883         winnings(cashvalue);
884 }
885
886 length(num)
887 int num;
888 {
889         pr("You made %d moves.\n",num);
890 }
891
892 logit(msg)
893 char *msg;
894 {
895         time_t t;
896
897         if (logfile != NULL) {
898                 time(&t);
899                 fprintf(logfile, "%s $%d %dx%d %s %s",
900                     getlogin(), cashvalue, lcnt, ccnt, msg, ctime(&t));
901                 fclose(logfile);
902         }
903 }