Add efidev.4 and efirt.9 manual pages from FreeBSD.
[dragonfly.git] / games / canfield / canfield / canfield.c
blobec6de9d740b37af1b7658e7d21eca09c55564090
1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
30 * @(#)canfield.c 8.1 (Berkeley) 5/31/93
31 * $FreeBSD: src/games/canfield/canfield/canfield.c,v 1.11 1999/12/12 07:25:13 billf Exp $
35 * The canfield program
37 * Authors:
38 * Originally written: Steve Levine
39 * Converted to use curses and debugged: Steve Feldman
40 * Card counting: Kirk McKusick and Mikey Olson
41 * User interface cleanups: Eric Allman and Kirk McKusick
42 * Betting by Kirk McKusick
45 #include <sys/types.h>
47 #include <ctype.h>
48 #include <curses.h>
49 #include <fcntl.h>
50 #include <signal.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <time.h>
54 #include <unistd.h>
56 #include "pathnames.h"
58 #define decksize 52
59 #define originrow 0
60 #define origincol 0
61 #define basecol 1
62 #define boxcol 42
63 #define tboxrow 2
64 #define bboxrow 17
65 #define movecol 43
66 #define moverow 16
67 #define msgcol 43
68 #define msgrow 15
69 #define titlecol 30
70 #define titlerow 0
71 #define sidecol 1
72 #define ottlrow 6
73 #define foundcol 11
74 #define foundrow 3
75 #define stockcol 2
76 #define stockrow 8
77 #define fttlcol 10
78 #define fttlrow 1
79 #define taloncol 2
80 #define talonrow 13
81 #define tabrow 8
82 #define ctoprow 21
83 #define cbotrow 23
84 #define cinitcol 14
85 #define cheightcol 1
86 #define cwidthcol 4
87 #define handstatrow 21
88 #define handstatcol 7
89 #define talonstatrow 22
90 #define talonstatcol 7
91 #define stockstatrow 23
92 #define stockstatcol 7
93 #define Ace 1
94 #define Jack 11
95 #define Queen 12
96 #define King 13
97 #define atabcol 11
98 #define btabcol 18
99 #define ctabcol 25
100 #define dtabcol 32
102 #define spades 's'
103 #define clubs 'c'
104 #define hearts 'h'
105 #define diamonds 'd'
106 #define black 'b'
107 #define red 'r'
109 #define stk 1
110 #define tal 2
111 #define tab 3
112 #define INCRHAND(row, col) {\
113 row -= cheightcol;\
114 if (row < ctoprow) {\
115 row = cbotrow;\
116 col += cwidthcol;\
119 #define DECRHAND(row, col) {\
120 row += cheightcol;\
121 if (row > cbotrow) {\
122 row = ctoprow;\
123 col -= cwidthcol;\
128 struct cardtype {
129 char suit;
130 char color;
131 bool visible;
132 bool paid;
133 int rank;
134 struct cardtype *next;
137 #define NIL ((struct cardtype *) -1)
139 struct cardtype *deck[decksize];
140 struct cardtype cards[decksize];
141 struct cardtype *bottom[4], *found[4], *tableau[4];
142 struct cardtype *talon, *hand, *stock, *basecard;
143 int length[4];
144 int cardsoff, base, cinhand, taloncnt, stockcnt, timesthru;
145 char suitmap[4] = {spades, clubs, hearts, diamonds};
146 char colormap[4] = {black, black, red, red};
147 char pilemap[4] = {atabcol, btabcol, ctabcol, dtabcol};
148 char srcpile, destpile;
149 int mtforigin, tempbase;
150 int coldcol, cnewcol, coldrow, cnewrow;
151 bool errmsg, done;
152 bool mtfdone, Cflag = FALSE;
153 #define INSTRUCTIONBOX 1
154 #define BETTINGBOX 2
155 #define NOBOX 3
156 int status = INSTRUCTIONBOX;
157 int uid;
160 * Basic betting costs
162 #define costofhand 13
163 #define costofinspection 13
164 #define costofgame 26
165 #define costofrunthroughhand 5
166 #define costofinformation 1
167 #define secondsperdollar 60
168 #define maxtimecharge 3
169 #define valuepercardup 5
171 * Variables associated with betting
173 struct betinfo {
174 long hand; /* cost of dealing hand */
175 long inspection; /* cost of inspecting hand */
176 long game; /* cost of buying game */
177 long runs; /* cost of running through hands */
178 long information; /* cost of information */
179 long thinktime; /* cost of thinking time */
180 long wins; /* total winnings */
181 long worth; /* net worth after costs */
183 struct betinfo this, game, total;
184 bool startedgame = FALSE, infullgame = FALSE;
185 time_t acctstart;
186 int dbfd = -1;
188 static void askquit(int);
189 static void cleanup(int);
190 static void cleanupboard(void);
191 static void clearabovemovebox(void);
192 static void clearbelowmovebox(void);
193 static void clearmsg(void);
194 static void clearstat(void);
195 static void destinerror(void);
196 static bool diffcolor(struct cardtype *, struct cardtype *);
197 static void dumberror(void);
198 static bool finish(void);
199 static void fndbase(struct cardtype **, int, int);
200 static void getcmd(int, int, const char *);
201 static void initall(void);
202 static void initdeck(struct cardtype *[]);
203 static void initgame(void);
204 static void instruct(void);
205 static void makeboard(void);
206 static void movebox(void);
207 static void movecard(void);
208 static void movetofound(struct cardtype **, int);
209 static void movetotalon(void);
210 static bool notempty(struct cardtype *);
211 static void printbottombettingbox(void);
212 static void printbottominstructions(void);
213 static void printcard(int, int, struct cardtype *);
214 static void printrank(int, int, struct cardtype *, bool);
215 static void printtopbettingbox(void);
216 static void printtopinstructions(void);
217 static bool rankhigher(struct cardtype *, int);
218 static bool ranklower(struct cardtype *, struct cardtype *);
219 static void removecard(int, int);
220 static bool samesuit(struct cardtype *, int);
221 static void showcards(void);
222 static void showstat(void);
223 static void shuffle(struct cardtype *[]);
224 static void simpletableau(struct cardtype **, int);
225 static void startgame(void);
226 static void suspend(void);
227 static bool tabok(struct cardtype *, int);
228 static void tabprint(int, int);
229 static void tabtotab(int, int);
230 static void transit(struct cardtype **, struct cardtype **);
231 static void updatebettinginfo(void);
232 static void usedstock(void);
233 static void usedtalon(void);
236 * The following procedures print the board onto the screen using the
237 * addressible cursor. The end of these procedures will also be
238 * separated from the rest of the program.
240 * procedure to set the move command box
242 static void
243 movebox(void)
245 switch (status) {
246 case BETTINGBOX:
247 printtopbettingbox();
248 break;
249 case NOBOX:
250 clearabovemovebox();
251 break;
252 case INSTRUCTIONBOX:
253 printtopinstructions();
254 break;
256 move(moverow, boxcol);
257 printw("| |");
258 move(msgrow, boxcol);
259 printw("| |");
260 switch (status) {
261 case BETTINGBOX:
262 printbottombettingbox();
263 break;
264 case NOBOX:
265 clearbelowmovebox();
266 break;
267 case INSTRUCTIONBOX:
268 printbottominstructions();
269 break;
271 refresh();
275 * print directions above move box
277 static void
278 printtopinstructions(void)
280 move(tboxrow, boxcol);
281 printw("*----------------------------------*");
282 move(tboxrow + 1, boxcol);
283 printw("| MOVES |");
284 move(tboxrow + 2, boxcol);
285 printw("|s# = stock to tableau |");
286 move(tboxrow + 3, boxcol);
287 printw("|sf = stock to foundation |");
288 move(tboxrow + 4, boxcol);
289 printw("|t# = talon to tableau |");
290 move(tboxrow + 5, boxcol);
291 printw("|tf = talon to foundation |");
292 move(tboxrow + 6, boxcol);
293 printw("|## = tableau to tableau |");
294 move(tboxrow + 7, boxcol);
295 printw("|#f = tableau to foundation |");
296 move(tboxrow + 8, boxcol);
297 printw("|ht = hand to talon |");
298 move(tboxrow + 9, boxcol);
299 printw("|c = toggle card counting |");
300 move(tboxrow + 10, boxcol);
301 printw("|b = present betting information |");
302 move(tboxrow + 11, boxcol);
303 printw("|q = quit to end the game |");
304 move(tboxrow + 12, boxcol);
305 printw("|==================================|");
309 * Print the betting box.
311 static void
312 printtopbettingbox(void)
315 move(tboxrow, boxcol);
316 printw("*----------------------------------*");
317 move(tboxrow + 1, boxcol);
318 printw("|Costs Hand Game Total |");
319 move(tboxrow + 2, boxcol);
320 printw("| Hands |");
321 move(tboxrow + 3, boxcol);
322 printw("| Inspections |");
323 move(tboxrow + 4, boxcol);
324 printw("| Games |");
325 move(tboxrow + 5, boxcol);
326 printw("| Runs |");
327 move(tboxrow + 6, boxcol);
328 printw("| Information |");
329 move(tboxrow + 7, boxcol);
330 printw("| Think time |");
331 move(tboxrow + 8, boxcol);
332 printw("|Total Costs |");
333 move(tboxrow + 9, boxcol);
334 printw("|Winnings |");
335 move(tboxrow + 10, boxcol);
336 printw("|Net Worth |");
337 move(tboxrow + 11, boxcol);
338 printw("|Return |");
339 move(tboxrow + 12, boxcol);
340 printw("|==================================|");
344 * clear info above move box
346 static void
347 clearabovemovebox(void)
349 int i;
351 for (i = 0; i <= 11; i++) {
352 move(tboxrow + i, boxcol);
353 printw(" ");
355 move(tboxrow + 12, boxcol);
356 printw("*----------------------------------*");
360 * print instructions below move box
362 static void
363 printbottominstructions(void)
365 move(bboxrow, boxcol);
366 printw("|Replace # with the number of the |");
367 move(bboxrow + 1, boxcol);
368 printw("|tableau you want. |");
369 move(bboxrow + 2, boxcol);
370 printw("*----------------------------------*");
374 * print betting information below move box
376 static void
377 printbottombettingbox(void)
379 move(bboxrow, boxcol);
380 printw("|x = toggle information box |");
381 move(bboxrow + 1, boxcol);
382 printw("|i = list playing instructions |");
383 move(bboxrow + 2, boxcol);
384 printw("*----------------------------------*");
388 * clear info below move box
390 static void
391 clearbelowmovebox(void)
393 int i;
395 move(bboxrow, boxcol);
396 printw("*----------------------------------*");
397 for (i = 1; i <= 2; i++) {
398 move(bboxrow + i, boxcol);
399 printw(" ");
404 * procedure to put the board on the screen using addressable cursor
406 static void
407 makeboard(void)
409 clear();
410 refresh();
411 move(titlerow, titlecol);
412 printw("=-> CANFIELD <-=");
413 move(fttlrow, fttlcol);
414 printw("foundation");
415 move(foundrow - 1, fttlcol);
416 printw("=---= =---= =---= =---=");
417 move(foundrow, fttlcol);
418 printw("| | | | | | | |");
419 move(foundrow + 1, fttlcol);
420 printw("=---= =---= =---= =---=");
421 move(ottlrow, sidecol);
422 printw("stock tableau");
423 move(stockrow - 1, sidecol);
424 printw("=---=");
425 move(stockrow, sidecol);
426 printw("| |");
427 move(stockrow + 1, sidecol);
428 printw("=---=");
429 move(talonrow - 2, sidecol);
430 printw("talon");
431 move(talonrow - 1, sidecol);
432 printw("=---=");
433 move(talonrow, sidecol);
434 printw("| |");
435 move(talonrow + 1, sidecol);
436 printw("=---=");
437 move(tabrow - 1, atabcol);
438 printw("-1- -2- -3- -4-");
439 movebox();
443 * clean up the board for another game
445 static void
446 cleanupboard(void)
448 int cnt, row, col;
449 struct cardtype *ptr;
451 col = 0;
452 if (Cflag) {
453 clearstat();
454 for(ptr = stock, row = stockrow;
455 ptr != NIL;
456 ptr = ptr->next, row++) {
457 move(row, sidecol);
458 printw(" ");
460 move(row, sidecol);
461 printw(" ");
462 move(stockrow + 1, sidecol);
463 printw("=---=");
464 move(talonrow - 2, sidecol);
465 printw("talon");
466 move(talonrow - 1, sidecol);
467 printw("=---=");
468 move(talonrow + 1, sidecol);
469 printw("=---=");
471 move(stockrow, sidecol);
472 printw("| |");
473 move(talonrow, sidecol);
474 printw("| |");
475 move(foundrow, fttlcol);
476 printw("| | | | | | | |");
477 for (cnt = 0; cnt < 4; cnt++) {
478 switch(cnt) {
479 case 0:
480 col = atabcol;
481 break;
482 case 1:
483 col = btabcol;
484 break;
485 case 2:
486 col = ctabcol;
487 break;
488 case 3:
489 col = dtabcol;
490 break;
492 for(ptr = tableau[cnt], row = tabrow;
493 ptr != NIL;
494 ptr = ptr->next, row++)
495 removecard(col, row);
500 * procedure to create a deck of cards
502 static void
503 initdeck(struct cardtype *ideck[])
505 int i;
506 int scnt;
507 char s;
508 int r;
510 i = 0;
511 for (scnt=0; scnt<4; scnt++) {
512 s = suitmap[scnt];
513 for (r=Ace; r<=King; r++) {
514 ideck[i] = &cards[i];
515 cards[i].rank = r;
516 cards[i].suit = s;
517 cards[i].color = colormap[scnt];
518 cards[i].next = NIL;
519 i++;
525 * procedure to shuffle the deck
527 static void
528 shuffle(struct cardtype *ideck[])
530 int i,j;
531 struct cardtype *temp;
533 for (i=0; i<decksize; i++) {
534 ideck[i]->visible = FALSE;
535 ideck[i]->paid = FALSE;
537 for (i = decksize-1; i>=0; i--) {
538 j = random() % decksize;
539 if (i != j) {
540 temp = ideck[i];
541 ideck[i] = ideck[j];
542 ideck[j] = temp;
548 * procedure to remove the card from the board
550 static void
551 removecard(int a, int b)
553 move(b, a);
554 printw(" ");
558 * procedure to print the cards on the board
560 static void
561 printrank(int a, int b, struct cardtype *cp, bool inverse)
563 move(b, a);
564 if (cp->rank != 10)
565 addch(' ');
566 if (inverse)
567 standout();
568 switch (cp->rank) {
569 case 2: case 3: case 4: case 5: case 6: case 7:
570 case 8: case 9: case 10:
571 printw("%d", cp->rank);
572 break;
573 case Ace:
574 addch('A');
575 break;
576 case Jack:
577 addch('J');
578 break;
579 case Queen:
580 addch('Q');
581 break;
582 case King:
583 addch('K');
585 if (inverse)
586 standend();
590 * procedure to print out a card
592 static void
593 printcard(int a, int b, struct cardtype *cp)
595 if (cp == NIL)
596 removecard(a, b);
597 else if (cp->visible == FALSE) {
598 move(b, a);
599 printw(" ? ");
600 } else {
601 bool inverse = (cp->suit == 'd' || cp->suit == 'h');
603 printrank(a, b, cp, inverse);
604 if (inverse)
605 standout();
606 addch(cp->suit);
607 if (inverse)
608 standend();
613 * procedure to move the top card from one location to the top
614 * of another location. The pointers always point to the top
615 * of the piles.
617 static void
618 transit(struct cardtype **source, struct cardtype **dest)
620 struct cardtype *temp;
622 temp = *source;
623 *source = (*source)->next;
624 temp->next = *dest;
625 *dest = temp;
629 * Procedure to set the cards on the foundation base when available.
630 * Note that it is only called on a foundation pile at the beginning of
631 * the game, so the pile will have exactly one card in it.
633 static void
634 fndbase(struct cardtype **cp, int column, int row)
636 bool nomore;
638 if (*cp != NIL)
639 do {
640 if ((*cp)->rank == basecard->rank) {
641 base++;
642 printcard(pilemap[base], foundrow, *cp);
643 if (*cp == tableau[0])
644 length[0] = length[0] - 1;
645 if (*cp == tableau[1])
646 length[1] = length[1] - 1;
647 if (*cp == tableau[2])
648 length[2] = length[2] - 1;
649 if (*cp == tableau[3])
650 length[3] = length[3] - 1;
651 transit(cp, &found[base]);
652 if (cp == &talon)
653 usedtalon();
654 if (cp == &stock)
655 usedstock();
656 if (*cp != NIL) {
657 printcard(column, row, *cp);
658 nomore = FALSE;
659 } else {
660 removecard(column, row);
661 nomore = TRUE;
663 cardsoff++;
664 if (infullgame) {
665 this.wins += valuepercardup;
666 game.wins += valuepercardup;
667 total.wins += valuepercardup;
669 } else
670 nomore = TRUE;
671 } while (nomore == FALSE);
675 * procedure to initialize the things necessary for the game
677 static void
678 initgame(void)
680 int i;
682 for (i=0; i<18; i++) {
683 deck[i]->visible = TRUE;
684 deck[i]->paid = TRUE;
686 stockcnt = 13;
687 stock = deck[12];
688 for (i=12; i>=1; i--)
689 deck[i]->next = deck[i - 1];
690 deck[0]->next = NIL;
691 found[0] = deck[13];
692 deck[13]->next = NIL;
693 for (i=1; i<4; i++)
694 found[i] = NIL;
695 basecard = found[0];
696 for (i=14; i<18; i++) {
697 tableau[i - 14] = deck[i];
698 deck[i]->next = NIL;
700 for (i=0; i<4; i++) {
701 bottom[i] = tableau[i];
702 length[i] = tabrow;
704 hand = deck[18];
705 for (i=18; i<decksize-1; i++)
706 deck[i]->next = deck[i + 1];
707 deck[decksize-1]->next = NIL;
708 talon = NIL;
709 base = 0;
710 cinhand = 34;
711 taloncnt = 0;
712 timesthru = 0;
713 cardsoff = 1;
714 coldrow = ctoprow;
715 coldcol = cinitcol;
716 cnewrow = ctoprow;
717 cnewcol = cinitcol + cwidthcol;
721 * procedure to print the beginning cards and to start each game
723 static void
724 startgame(void)
726 int j;
728 shuffle(deck);
729 initgame();
730 this.hand = costofhand;
731 game.hand += costofhand;
732 total.hand += costofhand;
733 this.inspection = 0;
734 this.game = 0;
735 this.runs = 0;
736 this.information = 0;
737 this.wins = 0;
738 this.thinktime = 0;
739 infullgame = FALSE;
740 startedgame = FALSE;
741 printcard(foundcol, foundrow, found[0]);
742 printcard(stockcol, stockrow, stock);
743 printcard(atabcol, tabrow, tableau[0]);
744 printcard(btabcol, tabrow, tableau[1]);
745 printcard(ctabcol, tabrow, tableau[2]);
746 printcard(dtabcol, tabrow, tableau[3]);
747 printcard(taloncol, talonrow, talon);
748 move(foundrow - 2, basecol);
749 printw("Base");
750 move(foundrow - 1, basecol);
751 printw("Rank");
752 printrank(basecol, foundrow, found[0], 0);
753 for (j=0; j<=3; j++)
754 fndbase(&tableau[j], pilemap[j], tabrow);
755 fndbase(&stock, stockcol, stockrow);
756 showstat(); /* show card counting info to cheaters */
757 movetotalon();
758 updatebettinginfo();
762 * procedure to clear the message printed from an error
764 static void
765 clearmsg(void)
767 int i;
769 if (errmsg == TRUE) {
770 errmsg = FALSE;
771 move(msgrow, msgcol);
772 for (i=0; i<25; i++)
773 addch(' ');
774 refresh();
779 * procedure to print an error message if the move is not listed
781 static void
782 dumberror(void)
784 errmsg = TRUE;
785 move(msgrow, msgcol);
786 printw("Not a proper move ");
790 * procedure to print an error message if the move is not possible
792 static void
793 destinerror(void)
795 errmsg = TRUE;
796 move(msgrow, msgcol);
797 printw("Error: Can't move there");
801 * function to see if the source has cards in it
803 static bool
804 notempty(struct cardtype *cp)
806 if (cp == NIL) {
807 errmsg = TRUE;
808 move(msgrow, msgcol);
809 printw("Error: no cards to move");
810 return (FALSE);
811 } else
812 return (TRUE);
816 * function to see if the rank of one card is less than another
818 static bool
819 ranklower(struct cardtype *cp1, struct cardtype *cp2)
821 if (cp2->rank == Ace)
822 if (cp1->rank == King)
823 return (TRUE);
824 else
825 return (FALSE);
826 else if (cp1->rank + 1 == cp2->rank)
827 return (TRUE);
828 else
829 return (FALSE);
833 * function to check the cardcolor for moving to a tableau
835 static bool
836 diffcolor(struct cardtype *cp1, struct cardtype *cp2)
838 if (cp1->color == cp2->color)
839 return (FALSE);
840 else
841 return (TRUE);
845 * function to see if the card can move to the tableau
847 static bool
848 tabok(struct cardtype *cp, int des)
850 if ((cp == stock) && (tableau[des] == NIL))
851 return (TRUE);
852 else if (tableau[des] == NIL)
853 if (stock == NIL &&
854 cp != bottom[0] && cp != bottom[1] &&
855 cp != bottom[2] && cp != bottom[3])
856 return (TRUE);
857 else
858 return (FALSE);
859 else if (ranklower(cp, tableau[des]) && diffcolor(cp, tableau[des]))
860 return (TRUE);
861 else
862 return (FALSE);
866 * procedure to turn the cards onto the talon from the deck
868 static void
869 movetotalon(void)
871 int i, fin;
873 if (cinhand <= 3 && cinhand > 0) {
874 move(msgrow, msgcol);
875 printw("Hand is now empty ");
877 if (cinhand >= 3)
878 fin = 3;
879 else if (cinhand > 0)
880 fin = cinhand;
881 else if (talon != NIL) {
882 timesthru++;
883 errmsg = TRUE;
884 move(msgrow, msgcol);
885 if (timesthru != 4) {
886 printw("Talon is now the new hand");
887 this.runs += costofrunthroughhand;
888 game.runs += costofrunthroughhand;
889 total.runs += costofrunthroughhand;
890 while (talon != NIL) {
891 transit(&talon, &hand);
892 cinhand++;
894 if (cinhand >= 3)
895 fin = 3;
896 else
897 fin = cinhand;
898 taloncnt = 0;
899 coldrow = ctoprow;
900 coldcol = cinitcol;
901 cnewrow = ctoprow;
902 cnewcol = cinitcol + cwidthcol;
903 clearstat();
904 showstat();
905 } else {
906 fin = 0;
907 done = TRUE;
908 printw("I believe you have lost");
909 refresh();
910 sleep(5);
912 } else {
913 errmsg = TRUE;
914 move(msgrow, msgcol);
915 printw("Talon and hand are empty");
916 fin = 0;
918 for (i=0; i<fin; i++) {
919 transit(&hand, &talon);
920 INCRHAND(cnewrow, cnewcol);
921 INCRHAND(coldrow, coldcol);
922 removecard(cnewcol, cnewrow);
923 if (i == fin - 1)
924 talon->visible = TRUE;
925 if (Cflag) {
926 if (talon->paid == FALSE && talon->visible == TRUE) {
927 this.information += costofinformation;
928 game.information += costofinformation;
929 total.information += costofinformation;
930 talon->paid = TRUE;
932 printcard(coldcol, coldrow, talon);
935 if (fin != 0) {
936 printcard(taloncol, talonrow, talon);
937 cinhand -= fin;
938 taloncnt += fin;
939 if (Cflag) {
940 move(handstatrow, handstatcol);
941 printw("%3d", cinhand);
942 move(talonstatrow, talonstatcol);
943 printw("%3d", taloncnt);
945 fndbase(&talon, taloncol, talonrow);
951 * procedure to print card counting info on screen
953 static void
954 showstat(void)
956 int row, col;
957 struct cardtype *ptr;
959 if (!Cflag)
960 return;
961 move(talonstatrow, talonstatcol - 7);
962 printw("Talon: %3d", taloncnt);
963 move(handstatrow, handstatcol - 7);
964 printw("Hand: %3d", cinhand);
965 move(stockstatrow, stockstatcol - 7);
966 printw("Stock: %3d", stockcnt);
967 for ( row = coldrow, col = coldcol, ptr = talon;
968 ptr != NIL;
969 ptr = ptr->next ) {
970 if (ptr->paid == FALSE && ptr->visible == TRUE) {
971 ptr->paid = TRUE;
972 this.information += costofinformation;
973 game.information += costofinformation;
974 total.information += costofinformation;
976 printcard(col, row, ptr);
977 DECRHAND(row, col);
979 for ( row = cnewrow, col = cnewcol, ptr = hand;
980 ptr != NIL;
981 ptr = ptr->next ) {
982 if (ptr->paid == FALSE && ptr->visible == TRUE) {
983 ptr->paid = TRUE;
984 this.information += costofinformation;
985 game.information += costofinformation;
986 total.information += costofinformation;
988 INCRHAND(row, col);
989 printcard(col, row, ptr);
994 * procedure to clear card counting info from screen
996 static void
997 clearstat(void)
999 int row;
1001 move(talonstatrow, talonstatcol - 7);
1002 printw(" ");
1003 move(handstatrow, handstatcol - 7);
1004 printw(" ");
1005 move(stockstatrow, stockstatcol - 7);
1006 printw(" ");
1007 for ( row = ctoprow ; row <= cbotrow ; row++ ) {
1008 move(row, cinitcol);
1009 printw("%56s", " ");
1014 * procedure to update card counting base
1016 static void
1017 usedtalon(void)
1019 removecard(coldcol, coldrow);
1020 DECRHAND(coldrow, coldcol);
1021 if (talon != NIL && (talon->visible == FALSE)) {
1022 talon->visible = TRUE;
1023 if (Cflag) {
1024 this.information += costofinformation;
1025 game.information += costofinformation;
1026 total.information += costofinformation;
1027 talon->paid = TRUE;
1028 printcard(coldcol, coldrow, talon);
1031 taloncnt--;
1032 if (Cflag) {
1033 move(talonstatrow, talonstatcol);
1034 printw("%3d", taloncnt);
1039 * procedure to update stock card counting base
1041 static void
1042 usedstock(void)
1044 stockcnt--;
1045 if (Cflag) {
1046 move(stockstatrow, stockstatcol);
1047 printw("%3d", stockcnt);
1052 * let 'em know how they lost!
1054 static void
1055 showcards(void)
1057 struct cardtype *ptr;
1058 int row;
1060 if (!Cflag || cardsoff == 52)
1061 return;
1062 for (ptr = talon; ptr != NIL; ptr = ptr->next) {
1063 ptr->visible = TRUE;
1064 ptr->paid = TRUE;
1066 for (ptr = hand; ptr != NIL; ptr = ptr->next) {
1067 ptr->visible = TRUE;
1068 ptr->paid = TRUE;
1070 showstat();
1071 move(stockrow + 1, sidecol);
1072 printw(" ");
1073 move(talonrow - 2, sidecol);
1074 printw(" ");
1075 move(talonrow - 1, sidecol);
1076 printw(" ");
1077 move(talonrow, sidecol);
1078 printw(" ");
1079 move(talonrow + 1, sidecol);
1080 printw(" ");
1081 for (ptr = stock, row = stockrow; ptr != NIL; ptr = ptr->next, row++) {
1082 move(row, stockcol - 1);
1083 printw("| |");
1084 printcard(stockcol, row, ptr);
1086 if (stock == NIL) {
1087 move(row, stockcol - 1);
1088 printw("| |");
1089 row++;
1091 move(handstatrow, handstatcol - 7);
1092 printw(" ");
1093 move(row, stockcol - 1);
1094 printw("=---=");
1095 if ( cardsoff == 52 )
1096 getcmd(moverow, movecol, "Hit return to exit");
1100 * procedure to update the betting values
1102 static void
1103 updatebettinginfo(void)
1105 long thiscosts, gamecosts, totalcosts;
1106 double thisreturn, gamereturn, totalreturn;
1107 time_t now;
1108 long dollars;
1110 time(&now);
1111 dollars = (now - acctstart) / secondsperdollar;
1112 if (dollars > 0) {
1113 acctstart += dollars * secondsperdollar;
1114 if (dollars > maxtimecharge)
1115 dollars = maxtimecharge;
1116 this.thinktime += dollars;
1117 game.thinktime += dollars;
1118 total.thinktime += dollars;
1120 thiscosts = this.hand + this.inspection + this.game +
1121 this.runs + this.information + this.thinktime;
1122 gamecosts = game.hand + game.inspection + game.game +
1123 game.runs + game.information + game.thinktime;
1124 totalcosts = total.hand + total.inspection + total.game +
1125 total.runs + total.information + total.thinktime;
1126 this.worth = this.wins - thiscosts;
1127 game.worth = game.wins - gamecosts;
1128 total.worth = total.wins - totalcosts;
1129 thisreturn = ((double)this.wins / (double)thiscosts - 1.0) * 100.0;
1130 gamereturn = ((double)game.wins / (double)gamecosts - 1.0) * 100.0;
1131 totalreturn = ((double)total.wins / (double)totalcosts - 1.0) * 100.0;
1132 if (status != BETTINGBOX)
1133 return;
1134 move(tboxrow + 2, boxcol + 13);
1135 printw("%4d%8d%9d", this.hand, game.hand, total.hand);
1136 move(tboxrow + 3, boxcol + 13);
1137 printw("%4d%8d%9d", this.inspection, game.inspection, total.inspection);
1138 move(tboxrow + 4, boxcol + 13);
1139 printw("%4d%8d%9d", this.game, game.game, total.game);
1140 move(tboxrow + 5, boxcol + 13);
1141 printw("%4d%8d%9d", this.runs, game.runs, total.runs);
1142 move(tboxrow + 6, boxcol + 13);
1143 printw("%4d%8d%9d", this.information, game.information,
1144 total.information);
1145 move(tboxrow + 7, boxcol + 13);
1146 printw("%4d%8d%9d", this.thinktime, game.thinktime, total.thinktime);
1147 move(tboxrow + 8, boxcol + 13);
1148 printw("%4d%8d%9d", thiscosts, gamecosts, totalcosts);
1149 move(tboxrow + 9, boxcol + 13);
1150 printw("%4d%8d%9d", this.wins, game.wins, total.wins);
1151 move(tboxrow + 10, boxcol + 13);
1152 printw("%4d%8d%9d", this.worth, game.worth, total.worth);
1153 move(tboxrow + 11, boxcol + 13);
1154 printw("%4.0f%%%7.1f%%%8.1f%%", thisreturn, gamereturn, totalreturn);
1158 * procedure to move a card from the stock or talon to the tableau
1160 static void
1161 simpletableau(struct cardtype **cp, int des)
1163 int origin;
1165 if (notempty(*cp)) {
1166 if (tabok(*cp, des)) {
1167 if (*cp == stock)
1168 origin = stk;
1169 else
1170 origin = tal;
1171 if (tableau[des] == NIL)
1172 bottom[des] = *cp;
1173 transit(cp, &tableau[des]);
1174 length[des]++;
1175 printcard(pilemap[des], length[des], tableau[des]);
1176 timesthru = 0;
1177 if (origin == stk) {
1178 usedstock();
1179 printcard(stockcol, stockrow, stock);
1180 } else {
1181 usedtalon();
1182 printcard(taloncol, talonrow, talon);
1184 } else
1185 destinerror();
1190 * print the tableau
1192 static void
1193 tabprint(int sour, int des)
1195 int dlength, slength, i;
1196 struct cardtype *tempcard;
1198 for (i=tabrow; i<=length[sour]; i++)
1199 removecard(pilemap[sour], i);
1200 dlength = length[des] + 1;
1201 slength = length[sour];
1202 if (slength == tabrow)
1203 printcard(pilemap[des], dlength, tableau[sour]);
1204 else
1205 while (slength != tabrow - 1) {
1206 tempcard = tableau[sour];
1207 for (i=1; i<=slength-tabrow; i++)
1208 tempcard = tempcard->next;
1209 printcard(pilemap[des], dlength, tempcard);
1210 slength--;
1211 dlength++;
1216 * procedure to move from the tableau to the tableau
1218 static void
1219 tabtotab(int sour, int des)
1221 struct cardtype *temp;
1223 if (notempty(tableau[sour])) {
1224 if (tabok(bottom[sour], des)) {
1225 tabprint(sour, des);
1226 temp = bottom[sour];
1227 bottom[sour] = NIL;
1228 if (bottom[des] == NIL)
1229 bottom[des] = temp;
1230 temp->next = tableau[des];
1231 tableau[des] = tableau[sour];
1232 tableau[sour] = NIL;
1233 length[des] = length[des] +
1234 (length[sour] - (tabrow - 1));
1235 length[sour] = tabrow - 1;
1236 timesthru = 0;
1237 } else
1238 destinerror();
1243 * functions to see if the card can go onto the foundation
1245 static bool
1246 rankhigher(struct cardtype *cp, int let)
1248 if (found[let]->rank == King)
1249 if (cp->rank == Ace)
1250 return(TRUE);
1251 else
1252 return(FALSE);
1253 else if (cp->rank - 1 == found[let]->rank)
1254 return(TRUE);
1255 else
1256 return(FALSE);
1260 * function to determine if two cards are the same suit
1262 static bool
1263 samesuit(struct cardtype *cp, int let)
1265 if (cp->suit == found[let]->suit)
1266 return (TRUE);
1267 else
1268 return (FALSE);
1272 * procedure to move a card to the correct foundation pile
1274 static void
1275 movetofound(struct cardtype **cp, int source)
1277 tempbase = 0;
1278 mtfdone = FALSE;
1279 if (notempty(*cp)) {
1280 do {
1281 if (found[tempbase] != NIL)
1282 if (rankhigher(*cp, tempbase)
1283 && samesuit(*cp, tempbase)) {
1284 if (*cp == stock)
1285 mtforigin = stk;
1286 else if (*cp == talon)
1287 mtforigin = tal;
1288 else
1289 mtforigin = tab;
1290 transit(cp, &found[tempbase]);
1291 printcard(pilemap[tempbase],
1292 foundrow, found[tempbase]);
1293 timesthru = 0;
1294 if (mtforigin == stk) {
1295 usedstock();
1296 printcard(stockcol, stockrow,
1297 stock);
1298 } else if (mtforigin == tal) {
1299 usedtalon();
1300 printcard(taloncol, talonrow,
1301 talon);
1302 } else {
1303 removecard(pilemap[source],
1304 length[source]);
1305 length[source]--;
1307 cardsoff++;
1308 if (infullgame) {
1309 this.wins += valuepercardup;
1310 game.wins += valuepercardup;
1311 total.wins += valuepercardup;
1313 mtfdone = TRUE;
1314 } else
1315 tempbase++;
1316 else
1317 tempbase++;
1318 } while ((tempbase != 4) && !mtfdone);
1319 if (!mtfdone)
1320 destinerror();
1325 * procedure to get a command
1327 static void
1328 getcmd(int row, int col, const char *cp)
1330 char cmd[2], ch;
1331 int i;
1333 i = 0;
1334 move(row, col);
1335 printw("%-24s", cp);
1336 col += 1 + strlen(cp);
1337 move(row, col);
1338 refresh();
1339 do {
1340 ch = getch() & 0177;
1341 if (ch >= 'A' && ch <= 'Z')
1342 ch += ('a' - 'A');
1343 if (ch == '\f') {
1344 wrefresh(curscr);
1345 refresh();
1346 } else if (i >= 2 && ch != erasechar() && ch != killchar()) {
1347 if (ch != '\n' && ch != '\r' && ch != ' ')
1348 write(1, "\007", 1);
1349 } else if (ch == erasechar() && i > 0) {
1350 printw("\b \b");
1351 refresh();
1352 i--;
1353 } else if (ch == killchar() && i > 0) {
1354 while (i > 0) {
1355 printw("\b \b");
1356 i--;
1358 refresh();
1359 } else if (ch == '\032') { /* Control-Z */
1360 suspend();
1361 move(row, col + i);
1362 refresh();
1363 } else if (isprint(ch)) {
1364 cmd[i++] = ch;
1365 addch(ch);
1366 refresh();
1368 } while (ch != '\n' && ch != '\r' && ch != ' ');
1369 srcpile = cmd[0];
1370 destpile = cmd[1];
1374 * Suspend the game (shell escape if no process control on system)
1376 static void
1377 suspend(void)
1379 updatebettinginfo();
1380 move(21, 0);
1381 refresh();
1382 if (dbfd != -1) {
1383 lseek(dbfd, uid * sizeof(struct betinfo), SEEK_SET);
1384 write(dbfd, (char *)&total, sizeof(total));
1386 kill(getpid(), SIGTSTP);
1387 raw();
1388 noecho();
1392 * procedure to evaluate and make the specific moves
1394 static void
1395 movecard(void)
1397 int source, dest;
1398 char osrcpile, odestpile;
1400 source = 0;
1401 dest = 0;
1402 done = FALSE;
1403 errmsg = FALSE;
1404 do {
1405 if (talon == NIL && hand != NIL)
1406 movetotalon();
1407 if (cardsoff == 52) {
1408 refresh();
1409 srcpile = 'q';
1410 } else if (!startedgame) {
1411 move(msgrow, msgcol);
1412 errmsg = TRUE;
1413 switch (34 - taloncnt - cinhand) {
1414 default:
1415 errmsg = FALSE;
1416 break;
1417 case 1:
1418 printw("One card used from talon ");
1419 break;
1420 case 2:
1421 printw("Two cards used from talon ");
1422 break;
1423 case 3:
1424 printw(">3< cards used from talon ");
1425 break;
1427 getcmd(moverow, movecol, "Move:");
1428 } else
1429 getcmd(moverow, movecol, "Move:");
1430 clearmsg();
1431 if (srcpile >= '1' && srcpile <= '4')
1432 source = (int) (srcpile - '1');
1433 if (destpile >= '1' && destpile <= '4')
1434 dest = (int) (destpile - '1');
1435 if (!startedgame &&
1436 (srcpile == 't' || srcpile == 's' || srcpile == 'h' ||
1437 srcpile == '1' || srcpile == '2' || srcpile == '3' ||
1438 srcpile == '4')) {
1439 startedgame = TRUE;
1440 osrcpile = srcpile;
1441 odestpile = destpile;
1442 if (status != BETTINGBOX)
1443 srcpile = 'y';
1444 else do {
1445 getcmd(moverow, movecol, "Inspect game?");
1446 } while (srcpile != 'y' && srcpile != 'n');
1447 if (srcpile == 'n') {
1448 srcpile = 'q';
1449 } else {
1450 this.inspection += costofinspection;
1451 game.inspection += costofinspection;
1452 total.inspection += costofinspection;
1453 srcpile = osrcpile;
1454 destpile = odestpile;
1457 switch (srcpile) {
1458 case 't':
1459 if (destpile == 'f' || destpile == 'F')
1460 movetofound(&talon, source);
1461 else if (destpile >= '1' && destpile <= '4')
1462 simpletableau(&talon, dest);
1463 else
1464 dumberror();
1465 break;
1466 case 's':
1467 if (destpile == 'f' || destpile == 'F')
1468 movetofound(&stock, source);
1469 else if (destpile >= '1' && destpile <= '4')
1470 simpletableau(&stock, dest);
1471 else dumberror();
1472 break;
1473 case 'h':
1474 if (destpile != 't' && destpile != 'T') {
1475 dumberror();
1476 break;
1478 if (infullgame) {
1479 movetotalon();
1480 break;
1482 if (status == BETTINGBOX) {
1483 do {
1484 getcmd(moverow, movecol,
1485 "Buy game?");
1486 } while (srcpile != 'y' &&
1487 srcpile != 'n');
1488 if (srcpile == 'n') {
1489 showcards();
1490 done = TRUE;
1491 break;
1494 infullgame = TRUE;
1495 this.wins += valuepercardup * cardsoff;
1496 game.wins += valuepercardup * cardsoff;
1497 total.wins += valuepercardup * cardsoff;
1498 this.game += costofgame;
1499 game.game += costofgame;
1500 total.game += costofgame;
1501 movetotalon();
1502 break;
1503 case 'q':
1504 showcards();
1505 done = TRUE;
1506 break;
1507 case 'b':
1508 printtopbettingbox();
1509 printbottombettingbox();
1510 status = BETTINGBOX;
1511 break;
1512 case 'x':
1513 clearabovemovebox();
1514 clearbelowmovebox();
1515 status = NOBOX;
1516 break;
1517 case 'i':
1518 printtopinstructions();
1519 printbottominstructions();
1520 status = INSTRUCTIONBOX;
1521 break;
1522 case 'c':
1523 Cflag = !Cflag;
1524 if (Cflag)
1525 showstat();
1526 else
1527 clearstat();
1528 break;
1529 case '1': case '2': case '3': case '4':
1530 if (destpile == 'f' || destpile == 'F')
1531 movetofound(&tableau[source], source);
1532 else if (destpile >= '1' && destpile <= '4')
1533 tabtotab(source, dest);
1534 else dumberror();
1535 break;
1536 default:
1537 dumberror();
1539 fndbase(&stock, stockcol, stockrow);
1540 fndbase(&talon, taloncol, talonrow);
1541 updatebettinginfo();
1542 } while (!done);
1545 const char *const basicinstructions[] = {
1546 "Here are brief instructions to the game of Canfield:\n\n",
1547 " If you have never played solitaire before, it is recom-\n",
1548 "mended that you consult a solitaire instruction book. In\n",
1549 "Canfield, tableau cards may be built on each other downward\n",
1550 "in alternate colors. An entire pile must be moved as a unit\n",
1551 "in building. Top cards of the piles are available to be able\n",
1552 "to be played on foundations, but never into empty spaces.\n\n",
1553 " Spaces must be filled from the stock. The top card of\n",
1554 "the stock also is available to be played on foundations or\n",
1555 "built on tableau piles. After the stock is exhausted, ta-\n",
1556 "bleau spaces may be filled from the talon and the player may\n",
1557 "keep them open until he wishes to use them.\n\n",
1558 " Cards are dealt from the hand to the talon by threes\n",
1559 "and this repeats until there are no more cards in the hand\n",
1560 "or the player quits. To have cards dealt onto the talon the\n",
1561 "player types 'ht' for his move. Foundation base cards are\n",
1562 "also automatically moved to the foundation when they become\n",
1563 "available.\n\n",
1564 "push any key when you are finished: ",
1565 0 };
1567 const char *const bettinginstructions[] = {
1568 " The rules for betting are somewhat less strict than\n",
1569 "those used in the official version of the game. The initial\n",
1570 "deal costs $13. You may quit at this point or inspect the\n",
1571 "game. Inspection costs $13 and allows you to make as many\n",
1572 "moves as is possible without moving any cards from your hand\n",
1573 "to the talon. (the initial deal places three cards on the\n",
1574 "talon; if all these cards are used, three more are made\n",
1575 "available) Finally, if the game seems interesting, you must\n",
1576 "pay the final installment of $26. At this point you are\n",
1577 "credited at the rate of $5 for each card on the foundation;\n",
1578 "as the game progresses you are credited with $5 for each\n",
1579 "card that is moved to the foundation. Each run through the\n",
1580 "hand after the first costs $5. The card counting feature\n",
1581 "costs $1 for each unknown card that is identified. If the\n",
1582 "information is toggled on, you are only charged for cards\n",
1583 "that became visible since it was last turned on. Thus the\n",
1584 "maximum cost of information is $34. Playing time is charged\n",
1585 "at a rate of $1 per minute.\n\n",
1586 "push any key when you are finished: ",
1587 0 };
1590 * procedure to printout instructions
1592 static void
1593 instruct(void)
1595 const char *const *cp;
1597 move(originrow, origincol);
1598 printw("This is the game of solitaire called Canfield. Do\n");
1599 printw("you want instructions for the game?");
1600 do {
1601 getcmd(originrow + 3, origincol, "y or n?");
1602 } while (srcpile != 'y' && srcpile != 'n');
1603 if (srcpile == 'n')
1604 return;
1605 clear();
1606 for (cp = basicinstructions; *cp != NULL; cp++)
1607 printw(*cp);
1608 refresh();
1609 getch();
1610 clear();
1611 move(originrow, origincol);
1612 printw("Do you want instructions for betting?");
1613 do {
1614 getcmd(originrow + 2, origincol, "y or n?");
1615 } while (srcpile != 'y' && srcpile != 'n');
1616 if (srcpile == 'n')
1617 return;
1618 clear();
1619 for (cp = bettinginstructions; *cp != NULL; cp++)
1620 printw(*cp);
1621 refresh();
1622 getch();
1626 * procedure to initialize the game
1628 static void
1629 initall(void)
1631 int i;
1633 if (dbfd < 0)
1634 return;
1635 srandomdev();
1636 time(&acctstart);
1637 initdeck(deck);
1638 uid = getuid();
1640 i = lseek(dbfd, uid * sizeof(struct betinfo), SEEK_SET);
1641 if (i < 0) {
1642 close(dbfd);
1643 dbfd = -1;
1644 return;
1646 i = read(dbfd, (char *)&total, sizeof(total));
1647 if (i < 0) {
1648 close(dbfd);
1649 dbfd = -1;
1650 return;
1655 * procedure to end the game
1657 static bool
1658 finish(void)
1660 int row, col;
1662 if (cardsoff == 52) {
1663 getcmd(moverow, movecol, "Hit return to exit");
1664 clear();
1665 refresh();
1666 move(originrow, origincol);
1667 printw("CONGRATULATIONS!\n");
1668 printw("You won the game. That is a feat to be proud of.\n");
1669 row = originrow + 5;
1670 col = origincol;
1671 } else {
1672 move(msgrow, msgcol);
1673 printw("You got %d card", cardsoff);
1674 if (cardsoff > 1)
1675 printw("s");
1676 printw(" off ");
1677 move(msgrow, msgcol);
1678 row = moverow;
1679 col = movecol;
1681 do {
1682 getcmd(row, col, "Play again (y or n)?");
1683 } while (srcpile != 'y' && srcpile != 'n');
1684 errmsg = TRUE;
1685 clearmsg();
1686 if (srcpile == 'y')
1687 return (FALSE);
1688 else
1689 return (TRUE);
1693 * procedure to clean up and exit
1695 static void
1696 cleanup(int sig __unused)
1699 total.thinktime += 1;
1700 status = NOBOX;
1701 updatebettinginfo();
1702 if (dbfd != -1) {
1703 lseek(dbfd, uid * sizeof(struct betinfo), SEEK_SET);
1704 write(dbfd, (char *)&total, sizeof(total));
1705 close(dbfd);
1707 clear();
1708 move(22,0);
1709 refresh();
1710 endwin();
1711 exit(0);
1712 /* NOTREACHED */
1716 * Field an interrupt.
1718 static void
1719 askquit(int sig __unused)
1721 move(msgrow, msgcol);
1722 printw("Really wish to quit? ");
1723 do {
1724 getcmd(moverow, movecol, "y or n?");
1725 } while (srcpile != 'y' && srcpile != 'n');
1726 clearmsg();
1727 if (srcpile == 'y')
1728 cleanup(0);
1729 signal(SIGINT, askquit);
1733 * Can you tell that this used to be a Pascal program?
1736 main(void)
1738 dbfd = open(_PATH_SCORE, O_RDWR);
1740 /* revoke */
1741 setgid(getgid());
1743 #ifdef MAXLOAD
1744 double vec[3];
1746 loadav(vec);
1747 if (vec[2] >= MAXLOAD) {
1748 puts("The system load is too high. Try again later.");
1749 exit(0);
1751 #endif
1752 signal(SIGINT, askquit);
1753 signal(SIGHUP, cleanup);
1754 signal(SIGTERM, cleanup);
1755 initscr();
1756 raw();
1757 noecho();
1758 initall();
1759 instruct();
1760 makeboard();
1761 for (;;) {
1762 startgame();
1763 movecard();
1764 if (finish())
1765 break;
1766 if (cardsoff == 52)
1767 makeboard();
1768 else
1769 cleanupboard();
1771 cleanup(0);
1772 /* NOTREACHED */
1773 return (EXIT_FAILURE);