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