1 /*
2  * Copyright (c) 1982 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 char copyright[] =
9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10  All rights reserved.\n";
11 #endif not lint
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)canfield.c	5.1 (Berkeley) 05/29/85";
15 #endif not lint
16 
17 /*
18  * The canfield program
19  *
20  * Authors:
21  *	Originally written: Steve Levine
22  *	Converted to use curses and debugged: Steve Feldman
23  *	Card counting: Kirk McKusick and Mikey Olson
24  *	User interface cleanups: Eric Allman and Kirk McKusick
25  *	Betting by Kirk McKusick
26  */
27 
28 #include <curses.h>
29 #include <ctype.h>
30 #include <signal.h>
31 #include <sys/types.h>
32 
33 #define	decksize	52
34 #define originrow	0
35 #define origincol	0
36 #define	basecol		1
37 #define	boxcol		42
38 #define	tboxrow		2
39 #define	bboxrow		17
40 #define	movecol		43
41 #define	moverow		16
42 #define	msgcol		43
43 #define	msgrow		15
44 #define	titlecol	30
45 #define	titlerow	0
46 #define	sidecol		1
47 #define	ottlrow		6
48 #define	foundcol	11
49 #define	foundrow	3
50 #define	stockcol	2
51 #define	stockrow	8
52 #define	fttlcol		10
53 #define	fttlrow		1
54 #define	taloncol	2
55 #define	talonrow	13
56 #define	tabrow		8
57 #define ctoprow		21
58 #define cbotrow		23
59 #define cinitcol	14
60 #define cheightcol	1
61 #define cwidthcol	4
62 #define handstatrow	21
63 #define handstatcol	7
64 #define talonstatrow	22
65 #define talonstatcol	7
66 #define stockstatrow	23
67 #define stockstatcol	7
68 #define	Ace		1
69 #define	Jack		11
70 #define	Queen		12
71 #define	King		13
72 #define	atabcol		11
73 #define	btabcol		18
74 #define	ctabcol		25
75 #define	dtabcol		32
76 
77 #define	spades		's'
78 #define	clubs		'c'
79 #define	hearts		'h'
80 #define	diamonds	'd'
81 #define	black		'b'
82 #define	red		'r'
83 
84 #define stk		1
85 #define	tal		2
86 #define tab		3
87 #define INCRHAND(row, col) {\
88 	row -= cheightcol;\
89 	if (row < ctoprow) {\
90 		row = cbotrow;\
91 		col += cwidthcol;\
92 	}\
93 }
94 #define DECRHAND(row, col) {\
95 	row += cheightcol;\
96 	if (row > cbotrow) {\
97 		row = ctoprow;\
98 		col -= cwidthcol;\
99 	}\
100 }
101 
102 
103 struct cardtype {
104 	char suit;
105 	char color;
106 	bool visible;
107 	bool paid;
108 	int rank;
109 	struct cardtype *next;
110 };
111 
112 #define	NIL	((struct cardtype *) -1)
113 
114 struct cardtype *deck[decksize];
115 struct cardtype cards[decksize];
116 struct cardtype *bottom[4], *found[4], *tableau[4];
117 struct cardtype *talon, *hand, *stock, *basecard;
118 int length[4];
119 int cardsoff, base, cinhand, taloncnt, stockcnt, timesthru;
120 char suitmap[4] = {spades, clubs, hearts, diamonds};
121 char colormap[4] = {black, black, red, red};
122 char pilemap[4] = {atabcol, btabcol, ctabcol, dtabcol};
123 char srcpile, destpile;
124 int mtforigin, tempbase;
125 int coldcol, cnewcol, coldrow, cnewrow;
126 bool errmsg, done;
127 bool mtfdone, Cflag = FALSE;
128 #define INSTRUCTIONBOX	1
129 #define BETTINGBOX	2
130 #define NOBOX		3
131 int status = INSTRUCTIONBOX;
132 
133 /*
134  * Basic betting costs
135  */
136 #define costofhand		13
137 #define costofinspection	13
138 #define costofgame		26
139 #define costofrunthroughhand	 5
140 #define costofinformation	 1
141 #define secondsperdollar	60
142 #define valuepercardup	 	 5
143 /*
144  * Variables associated with betting
145  */
146 struct betinfo {
147 	long	hand;		/* cost of dealing hand */
148 	long	inspection;	/* cost of inspecting hand */
149 	long	game;		/* cost of buying game */
150 	long	runs;		/* cost of running through hands */
151 	long	information;	/* cost of information */
152 	long	thinktime;	/* cost of thinking time */
153 	long	wins;		/* total winnings */
154 	long	worth;		/* net worth after costs */
155 };
156 struct betinfo this, total;
157 bool startedgame = FALSE, infullgame = FALSE;
158 time_t acctstart;
159 int dbfd = -1;
160 
161 /*
162  * The following procedures print the board onto the screen using the
163  * addressible cursor. The end of these procedures will also be
164  * separated from the rest of the program.
165  *
166  * procedure to set the move command box
167  */
168 movebox()
169 {
170 	switch (status) {
171 	case BETTINGBOX:
172 		printtopbettingbox();
173 		break;
174 	case NOBOX:
175 		clearabovemovebox();
176 		break;
177 	case INSTRUCTIONBOX:
178 		printtopinstructions();
179 		break;
180 	}
181 	move(moverow, boxcol);
182 	printw("|                          |");
183 	move(msgrow, boxcol);
184 	printw("|                          |");
185 	switch (status) {
186 	case BETTINGBOX:
187 		printbottombettingbox();
188 		break;
189 	case NOBOX:
190 		clearbelowmovebox();
191 		break;
192 	case INSTRUCTIONBOX:
193 		printbottominstructions();
194 		break;
195 	}
196 	refresh();
197 }
198 
199 /*
200  * print directions above move box
201  */
202 printtopinstructions()
203 {
204 	    move(tboxrow, boxcol);
205 	    printw("*--------------------------*");
206 	    move(tboxrow + 1, boxcol);
207 	    printw("|         MOVES            |");
208 	    move(tboxrow + 2, boxcol);
209 	    printw("|s# = stock to tableau     |");
210 	    move(tboxrow + 3, boxcol);
211 	    printw("|sf = stock to foundation  |");
212 	    move(tboxrow + 4, boxcol);
213 	    printw("|t# = talon to tableau     |");
214 	    move(tboxrow + 5, boxcol);
215 	    printw("|tf = talon to foundation  |");
216 	    move(tboxrow + 6, boxcol);
217 	    printw("|## = tableau to tableau   |");
218 	    move(tboxrow + 7, boxcol);
219 	    printw("|#f = tableau to foundation|");
220 	    move(tboxrow + 8, boxcol);
221 	    printw("|ht = hand to talon        |");
222 	    move(tboxrow + 9, boxcol);
223 	    printw("|c = toggle card counting  |");
224 	    move(tboxrow + 10, boxcol);
225 	    printw("|b = present betting info  |");
226 	    move(tboxrow + 11, boxcol);
227 	    printw("|q = quit to end the game  |");
228 	    move(tboxrow + 12, boxcol);
229 	    printw("|==========================|");
230 }
231 
232 /*
233  * Print the betting box.
234  */
235 printtopbettingbox()
236 {
237 
238 	    move(tboxrow, boxcol);
239 	    printw("                            ");
240 	    move(tboxrow + 1, boxcol);
241 	    printw("*--------------------------*");
242 	    move(tboxrow + 2, boxcol);
243 	    printw("|Costs        Hand   Total |");
244 	    move(tboxrow + 3, boxcol);
245 	    printw("| Hands                    |");
246 	    move(tboxrow + 4, boxcol);
247 	    printw("| Inspections              |");
248 	    move(tboxrow + 5, boxcol);
249 	    printw("| Games                    |");
250 	    move(tboxrow + 6, boxcol);
251 	    printw("| Runs                     |");
252 	    move(tboxrow + 7, boxcol);
253 	    printw("| Information              |");
254 	    move(tboxrow + 8, boxcol);
255 	    printw("| Think time               |");
256 	    move(tboxrow + 9, boxcol);
257 	    printw("|Total Costs               |");
258 	    move(tboxrow + 10, boxcol);
259 	    printw("|Winnings                  |");
260 	    move(tboxrow + 11, boxcol);
261 	    printw("|Net Worth                 |");
262 	    move(tboxrow + 12, boxcol);
263 	    printw("|==========================|");
264 }
265 
266 /*
267  * clear info above move box
268  */
269 clearabovemovebox()
270 {
271 	int i;
272 
273 	for (i = 0; i <= 11; i++) {
274 		move(tboxrow + i, boxcol);
275 		printw("                            ");
276 	}
277 	move(tboxrow + 12, boxcol);
278 	printw("*--------------------------*");
279 }
280 
281 /*
282  * print instructions below move box
283  */
284 printbottominstructions()
285 {
286 	    move(bboxrow, boxcol);
287 	    printw("|Replace # with the number |");
288 	    move(bboxrow + 1, boxcol);
289 	    printw("|of the tableau you want.  |");
290 	    move(bboxrow + 2, boxcol);
291 	    printw("*--------------------------*");
292 }
293 
294 /*
295  * print betting information below move box
296  */
297 printbottombettingbox()
298 {
299 	    move(bboxrow, boxcol);
300 	    printw("|x = toggle information box|");
301 	    move(bboxrow + 1, boxcol);
302 	    printw("|i = list instructions     |");
303 	    move(bboxrow + 2, boxcol);
304 	    printw("*--------------------------*");
305 }
306 
307 /*
308  * clear info below move box
309  */
310 clearbelowmovebox()
311 {
312 	int i;
313 
314 	move(bboxrow, boxcol);
315 	printw("*--------------------------*");
316 	for (i = 1; i <= 2; i++) {
317 		move(bboxrow + i, boxcol);
318 		printw("                            ");
319 	}
320 }
321 
322 /*
323  * procedure to put the board on the screen using addressable cursor
324  */
325 makeboard()
326 {
327 	clear();
328 	refresh();
329 	move(titlerow, titlecol);
330 	printw("=-> CANFIELD <-=");
331 	move(fttlrow, fttlcol);
332 	printw("foundation");
333 	move(foundrow - 1, fttlcol);
334 	printw("=---=  =---=  =---=  =---=");
335 	move(foundrow, fttlcol);
336 	printw("|   |  |   |  |   |  |   |");
337 	move(foundrow + 1, fttlcol);
338 	printw("=---=  =---=  =---=  =---=");
339 	move(ottlrow, sidecol);
340 	printw("stock     tableau");
341 	move(stockrow - 1, sidecol);
342 	printw("=---=");
343 	move(stockrow, sidecol);
344 	printw("|   |");
345 	move(stockrow + 1, sidecol);
346 	printw("=---=");
347 	move(talonrow - 2, sidecol);
348 	printw("talon");
349 	move(talonrow - 1, sidecol);
350 	printw("=---=");
351 	move(talonrow, sidecol);
352 	printw("|   |");
353 	move(talonrow + 1, sidecol);
354 	printw("=---=");
355 	move(tabrow - 1, atabcol);
356 	printw("-1-    -2-    -3-    -4-");
357 	movebox();
358 }
359 
360 /*
361  * clean up the board for another game
362  */
363 cleanupboard()
364 {
365 	int cnt, row, col;
366 	struct cardtype *ptr;
367 
368 	if (Cflag) {
369 		clearstat();
370 		for(ptr = stock, row = stockrow;
371 		    ptr != NIL;
372 		    ptr = ptr->next, row++) {
373 			move(row, sidecol);
374 			printw("     ");
375 		}
376 		move(row, sidecol);
377 		printw("     ");
378 		move(stockrow + 1, sidecol);
379 		printw("=---=");
380 		move(talonrow - 2, sidecol);
381 		printw("talon");
382 		move(talonrow - 1, sidecol);
383 		printw("=---=");
384 		move(talonrow + 1, sidecol);
385 		printw("=---=");
386 	}
387 	move(stockrow, sidecol);
388 	printw("|   |");
389 	move(talonrow, sidecol);
390 	printw("|   |");
391 	move(foundrow, fttlcol);
392 	printw("|   |  |   |  |   |  |   |");
393 	for (cnt = 0; cnt < 4; cnt++) {
394 		switch(cnt) {
395 		case 0:
396 			col = atabcol;
397 			break;
398 		case 1:
399 			col = btabcol;
400 			break;
401 		case 2:
402 			col = ctabcol;
403 			break;
404 		case 3:
405 			col = dtabcol;
406 			break;
407 		}
408 		for(ptr = tableau[cnt], row = tabrow;
409 		    ptr != NIL;
410 		    ptr = ptr->next, row++)
411 			removecard(col, row);
412 	}
413 }
414 
415 /*
416  * procedure to create a deck of cards
417  */
418 initdeck(deck)
419 	struct cardtype *deck[];
420 {
421 	int i;
422 	int scnt;
423 	char s;
424 	int r;
425 
426 	i = 0;
427 	for (scnt=0; scnt<4; scnt++) {
428 		s = suitmap[scnt];
429 		for (r=Ace; r<=King; r++) {
430 			deck[i] = &cards[i];
431 			cards[i].rank = r;
432 			cards[i].suit = s;
433 			cards[i].color = colormap[scnt];
434 			cards[i].next = NIL;
435 			i++;
436 		}
437 	}
438 }
439 
440 /*
441  * procedure to shuffle the deck
442  */
443 shuffle(deck)
444 	struct cardtype *deck[];
445 {
446 	int i,j;
447 	struct cardtype *temp;
448 
449 	for (i=0; i<decksize; i++) {
450 		deck[i]->visible = FALSE;
451 		deck[i]->paid = FALSE;
452 	}
453 	for (i = decksize-1; i>=0; i--) {
454 		j = random() % decksize;
455 		if (i != j) {
456 			temp = deck[i];
457 			deck[i] = deck[j];
458 			deck[j] = temp;
459 		}
460 	}
461 }
462 
463 /*
464  * procedure to remove the card from the board
465  */
466 removecard(a, b)
467 {
468 	move(b, a);
469 	printw("   ");
470 }
471 
472 /*
473  * procedure to print the cards on the board
474  */
475 printrank(a, b, cp, inverse)
476 	struct cardtype *cp;
477 	bool inverse;
478 {
479 	move(b, a);
480 	if (cp->rank != 10)
481 		addch(' ');
482 	if (inverse)
483 		standout();
484 	switch (cp->rank) {
485 		case 2: case 3: case 4: case 5: case 6: case 7:
486 		case 8: case 9: case 10:
487 			printw("%d", cp->rank);
488 			break;
489 		case Ace:
490 			addch('A');
491 			break;
492 		case Jack:
493 			addch('J');
494 			break;
495 		case Queen:
496 			addch('Q');
497 			break;
498 		case King:
499 			addch('K');
500 	}
501 	if (inverse)
502 		standend();
503 }
504 
505 /*
506  * procedure to print out a card
507  */
508 printcard(a, b, cp)
509 	int a,b;
510 	struct cardtype *cp;
511 {
512 	if (cp == NIL)
513 		removecard(a, b);
514 	else if (cp->visible == FALSE) {
515 		move(b, a);
516 		printw(" ? ");
517 	} else {
518 		bool inverse = (cp->suit == 'd' || cp->suit == 'h');
519 
520 		printrank(a, b, cp, inverse);
521 		if (inverse)
522 			standout();
523 		addch(cp->suit);
524 		if (inverse)
525 			standend();
526 	}
527 }
528 
529 /*
530  * procedure to move the top card from one location to the top
531  * of another location. The pointers always point to the top
532  * of the piles.
533  */
534 transit(source, dest)
535 	struct cardtype **source, **dest;
536 {
537 	struct cardtype *temp;
538 
539 	temp = *source;
540 	*source = (*source)->next;
541 	temp->next = *dest;
542 	*dest = temp;
543 }
544 
545 /*
546  * Procedure to set the cards on the foundation base when available.
547  * Note that it is only called on a foundation pile at the beginning of
548  * the game, so the pile will have exactly one card in it.
549  */
550 fndbase(cp, column, row)
551 	struct cardtype **cp;
552 {
553 	bool nomore;
554 
555 	if (*cp != NIL)
556 		do {
557 			if ((*cp)->rank == basecard->rank) {
558 				base++;
559 				printcard(pilemap[base], foundrow, *cp);
560 				if (*cp == tableau[0])
561 					length[0] = length[0] - 1;
562 				if (*cp == tableau[1])
563 					length[1] = length[1] - 1;
564 				if (*cp == tableau[2])
565 					length[2] = length[2] - 1;
566 				if (*cp == tableau[3])
567 					length[3] = length[3] - 1;
568 				transit(cp, &found[base]);
569 				if (cp == &talon)
570 					usedtalon();
571 				if (cp == &stock)
572 					usedstock();
573 				if (*cp != NIL) {
574 					printcard(column, row, *cp);
575 					nomore = FALSE;
576 				} else {
577 					removecard(column, row);
578 					nomore = TRUE;
579 				}
580 				cardsoff++;
581 				if (infullgame) {
582 					this.wins += valuepercardup;
583 					total.wins += valuepercardup;
584 				}
585 			} else
586 				nomore = TRUE;
587 	} while (nomore == FALSE);
588 }
589 
590 /*
591  * procedure to initialize the things necessary for the game
592  */
593 initgame()
594 {
595 	register i;
596 
597 	for (i=0; i<18; i++) {
598 		deck[i]->visible = TRUE;
599 		deck[i]->paid = TRUE;
600 	}
601 	stockcnt = 13;
602 	stock = deck[12];
603 	for (i=12; i>=1; i--)
604 		deck[i]->next = deck[i - 1];
605 	deck[0]->next = NIL;
606 	found[0] = deck[13];
607 	deck[13]->next = NIL;
608 	for (i=1; i<4; i++)
609 		found[i] = NIL;
610 	basecard = found[0];
611 	for (i=14; i<18; i++) {
612 		tableau[i - 14] = deck[i];
613 		deck[i]->next = NIL;
614 	}
615 	for (i=0; i<4; i++) {
616 		bottom[i] = tableau[i];
617 		length[i] = tabrow;
618 	}
619 	hand = deck[18];
620 	for (i=18; i<decksize-1; i++)
621 		deck[i]->next = deck[i + 1];
622 	deck[decksize-1]->next = NIL;
623 	talon = NIL;
624 	base = 0;
625 	cinhand = 34;
626 	taloncnt = 0;
627 	timesthru = 0;
628 	cardsoff = 1;
629 	coldrow = ctoprow;
630 	coldcol = cinitcol;
631 	cnewrow = ctoprow;
632 	cnewcol = cinitcol + cwidthcol;
633 }
634 
635 /*
636  * procedure to print the beginning cards and to start each game
637  */
638 startgame()
639 {
640 	register int j;
641 
642 	shuffle(deck);
643 	initgame();
644 	this.hand = costofhand;
645 	total.hand += costofhand;
646 	this.inspection = 0;
647 	this.game = 0;
648 	this.runs = 0;
649 	this.information = 0;
650 	this.wins = 0;
651 	this.thinktime = 0;
652 	infullgame = FALSE;
653 	startedgame = FALSE;
654 	printcard(foundcol, foundrow, found[0]);
655 	printcard(stockcol, stockrow, stock);
656 	printcard(atabcol, tabrow, tableau[0]);
657 	printcard(btabcol, tabrow, tableau[1]);
658 	printcard(ctabcol, tabrow, tableau[2]);
659 	printcard(dtabcol, tabrow, tableau[3]);
660 	printcard(taloncol, talonrow, talon);
661 	move(foundrow - 2, basecol);
662 	printw("Base");
663 	move(foundrow - 1, basecol);
664 	printw("Rank");
665 	printrank(basecol, foundrow, found[0], 0);
666 	for (j=0; j<=3; j++)
667 		fndbase(&tableau[j], pilemap[j], tabrow);
668 	fndbase(&stock, stockcol, stockrow);
669 	showstat();	/* show card counting info to cheaters */
670 	movetotalon();
671 	updatebettinginfo();
672 }
673 
674 /*
675  * procedure to clear the message printed from an error
676  */
677 clearmsg()
678 {
679 	int i;
680 
681 	if (errmsg == TRUE) {
682 		errmsg = FALSE;
683 		move(msgrow, msgcol);
684 		for (i=0; i<25; i++)
685 			addch(' ');
686 		refresh();
687 	}
688 }
689 
690 /*
691  * procedure to print an error message if the move is not listed
692  */
693 dumberror()
694 {
695 	errmsg = TRUE;
696 	move(msgrow, msgcol);
697 	printw("Not a proper move       ");
698 }
699 
700 /*
701  * procedure to print an error message if the move is not possible
702  */
703 destinerror()
704 {
705 	errmsg = TRUE;
706 	move(msgrow, msgcol);
707 	printw("Error: Can't move there");
708 }
709 
710 /*
711  * function to see if the source has cards in it
712  */
713 bool
714 notempty(cp)
715 struct cardtype *cp;
716 {
717 	if (cp == NIL) {
718 		errmsg = TRUE;
719 		move(msgrow, msgcol);
720 		printw("Error: no cards to move");
721 		return (FALSE);
722 	} else
723 		return (TRUE);
724 }
725 
726 /*
727  * function to see if the rank of one card is less than another
728  */
729 bool
730 ranklower(cp1, cp2)
731 	struct cardtype *cp1, *cp2;
732 {
733 	if (cp2->rank == Ace)
734 		if (cp1->rank == King)
735 			return (TRUE);
736 		else
737 			return (FALSE);
738 	else if (cp1->rank + 1 == cp2->rank)
739 		return (TRUE);
740 	else
741 		return (FALSE);
742 }
743 
744 /*
745  * function to check the cardcolor for moving to a tableau
746  */
747 bool
748 diffcolor(cp1, cp2)
749 	struct cardtype *cp1, *cp2;
750 {
751 	if (cp1->color == cp2->color)
752 		return (FALSE);
753 	else
754 		return (TRUE);
755 }
756 
757 /*
758  * function to see if the card can move to the tableau
759  */
760 bool
761 tabok(cp, des)
762 	struct cardtype *cp;
763 {
764 	if ((cp == stock) && (tableau[des] == NIL))
765 		return (TRUE);
766 	else if (tableau[des] == NIL)
767 		if (stock == NIL)
768 			return (TRUE);
769 		else
770 			return (FALSE);
771 	else if (ranklower(cp, tableau[des]) && diffcolor(cp, tableau[des]))
772 		return (TRUE);
773 	else
774 		return (FALSE);
775 }
776 
777 /*
778  * procedure to turn the cards onto the talon from the deck
779  */
780 movetotalon()
781 {
782 	int i, fin;
783 
784 	if (cinhand >= 3)
785 		fin = 3;
786 	else if (cinhand > 0)
787 		fin = cinhand;
788 	else if (talon != NIL) {
789 		timesthru++;
790 		errmsg = TRUE;
791 		move(msgrow, msgcol);
792 		if (timesthru != 4) {
793 			printw("Talon is now the new hand");
794 			this.runs += costofrunthroughhand;
795 			total.runs += costofrunthroughhand;
796 			while (talon != NIL) {
797 				transit(&talon, &hand);
798 				cinhand++;
799 			}
800 			if (cinhand >= 3)
801 				fin = 3;
802 			else
803 				fin = cinhand;
804 			taloncnt = 0;
805 			coldrow = ctoprow;
806 			coldcol = cinitcol;
807 			cnewrow = ctoprow;
808 			cnewcol = cinitcol + cwidthcol;
809 			clearstat();
810 			showstat();
811 		} else {
812 			fin = 0;
813 			done = TRUE;
814 			printw("I believe you have lost");
815 			refresh();
816 			sleep(5);
817 		}
818 	} else {
819 		errmsg = TRUE;
820 		move(msgrow, msgcol);
821 		printw("Talon and hand are empty");
822 		fin = 0;
823 	}
824 	for (i=0; i<fin; i++) {
825 		transit(&hand, &talon);
826 		INCRHAND(cnewrow, cnewcol);
827 		INCRHAND(coldrow, coldcol);
828 		removecard(cnewcol, cnewrow);
829 		if (i == fin - 1)
830 			talon->visible = TRUE;
831 		if (Cflag) {
832 			if (talon->paid == FALSE && talon->visible == TRUE) {
833 				this.information += costofinformation;
834 				total.information += costofinformation;
835 				talon->paid = TRUE;
836 			}
837 			printcard(coldcol, coldrow, talon);
838 		}
839 	}
840 	if (fin != 0) {
841 		printcard(taloncol, talonrow, talon);
842 		cinhand -= fin;
843 		taloncnt += fin;
844 		if (Cflag) {
845 			move(handstatrow, handstatcol);
846 			printw("%3d", cinhand);
847 			move(talonstatrow, talonstatcol);
848 			printw("%3d", taloncnt);
849 		}
850 		fndbase(&talon, taloncol, talonrow);
851 	}
852 }
853 
854 
855 /*
856  * procedure to print card counting info on screen
857  */
858 showstat()
859 {
860 	int row, col;
861 	register struct cardtype *ptr;
862 
863 	if (!Cflag)
864 		return;
865 	move(talonstatrow, talonstatcol - 7);
866 	printw("Talon: %3d", taloncnt);
867 	move(handstatrow, handstatcol - 7);
868 	printw("Hand:  %3d", cinhand);
869 	move(stockstatrow, stockstatcol - 7);
870 	printw("Stock: %3d", stockcnt);
871 	for ( row = coldrow, col = coldcol, ptr = talon;
872 	      ptr != NIL;
873 	      ptr = ptr->next ) {
874 		if (ptr->paid == FALSE && ptr->visible == TRUE) {
875 			ptr->paid = TRUE;
876 			this.information += costofinformation;
877 			total.information += costofinformation;
878 		}
879 		printcard(col, row, ptr);
880 		DECRHAND(row, col);
881 	}
882 	for ( row = cnewrow, col = cnewcol, ptr = hand;
883 	      ptr != NIL;
884 	      ptr = ptr->next ) {
885 		if (ptr->paid == FALSE && ptr->visible == TRUE) {
886 			ptr->paid = TRUE;
887 			this.information += costofinformation;
888 			total.information += costofinformation;
889 		}
890 		INCRHAND(row, col);
891 		printcard(col, row, ptr);
892 	}
893 }
894 
895 /*
896  * procedure to clear card counting info from screen
897  */
898 clearstat()
899 {
900 	int row;
901 
902 	move(talonstatrow, talonstatcol - 7);
903 	printw("          ");
904 	move(handstatrow, handstatcol - 7);
905 	printw("          ");
906 	move(stockstatrow, stockstatcol - 7);
907 	printw("          ");
908 	for ( row = ctoprow ; row <= cbotrow ; row++ ) {
909 		move(row, cinitcol);
910 		printw("%56s", " ");
911 	}
912 }
913 
914 /*
915  * procedure to update card counting base
916  */
917 usedtalon()
918 {
919 	removecard(coldcol, coldrow);
920 	DECRHAND(coldrow, coldcol);
921 	if (talon != NIL && (talon->visible == FALSE)) {
922 		talon->visible = TRUE;
923 		if (Cflag) {
924 			this.information += costofinformation;
925 			total.information += costofinformation;
926 			talon->paid = TRUE;
927 			printcard(coldcol, coldrow, talon);
928 		}
929 	}
930 	taloncnt--;
931 	if (Cflag) {
932 		move(talonstatrow, talonstatcol);
933 		printw("%3d", taloncnt);
934 	}
935 }
936 
937 /*
938  * procedure to update stock card counting base
939  */
940 usedstock()
941 {
942 	stockcnt--;
943 	if (Cflag) {
944 		move(stockstatrow, stockstatcol);
945 		printw("%3d", stockcnt);
946 	}
947 }
948 
949 /*
950  * let 'em know how they lost!
951  */
952 showcards()
953 {
954 	register struct cardtype *ptr;
955 	int row;
956 
957 	if (!Cflag)
958 		return;
959 	for (ptr = talon; ptr != NIL; ptr = ptr->next) {
960 		ptr->visible = TRUE;
961 		ptr->paid = TRUE;
962 	}
963 	for (ptr = hand; ptr != NIL; ptr = ptr->next) {
964 		ptr->visible = TRUE;
965 		ptr->paid = TRUE;
966 	}
967 	showstat();
968 	move(stockrow + 1, sidecol);
969 	printw("     ");
970 	move(talonrow - 2, sidecol);
971 	printw("     ");
972 	move(talonrow - 1, sidecol);
973 	printw("     ");
974 	move(talonrow, sidecol);
975 	printw("     ");
976 	move(talonrow + 1, sidecol);
977 	printw("     ");
978 	for (ptr = stock, row = stockrow; ptr != NIL; ptr = ptr->next, row++) {
979 		move(row, stockcol - 1);
980 		printw("|   |");
981 		printcard(stockcol, row, ptr);
982 	}
983 	if (stock == NIL) {
984 		move(row, stockcol - 1);
985 		printw("|   |");
986 		row++;
987 	}
988 	move(handstatrow, handstatcol - 7);
989 	printw("          ");
990 	move(row, stockcol - 1);
991 	printw("=---=");
992 	getcmd(moverow, movecol, "Hit return to exit");
993 }
994 
995 /*
996  * procedure to update the betting values
997  */
998 updatebettinginfo()
999 {
1000 	long thiscosts, totalcosts;
1001 	time_t now;
1002 	register long dollars;
1003 
1004 	time(&now);
1005 	dollars = (now - acctstart) / secondsperdollar;
1006 	if (dollars > 0) {
1007 		this.thinktime += dollars;
1008 		total.thinktime += dollars;
1009 		acctstart += dollars * secondsperdollar;
1010 	}
1011 	thiscosts = this.hand + this.inspection + this.game +
1012 		this.runs + this.information + this.thinktime;
1013 	totalcosts = total.hand + total.inspection + total.game +
1014 		total.runs + total.information + total.thinktime;
1015 	this.worth = this.wins - thiscosts;
1016 	total.worth = total.wins - totalcosts;
1017 	if (status != BETTINGBOX)
1018 		return;
1019 	move(tboxrow + 3, boxcol + 13);
1020 	printw("%4d%9d", this.hand, total.hand);
1021 	move(tboxrow + 4, boxcol + 13);
1022 	printw("%4d%9d", this.inspection, total.inspection);
1023 	move(tboxrow + 5, boxcol + 13);
1024 	printw("%4d%9d", this.game, total.game);
1025 	move(tboxrow + 6, boxcol + 13);
1026 	printw("%4d%9d", this.runs, total.runs);
1027 	move(tboxrow + 7, boxcol + 13);
1028 	printw("%4d%9d", this.information, total.information);
1029 	move(tboxrow + 8, boxcol + 13);
1030 	printw("%4d%9d", this.thinktime, total.thinktime);
1031 	move(tboxrow + 9, boxcol + 13);
1032 	printw("%4d%9d", thiscosts, totalcosts);
1033 	move(tboxrow + 10, boxcol + 13);
1034 	printw("%4d%9d", this.wins, total.wins);
1035 	move(tboxrow + 11, boxcol + 13);
1036 	printw("%4d%9d", this.worth, total.worth);
1037 }
1038 
1039 /*
1040  * procedure to move a card from the stock or talon to the tableau
1041  */
1042 simpletableau(cp, des)
1043 struct cardtype **cp;
1044 {
1045 	int origin;
1046 
1047 	if (notempty(*cp)) {
1048 		if (tabok(*cp, des)) {
1049 			if (*cp == stock)
1050 				origin = stk;
1051 			else
1052 				origin = tal;
1053 			if (tableau[des] == NIL)
1054 				bottom[des] = *cp;
1055 			transit(cp, &tableau[des]);
1056 			length[des]++;
1057 			printcard(pilemap[des], length[des], tableau[des]);
1058 			timesthru = 0;
1059 			if (origin == stk) {
1060 				usedstock();
1061 				printcard(stockcol, stockrow, stock);
1062 			} else {
1063 				usedtalon();
1064 				printcard(taloncol, talonrow, talon);
1065 			}
1066 		} else
1067 			destinerror();
1068 	}
1069 }
1070 
1071 /*
1072  * print the tableau
1073  */
1074 tabprint(sour, des)
1075 {
1076 	int dlength, slength, i;
1077 	struct cardtype *tempcard;
1078 
1079 	for (i=tabrow; i<=length[sour]; i++)
1080 		removecard(pilemap[sour], i);
1081 	dlength = length[des] + 1;
1082 	slength = length[sour];
1083 	if (slength == tabrow)
1084 		printcard(pilemap[des], dlength, tableau[sour]);
1085 	else
1086 		while (slength != tabrow - 1) {
1087 			tempcard = tableau[sour];
1088 			for (i=1; i<=slength-tabrow; i++)
1089 			    tempcard = tempcard->next;
1090 			printcard(pilemap[des], dlength, tempcard);
1091 			slength--;
1092 			dlength++;
1093 		}
1094 }
1095 
1096 /*
1097  * procedure to move from the tableau to the tableau
1098  */
1099 tabtotab(sour, des)
1100 	register int sour, des;
1101 {
1102 	struct cardtype *temp;
1103 
1104 	if (notempty(tableau[sour])) {
1105 		if (tabok(bottom[sour], des)) {
1106 			tabprint(sour, des);
1107 			temp = bottom[sour];
1108 			bottom[sour] = NIL;
1109 			if (bottom[des] == NIL)
1110 				bottom[des] = temp;
1111 			temp->next = tableau[des];
1112 			tableau[des] = tableau[sour];
1113 			tableau[sour] = NIL;
1114 			length[des] = length[des] + (length[sour] - (tabrow - 1));
1115 			length[sour] = tabrow - 1;
1116 			timesthru = 0;
1117 		} else
1118 			destinerror();
1119 	}
1120 }
1121 
1122 /*
1123  * functions to see if the card can go onto the foundation
1124  */
1125 bool
1126 rankhigher(cp, let)
1127 	struct cardtype *cp;
1128 {
1129 	if (found[let]->rank == King)
1130 		if (cp->rank == Ace)
1131 			return(TRUE);
1132 		else
1133 			return(FALSE);
1134 	else if (cp->rank - 1 == found[let]->rank)
1135 		return(TRUE);
1136 	else
1137 		return(FALSE);
1138 }
1139 
1140 /*
1141  * function to determine if two cards are the same suit
1142  */
1143 samesuit(cp, let)
1144 	struct cardtype *cp;
1145 {
1146 	if (cp->suit == found[let]->suit)
1147 		return (TRUE);
1148 	else
1149 		return (FALSE);
1150 }
1151 
1152 /*
1153  * procedure to move a card to the correct foundation pile
1154  */
1155 movetofound(cp, source)
1156 	struct cardtype **cp;
1157 {
1158 	tempbase = 0;
1159 	mtfdone = FALSE;
1160 	if (notempty(*cp)) {
1161 		do {
1162 			if (found[tempbase] != NIL)
1163 				if (rankhigher(*cp, tempbase)
1164 				    && samesuit(*cp, tempbase)) {
1165 					if (*cp == stock)
1166 						mtforigin = stk;
1167 					else if (*cp == talon)
1168 						mtforigin = tal;
1169 					else
1170 						mtforigin = tab;
1171 					transit(cp, &found[tempbase]);
1172 					printcard(pilemap[tempbase],
1173 						foundrow, found[tempbase]);
1174 					timesthru = 0;
1175 					if (mtforigin == stk) {
1176 						usedstock();
1177 						printcard(stockcol, stockrow, stock);
1178 					} else if (mtforigin == tal) {
1179 						usedtalon();
1180 						printcard(taloncol, talonrow, talon);
1181 					} else {
1182 						removecard(pilemap[source], length[source]);
1183 						length[source]--;
1184 					}
1185 					cardsoff++;
1186 					if (infullgame) {
1187 						this.wins += valuepercardup;
1188 						total.wins += valuepercardup;
1189 					}
1190 					mtfdone = TRUE;
1191 				} else
1192 					tempbase++;
1193 			else
1194 				tempbase++;
1195 		} while ((tempbase != 4) && !mtfdone);
1196 		if (!mtfdone)
1197 			destinerror();
1198 	}
1199 }
1200 
1201 /*
1202  * procedure to get a command
1203  */
1204 getcmd(row, col, cp)
1205 	int row, col;
1206 	char *cp;
1207 {
1208 	char cmd[2], ch;
1209 	int i;
1210 
1211 	i = 0;
1212 	move(row, col);
1213 	printw("%-24s", cp);
1214 	col += 1 + strlen(cp);
1215 	move(row, col);
1216 	refresh();
1217 	do {
1218 		ch = getch() & 0177;
1219 		if (ch >= 'A' && ch <= 'Z')
1220 			ch += ('a' - 'A');
1221 		if (ch == '\f') {
1222 			wrefresh(curscr);
1223 			refresh();
1224 		} else if (i >= 2 && ch != _tty.sg_erase && ch != _tty.sg_kill) {
1225 			if (ch != '\n' && ch != '\r' && ch != ' ')
1226 				write(1, "\007", 1);
1227 		} else if (ch == _tty.sg_erase && i > 0) {
1228 			printw("\b \b");
1229 			refresh();
1230 			i--;
1231 		} else if (ch == _tty.sg_kill && i > 0) {
1232 			while (i > 0) {
1233 				printw("\b \b");
1234 				i--;
1235 			}
1236 			refresh();
1237 		} else if (ch == '\032') {	/* Control-Z */
1238 			suspend();
1239 			move(row, col + i);
1240 			refresh();
1241 		} else if (isprint(ch)) {
1242 			cmd[i++] = ch;
1243 			addch(ch);
1244 			refresh();
1245 		}
1246 	} while (ch != '\n' && ch != '\r' && ch != ' ');
1247 	srcpile = cmd[0];
1248 	destpile = cmd[1];
1249 }
1250 
1251 /*
1252  * Suspend the game (shell escape if no process control on system)
1253  */
1254 suspend()
1255 {
1256 #ifndef SIGTSTP
1257 	char *sh;
1258 #endif
1259 
1260 	move(21, 0);
1261 	refresh();
1262 #ifdef SIGTSTP
1263 	kill(getpid(), SIGTSTP);
1264 #else
1265 	sh = getenv("SHELL");
1266 	if (sh == NULL)
1267 		sh = "/bin/sh";
1268 	system(sh);
1269 #endif
1270 	raw();
1271 	noecho();
1272 }
1273 
1274 /*
1275  * procedure to evaluate and make the specific moves
1276  */
1277 movecard()
1278 {
1279 	int source, dest;
1280 	char osrcpile, odestpile;
1281 
1282 	done = FALSE;
1283 	errmsg = FALSE;
1284 	do {
1285 		if (talon == NIL && hand != NIL)
1286 			movetotalon();
1287 		if (cardsoff == 52) {
1288 			refresh();
1289 			srcpile = 'q';
1290 		} else
1291 			getcmd(moverow, movecol, "Move:");
1292 		clearmsg();
1293 		if (srcpile >= '1' && srcpile <= '4')
1294 			source = (int) (srcpile - '1');
1295 		if (destpile >= '1' && destpile <= '4')
1296 			dest = (int) (destpile - '1');
1297 		if (!startedgame &&
1298 		    (srcpile == 't' || srcpile == 's' || srcpile == 'h' ||
1299 		     srcpile == '1' || srcpile == '2' || srcpile == '3' ||
1300 		     srcpile == '4')) {
1301 			startedgame = TRUE;
1302 			osrcpile = srcpile;
1303 			odestpile = destpile;
1304 			if (status != BETTINGBOX)
1305 				srcpile = 'y';
1306 			else do {
1307 				getcmd(moverow, movecol, "Inspect game?");
1308 			} while (srcpile != 'y' && srcpile != 'n');
1309 			if (srcpile == 'n') {
1310 				srcpile = 'q';
1311 			} else {
1312 				this.inspection += costofinspection;
1313 				total.inspection += costofinspection;
1314 				srcpile = osrcpile;
1315 				destpile = odestpile;
1316 			}
1317 		}
1318 		switch (srcpile) {
1319 			case 't':
1320 				if (destpile == 'f' || destpile == 'F')
1321 					movetofound(&talon, source);
1322 				else if (destpile >= '1' && destpile <= '4')
1323 					simpletableau(&talon, dest);
1324 				else
1325 					dumberror();
1326 				break;
1327 			case 's':
1328 				if (destpile == 'f' || destpile == 'F')
1329 					movetofound(&stock, source);
1330 				else if (destpile >= '1' && destpile <= '4')
1331 					simpletableau(&stock, dest);
1332 				else dumberror();
1333 				break;
1334 			case 'h':
1335 				if (destpile != 't' && destpile != 'T') {
1336 					dumberror();
1337 					break;
1338 				}
1339 				if (infullgame) {
1340 					movetotalon();
1341 					break;
1342 				}
1343 				if (status == BETTINGBOX) {
1344 					do {
1345 						getcmd(moverow, movecol,
1346 							"Buy game?");
1347 					} while (srcpile != 'y' &&
1348 						 srcpile != 'n');
1349 					if (srcpile == 'n') {
1350 						showcards();
1351 						done = TRUE;
1352 						break;
1353 					}
1354 				}
1355 				infullgame = TRUE;
1356 				this.wins += valuepercardup * cardsoff;
1357 				total.wins += valuepercardup * cardsoff;
1358 				this.game += costofgame;
1359 				total.game += costofgame;
1360 				movetotalon();
1361 				break;
1362 			case 'q':
1363 				showcards();
1364 				done = TRUE;
1365 				break;
1366 			case 'b':
1367 				printtopbettingbox();
1368 				printbottombettingbox();
1369 				status = BETTINGBOX;
1370 				break;
1371 			case 'x':
1372 				clearabovemovebox();
1373 				clearbelowmovebox();
1374 				status = NOBOX;
1375 				break;
1376 			case 'i':
1377 				printtopinstructions();
1378 				printbottominstructions();
1379 				status = INSTRUCTIONBOX;
1380 				break;
1381 			case 'c':
1382 				Cflag = !Cflag;
1383 				if (Cflag)
1384 					showstat();
1385 				else
1386 					clearstat();
1387 				break;
1388 			case '1': case '2': case '3': case '4':
1389 				if (destpile == 'f' || destpile == 'F')
1390 					movetofound(&tableau[source], source);
1391 				else if (destpile >= '1' && destpile <= '4')
1392 					tabtotab(source, dest);
1393 				else dumberror();
1394 				break;
1395 			default:
1396 				dumberror();
1397 		}
1398 		fndbase(&stock, stockcol, stockrow);
1399 		fndbase(&talon, taloncol, talonrow);
1400 		updatebettinginfo();
1401 	} while (!done);
1402 }
1403 
1404 char *basicinstructions[] = {
1405 	"Here are brief instuctions to the game of Canfield:\n\n",
1406 	"     If you have never played solitaire before, it is recom-\n",
1407 	"mended  that  you  consult  a solitaire instruction book. In\n",
1408 	"Canfield, tableau cards may be built on each other  downward\n",
1409 	"in  alternate colors. An entire pile must be moved as a unit\n",
1410 	"in building. Top cards of the piles are available to be able\n",
1411 	"to be played on foundations, but never into empty spaces.\n\n",
1412 	"     Spaces must be filled from the stock. The top  card  of\n",
1413 	"the  stock  also is available to be played on foundations or\n",
1414 	"built on tableau piles. After the stock  is  exhausted,  ta-\n",
1415 	"bleau spaces may be filled from the talon and the player may\n",
1416 	"keep them open until he wishes to use them.\n\n",
1417 	"     Cards are dealt from the hand to the  talon  by  threes\n",
1418 	"and  this  repeats until there are no more cards in the hand\n",
1419 	"or the player quits. To have cards dealt onto the talon  the\n",
1420 	"player  types  'ht'  for his move. Foundation base cards are\n",
1421 	"also automatically moved to the foundation when they  become\n",
1422 	"available.\n\n",
1423 	"push any key when you are finished: ",
1424 	0 };
1425 
1426 char *bettinginstructions[] = {
1427 	"     The rules for betting are  somewhat  less  strict  than\n",
1428 	"those  used in the official version of the game. The initial\n",
1429 	"deal costs $13. You may quit at this point  or  inspect  the\n",
1430 	"game.  Inspection  costs  $13 and allows you to make as many\n",
1431 	"moves as is possible without moving any cards from your hand\n",
1432 	"to  the  talon.  (the initial deal places three cards on the\n",
1433 	"talon; if all these cards are  used,  three  more  are  made\n",
1434 	"available)  Finally, if the game seems interesting, you must\n",
1435 	"pay the final installment of $26.  At  this  point  you  are\n",
1436 	"credited  at the rate of $5 for each card on the foundation;\n",
1437 	"as the game progresses you are credited  with  $5  for  each\n",
1438 	"card  that is moved to the foundation.  Each run through the\n",
1439 	"hand after the first costs $5.  The  card  counting  feature\n",
1440 	"costs  $1  for  each unknown card that is identified. If the\n",
1441 	"information is toggled on, you are only  charged  for  cards\n",
1442 	"that  became  visible  since it was last turned on. Thus the\n",
1443 	"maximum cost of information is $34.  Playing time is charged\n",
1444 	"at a rate of $1 per minute.\n\n",
1445 	"push any key when you are finished: ",
1446 	0 };
1447 
1448 /*
1449  * procedure to printout instructions
1450  */
1451 instruct()
1452 {
1453 	register char **cp;
1454 
1455 	move(originrow, origincol);
1456 	printw("This is the game of solitaire called Canfield.  Do\n");
1457 	printw("you want instructions for the game?");
1458 	do {
1459 		getcmd(originrow + 3, origincol, "y or n?");
1460 	} while (srcpile != 'y' && srcpile != 'n');
1461 	if (srcpile == 'n')
1462 		return;
1463 	clear();
1464 	for (cp = basicinstructions; *cp != 0; cp++)
1465 		printw(*cp);
1466 	refresh();
1467 	getch();
1468 	clear();
1469 	move(originrow, origincol);
1470 	printw("Do you want instructions for betting?");
1471 	do {
1472 		getcmd(originrow + 2, origincol, "y or n?");
1473 	} while (srcpile != 'y' && srcpile != 'n');
1474 	if (srcpile == 'n')
1475 		return;
1476 	clear();
1477 	for (cp = bettinginstructions; *cp != 0; cp++)
1478 		printw(*cp);
1479 	refresh();
1480 	getch();
1481 }
1482 
1483 /*
1484  * procedure to initialize the game
1485  */
1486 initall()
1487 {
1488 	int uid, i;
1489 
1490 	srandom(getpid());
1491 	time(&acctstart);
1492 	initdeck(deck);
1493 	uid = getuid();
1494 	if (uid < 0)
1495 		return;
1496 	dbfd = open("/usr/games/lib/cfscores", 2);
1497 	if (dbfd < 0)
1498 		return;
1499 	i = lseek(dbfd, uid * sizeof(struct betinfo), 0);
1500 	if (i < 0) {
1501 		close(dbfd);
1502 		dbfd = -1;
1503 		return;
1504 	}
1505 	i = read(dbfd, (char *)&total, sizeof(total));
1506 	if (i < 0) {
1507 		close(dbfd);
1508 		dbfd = -1;
1509 		return;
1510 	}
1511 	lseek(dbfd, uid * sizeof(struct betinfo), 0);
1512 }
1513 
1514 /*
1515  * procedure to end the game
1516  */
1517 bool
1518 finish()
1519 {
1520 	int row, col;
1521 
1522 	if (cardsoff == 52) {
1523 		clear();
1524 		refresh();
1525 		move(originrow, origincol);
1526 		printw("CONGRATULATIONS!\n");
1527 		printw("You won the game. That is a feat to be proud of.\n");
1528 		move(originrow + 4, origincol);
1529 		printw("Wish to play again?     ");
1530 		row = originrow + 5;
1531 		col = origincol;
1532 	} else {
1533 		move(msgrow, msgcol);
1534 		printw("You got %d card", cardsoff);
1535 		if (cardsoff > 1)
1536 			printw("s");
1537 		printw(" off    ");
1538 		getcmd(moverow, movecol, "Hit return to continue");
1539 		move(msgrow, msgcol);
1540 		printw("Wish to play again?     ");
1541 		row = moverow;
1542 		col = movecol;
1543 	}
1544 	do {
1545 		getcmd(row, col, "y or n?");
1546 	} while (srcpile != 'y' && srcpile != 'n');
1547 	errmsg = TRUE;
1548 	clearmsg();
1549 	if (srcpile == 'y')
1550 		return (FALSE);
1551 	else
1552 		return (TRUE);
1553 }
1554 
1555 /*
1556  * Field an interrupt.
1557  */
1558 askquit()
1559 {
1560 	move(msgrow, msgcol);
1561 	printw("Really wish to quit?    ");
1562 	do {
1563 		getcmd(moverow, movecol, "y or n?");
1564 	} while (srcpile != 'y' && srcpile != 'n');
1565 	clearmsg();
1566 	if (srcpile == 'y')
1567 		cleanup();
1568 	signal(SIGINT, askquit);
1569 }
1570 
1571 /*
1572  * procedure to clean up and exit
1573  */
1574 cleanup()
1575 {
1576 
1577 	total.thinktime += 1;
1578 	status = NOBOX;
1579 	updatebettinginfo();
1580 	if (dbfd != -1) {
1581 		write(dbfd, (char *)&total, sizeof(total));
1582 		close(dbfd);
1583 	}
1584 	clear();
1585 	move(22,0);
1586 	refresh();
1587 	endwin();
1588 	exit(0);
1589 	/* NOTREACHED */
1590 }
1591 
1592 /*
1593  * Can you tell that this used to be a Pascal program?
1594  */
1595 main(argc, argv)
1596 	int argc;
1597 	char *argv[];
1598 {
1599 #ifdef MAXLOAD
1600 	double vec[3];
1601 
1602 	loadav(vec);
1603 	if (vec[2] >= MAXLOAD) {
1604 		puts("The system load is too high.  Try again later.");
1605 		exit(0);
1606 	}
1607 #endif
1608 	signal(SIGINT, askquit);
1609 	signal(SIGHUP, cleanup);
1610 	signal(SIGTERM, cleanup);
1611 	initscr();
1612 	raw();
1613 	noecho();
1614 	initall();
1615 	instruct();
1616 	makeboard();
1617 	for (;;) {
1618 		startgame();
1619 		movecard();
1620 		if (finish())
1621 			break;
1622 		if (cardsoff == 52)
1623 			makeboard();
1624 		else
1625 			cleanupboard();
1626 	}
1627 	cleanup();
1628 	/* NOTREACHED */
1629 }
1630