games: Massive style(9) cleanup commit. Reduces differences to NetBSD.
[dragonfly.git] / games / snake / snake / snake.c
blobc5c68f713bb74295820e69de2618b46225e4f0d5
1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
30 * @(#)snake.c 8.2 (Berkeley) 1/7/94
31 * $FreeBSD: src/games/snake/snake/snake.c,v 1.11.2.1 2000/08/17 06:21:44 jhb Exp $
32 * $DragonFly: src/games/snake/snake/snake.c,v 1.4 2006/09/03 23:47:56 pavalos Exp $
36 * snake - crt hack game.
38 * You move around the screen with arrow keys trying to pick up money
39 * without getting eaten by the snake. hjkl work as in vi in place of
40 * arrow keys. You can leave at the exit any time.
42 * compile as follows:
43 * cc -O snake.c move.c -o snake -lm -ltermlib
46 #include <sys/param.h>
48 #include <curses.h>
49 #include <fcntl.h>
50 #include <pwd.h>
51 #include <time.h>
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <sys/types.h>
55 #include <err.h>
56 #include <math.h>
57 #include <signal.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <termios.h>
63 #include "pathnames.h"
65 #define cashvalue chunk*(loot-penalty)/25
67 struct point {
68 int col, line;
71 #define same(s1, s2) ((s1)->line == (s2)->line && (s1)->col == (s2)->col)
73 #define PENALTY 10 /* % penalty for invoking spacewarp */
75 #define EOT '\004'
76 #define LF '\n'
77 #define DEL '\177'
79 #define ME 'I'
80 #define SNAKEHEAD 'S'
81 #define SNAKETAIL 's'
82 #define TREASURE '$'
83 #define GOAL '#'
85 #ifndef MIN
86 #define MIN(a, b) ((a) < (b) ? (a) : (b))
87 #endif
89 #define pchar(point, c) mvaddch((point)->line + 1, (point)->col + 1, (c))
90 #define delay(t) usleep(t * 50000);
92 struct point you;
93 struct point money;
94 struct point finish;
95 struct point snake[6];
97 int loot, penalty;
98 int moves;
99 int fast = 1;
101 int rawscores;
102 FILE *logfile;
104 int lcnt, ccnt; /* user's idea of screen size */
105 int chunk; /* amount of money given at a time */
107 void chase(struct point *, struct point *);
108 int chk(const struct point *);
109 void drawbox(void);
110 void flushi(void);
111 void home(void);
112 void length(int);
113 void logit(const char *);
114 int main(int, char **);
115 void mainloop(void) __attribute__((__noreturn__));
116 struct point *point(struct point *, int, int);
117 int post(int, int);
118 int pushsnake(void);
119 void right(const struct point *);
120 void setup(void);
121 void snap(void);
122 void snrand(struct point *);
123 void spacewarp(int);
124 void stop(int) __attribute__((__noreturn__));
125 int stretch(const struct point *);
126 void surround(struct point *);
127 void suspend(void);
128 void win(const struct point *);
129 void winnings(int);
132 main(int argc, char **argv)
134 int ch, i;
135 time_t tv;
137 /* Open score files then revoke setgid privileges */
138 rawscores = open(_PATH_RAWSCORES, O_RDWR|O_CREAT, 0664);
139 if (rawscores < 0) {
140 warn("open %s", _PATH_RAWSCORES);
141 sleep(2);
142 } else if (rawscores < 3)
143 exit(1);
144 logfile = fopen(_PATH_LOGFILE, "a");
145 if (logfile == NULL) {
146 warn("fopen %s", _PATH_LOGFILE);
147 sleep(2);
149 setgid(getgid());
151 time(&tv);
153 while ((ch = getopt(argc, argv, "l:w:t")) != -1)
154 switch ((char) ch) {
155 #ifdef DEBUG
156 case 'd':
157 tv = atol(optarg);
158 break;
159 #endif
160 case 'w': /* width */
161 ccnt = atoi(optarg);
162 break;
163 case 'l': /* length */
164 lcnt = atoi(optarg);
165 break;
166 case 't':
167 fast = 0;
168 break;
169 case '?':
170 default:
171 #ifdef DEBUG
172 fputs("usage: snake [-d seed] [-w width] [-l length] [-t]\n", stderr);
173 #else
174 fputs("usage: snake [-w width] [-l length] [-t]\n", stderr);
175 #endif
176 exit(1);
179 srandom((int) tv);
181 penalty = loot = 0;
182 initscr();
183 cbreak();
184 noecho();
185 #ifdef KEY_LEFT
186 keypad(stdscr, TRUE);
187 #endif
188 if (!lcnt || lcnt > LINES - 2)
189 lcnt = LINES - 2;
190 if (!ccnt || ccnt > COLS - 2)
191 ccnt = COLS - 2;
193 i = MIN(lcnt, ccnt);
194 if (i < 4) {
195 endwin();
196 errx(1, "screen too small for a fair game.");
200 * chunk is the amount of money the user gets for each $.
201 * The formula below tries to be fair for various screen sizes.
202 * We only pay attention to the smaller of the 2 edges, since
203 * that seems to be the bottleneck.
204 * This formula is a hyperbola which includes the following points:
205 * (24, $25) (original scoring algorithm)
206 * (12, $40) (experimentally derived by the "feel")
207 * (48, $15) (a guess)
208 * This will give a 4x4 screen $99/shot. We don't allow anything
209 * smaller than 4x4 because there is a 3x3 game where you can win
210 * an infinite amount of money.
212 if (i < 12) /* otherwise it isn't fair */
213 i = 12;
215 * Compensate for border. This really changes the game since
216 * the screen is two squares smaller but we want the default
217 * to be $25, and the high scores on small screens were a bit
218 * much anyway.
220 i += 2;
221 chunk = (675.0 / (i + 6)) + 2.5; /* min screen edge */
223 signal(SIGINT, stop);
225 snrand(&finish);
226 snrand(&you);
227 snrand(&money);
228 snrand(&snake[0]);
230 for (i = 1; i < 6; i++)
231 chase(&snake[i], &snake[i - 1]);
232 setup();
233 mainloop();
234 /* NOTREACHED */
235 return (0);
238 struct point *
239 point(struct point *ps, int x, int y)
241 ps->col = x;
242 ps->line = y;
243 return (ps);
246 /* Main command loop */
247 void
248 mainloop(void)
250 int k;
251 int repeat = 1;
252 int lastc = 0;
254 for (;;) {
255 int c;
257 /* Highlight you, not left & above */
258 move(you.line + 1, you.col + 1);
259 refresh();
260 if (((c = getch()) <= '9') && (c >= '0')) {
261 repeat = c - '0';
262 while (((c = getch()) <= '9') && (c >= '0'))
263 repeat = 10 * repeat + (c - '0');
264 } else {
265 if (c != '.')
266 repeat = 1;
268 if (c == '.') {
269 c = lastc;
271 if (!fast)
272 flushi();
273 lastc = c;
274 switch (c) {
275 case CTRL('z'):
276 suspend();
277 continue;
278 case EOT:
279 case 'x':
280 case 0177: /* del or end of file */
281 endwin();
282 length(moves);
283 logit("quit");
284 exit(0);
285 case CTRL('l'):
286 setup();
287 winnings(cashvalue);
288 continue;
289 case 'p':
290 case 'd':
291 snap();
292 continue;
293 case 'w':
294 spacewarp(0);
295 continue;
296 case 'A':
297 repeat = you.col;
298 c = 'h';
299 break;
300 case 'H':
301 case 'S':
302 repeat = you.col - money.col;
303 c = 'h';
304 break;
305 case 'T':
306 repeat = you.line;
307 c = 'k';
308 break;
309 case 'K':
310 case 'E':
311 repeat = you.line - money.line;
312 c = 'k';
313 break;
314 case 'P':
315 repeat = ccnt - 1 - you.col;
316 c = 'l';
317 break;
318 case 'L':
319 case 'F':
320 repeat = money.col - you.col;
321 c = 'l';
322 break;
323 case 'B':
324 repeat = lcnt - 1 - you.line;
325 c = 'j';
326 break;
327 case 'J':
328 case 'C':
329 repeat = money.line - you.line;
330 c = 'j';
331 break;
333 for (k = 1; k <= repeat; k++) {
334 moves++;
335 switch (c) {
336 case 's':
337 case 'h':
338 #ifdef KEY_LEFT
339 case KEY_LEFT:
340 #endif
341 case '\b':
342 if (you.col > 0) {
343 if ((fast) || (k == 1))
344 pchar(&you, ' ');
345 you.col--;
346 if ((fast) || (k == repeat) ||
347 (you.col == 0))
348 pchar(&you, ME);
350 break;
351 case 'f':
352 case 'l':
353 #ifdef KEY_RIGHT
354 case KEY_RIGHT:
355 #endif
356 case ' ':
357 if (you.col < ccnt - 1) {
358 if ((fast) || (k == 1))
359 pchar(&you, ' ');
360 you.col++;
361 if ((fast) || (k == repeat) ||
362 (you.col == ccnt - 1))
363 pchar(&you, ME);
365 break;
366 case CTRL('p'):
367 case 'e':
368 case 'k':
369 #ifdef KEY_UP
370 case KEY_UP:
371 #endif
372 case 'i':
373 if (you.line > 0) {
374 if ((fast) || (k == 1))
375 pchar(&you, ' ');
376 you.line--;
377 if ((fast) || (k == repeat) ||
378 (you.line == 0))
379 pchar(&you, ME);
381 break;
382 case CTRL('n'):
383 case 'c':
384 case 'j':
385 #ifdef KEY_DOWN
386 case KEY_DOWN:
387 #endif
388 case LF:
389 case 'm':
390 if (you.line + 1 < lcnt) {
391 if ((fast) || (k == 1))
392 pchar(&you, ' ');
393 you.line++;
394 if ((fast) || (k == repeat) ||
395 (you.line == lcnt - 1))
396 pchar(&you, ME);
398 break;
401 if (same(&you, &money)) {
402 loot += 25;
403 if (k < repeat)
404 pchar(&you, ' ');
405 do {
406 snrand(&money);
407 } while ((money.col == finish.col &&
408 money.line == finish.line) ||
409 (money.col < 5 && money.line == 0) ||
410 (money.col == you.col &&
411 money.line == you.line));
412 pchar(&money, TREASURE);
413 winnings(cashvalue);
414 continue;
416 if (same(&you, &finish)) {
417 win(&finish);
418 flushi();
419 endwin();
420 printf("You have won with $%d.\n", cashvalue);
421 fflush(stdout);
422 logit("won");
423 post(cashvalue, 1);
424 length(moves);
425 exit(0);
427 if (pushsnake())
428 break;
434 * setup the board
436 void
437 setup(void)
439 int i;
441 erase();
442 pchar(&you, ME);
443 pchar(&finish, GOAL);
444 pchar(&money, TREASURE);
445 for (i = 1; i < 6; i++) {
446 pchar(&snake[i], SNAKETAIL);
448 pchar(&snake[0], SNAKEHEAD);
449 drawbox();
450 refresh();
453 void
454 drawbox(void)
456 int i;
458 for (i = 1; i <= ccnt; i++) {
459 mvaddch(0, i, '-');
460 mvaddch(lcnt + 1, i, '-');
462 for (i = 0; i <= lcnt + 1; i++) {
463 mvaddch(i, 0, '|');
464 mvaddch(i, ccnt + 1, '|');
468 void
469 snrand(struct point *sp)
471 struct point p;
472 int i;
474 for (;;) {
475 p.col = random() % ccnt;
476 p.line = random() % lcnt;
478 /* make sure it's not on top of something else */
479 if (p.line == 0 && p.col < 5)
480 continue;
481 if (same(&p, &you))
482 continue;
483 if (same(&p, &money))
484 continue;
485 if (same(&p, &finish))
486 continue;
487 for (i = 0; i < 6; i++)
488 if (same(&p, &snake[i]))
489 break;
490 if (i < 6)
491 continue;
492 break;
494 *sp = p;
498 post(int iscore, int flag)
500 short score = iscore;
501 short uid;
502 short oldbest = 0;
503 short allbwho = 0, allbscore = 0;
504 struct passwd *p;
506 /* I want to printf() the scores for terms that clear on cook(),
507 * but this routine also gets called with flag == 0 to see if
508 * the snake should wink. If (flag) then we're at game end and
509 * can printf.
512 * Neg uid, 0, and 1 cannot have scores recorded.
514 if ((uid = getuid()) <= 1) {
515 if (flag)
516 printf("No saved scores for uid %d.\n", uid);
517 return (1);
519 if (rawscores < 0) {
520 /* Error reported earlier */
521 return (1);
523 /* Figure out what happened in the past */
524 read(rawscores, &allbscore, sizeof(short));
525 read(rawscores, &allbwho, sizeof(short));
526 lseek(rawscores, ((off_t)uid)*sizeof(short), SEEK_SET);
527 read(rawscores, &oldbest, sizeof(short));
528 if (!flag) {
529 lseek(rawscores, 0, SEEK_SET);
530 return (score > oldbest ? 1 : 0);
533 /* Update this jokers best */
534 if (score > oldbest) {
535 lseek(rawscores, ((off_t)uid)*sizeof(short), SEEK_SET);
536 write(rawscores, &score, sizeof(short));
537 printf("You bettered your previous best of $%d\n", oldbest);
538 } else
539 printf("Your best to date is $%d\n", oldbest);
541 /* See if we have a new champ */
542 p = getpwuid(allbwho);
543 if (score > allbscore) {
544 lseek(rawscores, 0, SEEK_SET);
545 write(rawscores, &score, sizeof(short));
546 write(rawscores, &uid, sizeof(short));
547 if (allbwho) {
548 if (p)
549 printf("You beat %s's old record of $%d!\n",
550 p->pw_name, allbscore);
551 else
552 printf("You beat (%d)'s old record of $%d!\n",
553 (int)allbwho, allbscore);
555 else
556 printf("You set a new record!\n");
557 } else if (p)
558 printf("The highest is %s with $%d\n", p->pw_name, allbscore);
559 else
560 printf("The highest is (%d) with $%d\n", (int)allbwho,
561 allbscore);
562 lseek(rawscores, 0, SEEK_SET);
563 return (1);
567 * Flush typeahead to keep from buffering a bunch of chars and then
568 * overshooting. This loses horribly at 9600 baud, but works nicely
569 * if the terminal gets behind.
571 void
572 flushi(void)
574 tcflush(0, TCIFLUSH);
577 int mx[8] = {
578 0, 1, 1, 1, 0, -1, -1, -1
580 int my[8] = {
581 -1, -1, 0, 1, 1, 1, 0, -1
583 float absv[8] = {
584 1, 1.4, 1, 1.4, 1, 1.4, 1, 1.4
586 int oldw = 0;
588 void
589 chase(struct point *np, struct point *sp)
591 /* this algorithm has bugs; otherwise the snake would get too good */
592 struct point d;
593 int w, i, wt[8];
594 double v1, v2, vp, max;
595 point(&d, you.col - sp->col, you.line - sp->line);
596 v1 = sqrt((double)(d.col * d.col + d.line * d.line));
597 w = 0;
598 max = 0;
599 for (i = 0; i < 8; i++) {
600 vp = d.col * mx[i] + d.line * my[i];
601 v2 = absv[i];
602 if (v1 > 0)
603 vp = ((double)vp) / (v1 * v2);
604 else
605 vp = 1.0;
606 if (vp > max) {
607 max = vp;
608 w = i;
611 for (i = 0; i < 8; i++) {
612 point(&d, sp->col + mx[i], sp->line + my[i]);
613 wt[i] = 0;
614 if (d.col < 0 || d.col >= ccnt || d.line < 0 || d.line >= lcnt)
615 continue;
617 * Change to allow snake to eat you if you're on the money,
618 * otherwise, you can just crouch there until the snake goes
619 * away. Not positive it's right.
621 * if (d.line == 0 && d.col < 5) continue;
623 if (same(&d, &money))
624 continue;
625 if (same(&d, &finish))
626 continue;
627 wt[i] = i == w ? loot / 10 : 1;
628 if (i == oldw)
629 wt[i] += loot / 20;
631 for (w = i = 0; i < 8; i++)
632 w += wt[i];
633 vp = ((random() >> 6) & 01777) % w;
634 for (i = 0; i < 8; i++)
635 if (vp < wt[i])
636 break;
637 else
638 vp -= wt[i];
639 if (i == 8) {
640 printw("failure\n");
641 i = 0;
642 while (wt[i] == 0)
643 i++;
645 oldw = w = i;
646 point(np, sp->col + mx[w], sp->line + my[w]);
649 void
650 spacewarp(int w)
652 struct point p;
653 int j;
654 const char *str;
656 snrand(&you);
657 point(&p, COLS / 2 - 8, LINES / 2 - 1);
658 if (p.col < 0)
659 p.col = 0;
660 if (p.line < 0)
661 p.line = 0;
662 if (w) {
663 str = "BONUS!!!";
664 loot = loot - penalty;
665 penalty = 0;
666 } else {
667 str = "SPACE WARP!!!";
668 penalty += loot / PENALTY;
670 for (j = 0; j < 3; j++) {
671 erase();
672 refresh();
673 delay(5);
674 mvaddstr(p.line + 1, p.col + 1, str);
675 refresh();
676 delay(10);
678 setup();
679 winnings(cashvalue);
682 void
683 snap(void)
685 if (!stretch(&money))
686 if (!stretch(&finish)) {
687 pchar(&you, '?');
688 refresh();
689 delay(10);
690 pchar(&you, ME);
692 refresh();
696 stretch(const struct point *ps)
698 struct point p;
700 point(&p, you.col, you.line);
701 if ((abs(ps->col - you.col) < (ccnt / 12)) && (you.line != ps->line)) {
702 if (you.line < ps->line) {
703 for (p.line = you.line + 1; p.line <= ps->line; p.line++)
704 pchar(&p, 'v');
705 refresh();
706 delay(10);
707 for (; p.line > you.line; p.line--)
708 chk(&p);
709 } else {
710 for (p.line = you.line - 1; p.line >= ps->line; p.line--)
711 pchar(&p, '^');
712 refresh();
713 delay(10);
714 for (; p.line < you.line; p.line++)
715 chk(&p);
717 return (1);
718 } else
719 if ((abs(ps->line - you.line) < (lcnt / 7))
720 && (you.col != ps->col)) {
721 p.line = you.line;
722 if (you.col < ps->col) {
723 for (p.col = you.col + 1; p.col <= ps->col; p.col++)
724 pchar(&p, '>');
725 refresh();
726 delay(10);
727 for (; p.col > you.col; p.col--)
728 chk(&p);
729 } else {
730 for (p.col = you.col - 1; p.col >= ps->col; p.col--)
731 pchar(&p, '<');
732 refresh();
733 delay(10);
734 for (; p.col < you.col; p.col++)
735 chk(&p);
737 return (1);
739 return (0);
742 void
743 surround(struct point *ps)
745 int j;
747 if (ps->col == 0)
748 ps->col++;
749 if (ps->line == 0)
750 ps->line++;
751 if (ps->line == LINES - 1)
752 ps->line--;
753 if (ps->col == COLS - 1)
754 ps->col--;
755 mvaddstr(ps->line, ps->col, "/*\\");
756 mvaddstr(ps->line + 1, ps->col, "* *");
757 mvaddstr(ps->line + 2, ps->col, "\\*/");
758 for (j = 0; j < 20; j++) {
759 pchar(ps, '@');
760 refresh();
761 delay(1);
762 pchar(ps, ' ');
763 refresh();
764 delay(1);
766 if (post(cashvalue, 0)) {
767 mvaddstr(ps->line, ps->col, " ");
768 mvaddstr(ps->line + 1, ps->col, "o.o");
769 mvaddstr(ps->line + 2, ps->col, "\\_/");
770 refresh();
771 delay(6);
772 mvaddstr(ps->line, ps->col, " ");
773 mvaddstr(ps->line + 1, ps->col, "o.-");
774 mvaddstr(ps->line + 2, ps->col, "\\_/");
775 refresh();
776 delay(6);
778 mvaddstr(ps->line, ps->col, " ");
779 mvaddstr(ps->line + 1, ps->col, "o.o");
780 mvaddstr(ps->line + 2, ps->col, "\\_/");
781 refresh();
782 delay(6);
785 void
786 win(const struct point *ps)
788 struct point x;
789 int j, k;
790 int boxsize; /* actually diameter of box, not radius */
792 boxsize = fast ? 10 : 4;
793 point(&x, ps->col, ps->line);
794 for (j = 1; j < boxsize; j++) {
795 for (k = 0; k < j; k++) {
796 pchar(&x, '#');
797 x.line--;
799 for (k = 0; k < j; k++) {
800 pchar(&x, '#');
801 x.col++;
803 j++;
804 for (k = 0; k < j; k++) {
805 pchar(&x, '#');
806 x.line++;
808 for (k = 0; k < j; k++) {
809 pchar(&x, '#');
810 x.col--;
812 refresh();
813 delay(1);
818 pushsnake(void)
820 int i, bonus;
821 int issame = 0;
822 struct point tmp;
825 * My manual says times doesn't return a value. Furthermore, the
826 * snake should get his turn every time no matter if the user is
827 * on a fast terminal with typematic keys or not.
828 * So I have taken the call to times out.
830 for (i = 4; i >= 0; i--)
831 if (same(&snake[i], &snake[5]))
832 issame++;
833 if (!issame)
834 pchar(&snake[5], ' ');
835 /* Need the following to catch you if you step on the snake's tail */
836 tmp.col = snake[5].col;
837 tmp.line = snake[5].line;
838 for (i = 4; i >= 0; i--)
839 snake[i + 1] = snake[i];
840 chase(&snake[0], &snake[1]);
841 pchar(&snake[1], SNAKETAIL);
842 pchar(&snake[0], SNAKEHEAD);
843 for (i = 0; i < 6; i++) {
844 if (same(&snake[i], &you) || same(&tmp, &you)) {
845 surround(&you);
846 i = (cashvalue) % 10;
847 bonus = ((random() >> 8) & 0377) % 10;
848 mvprintw(lcnt + 1, 0, "%d\n", bonus);
849 refresh();
850 delay(30);
851 if (bonus == i) {
852 spacewarp(1);
853 logit("bonus");
854 flushi();
855 return (1);
857 flushi();
858 endwin();
859 if (loot >= penalty) {
860 printf("\nYou and your $%d have been eaten\n",
861 cashvalue);
862 } else {
863 printf("\nThe snake ate you. You owe $%d.\n",
864 -cashvalue);
866 logit("eaten");
867 length(moves);
868 exit(0);
871 return (0);
875 chk(const struct point *sp)
877 int j;
879 if (same(sp, &money)) {
880 pchar(sp, TREASURE);
881 return (2);
883 if (same(sp, &finish)) {
884 pchar(sp, GOAL);
885 return (3);
887 if (same(sp, &snake[0])) {
888 pchar(sp, SNAKEHEAD);
889 return (4);
891 for (j = 1; j < 6; j++) {
892 if (same(sp, &snake[j])) {
893 pchar(sp, SNAKETAIL);
894 return (4);
897 if ((sp->col < 4) && (sp->line == 0)) {
898 winnings(cashvalue);
899 if ((you.line == 0) && (you.col < 4))
900 pchar(&you, ME);
901 return (5);
903 if (same(sp, &you)) {
904 pchar(sp, ME);
905 return (1);
907 pchar(sp, ' ');
908 return (0);
911 void
912 winnings(int won)
914 if (won > 0) {
915 mvprintw(1, 1, "$%d", won);
919 void
920 stop(int dummy __unused)
922 signal(SIGINT, SIG_IGN);
923 endwin();
924 length(moves);
925 exit(0);
928 void
929 suspend(void)
931 endwin();
932 kill(getpid(), SIGTSTP);
933 refresh();
934 winnings(cashvalue);
937 void
938 length(int num)
940 printf("You made %d moves.\n", num);
943 void
944 logit(const char *msg)
946 time_t t;
948 if (logfile != NULL) {
949 time(&t);
950 fprintf(logfile, "%s $%d %dx%d %s %s",
951 getlogin(), cashvalue, lcnt, ccnt, msg, ctime(&t));
952 fflush(logfile);