home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / snake / snake / snake.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  17.3 KB  |  891 lines

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