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