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