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