MFC r1.6 (HEAD):
[dragonfly.git] / games / canfield / canfield / canfield.c
blobaa1ff0ce0975a014ff467651c12615788c0b4419
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. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
34 * @(#)canfield.c 8.1 (Berkeley) 5/31/93
35 * $FreeBSD: src/games/canfield/canfield/canfield.c,v 1.11 1999/12/12 07:25:13 billf Exp $
36 * $DragonFly: src/games/canfield/canfield/canfield.c,v 1.4 2005/11/19 09:50:30 swildner Exp $
40 * The canfield program
42 * Authors:
43 * Originally written: Steve Levine
44 * Converted to use curses and debugged: Steve Feldman
45 * Card counting: Kirk McKusick and Mikey Olson
46 * User interface cleanups: Eric Allman and Kirk McKusick
47 * Betting by Kirk McKusick
50 #include <sys/types.h>
52 #include <curses.h>
53 #include <ctype.h>
54 #include <signal.h>
55 #include <unistd.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <fcntl.h>
60 #include "pathnames.h"
62 #define decksize 52
63 #define originrow 0
64 #define origincol 0
65 #define basecol 1
66 #define boxcol 42
67 #define tboxrow 2
68 #define bboxrow 17
69 #define movecol 43
70 #define moverow 16
71 #define msgcol 43
72 #define msgrow 15
73 #define titlecol 30
74 #define titlerow 0
75 #define sidecol 1
76 #define ottlrow 6
77 #define foundcol 11
78 #define foundrow 3
79 #define stockcol 2
80 #define stockrow 8
81 #define fttlcol 10
82 #define fttlrow 1
83 #define taloncol 2
84 #define talonrow 13
85 #define tabrow 8
86 #define ctoprow 21
87 #define cbotrow 23
88 #define cinitcol 14
89 #define cheightcol 1
90 #define cwidthcol 4
91 #define handstatrow 21
92 #define handstatcol 7
93 #define talonstatrow 22
94 #define talonstatcol 7
95 #define stockstatrow 23
96 #define stockstatcol 7
97 #define Ace 1
98 #define Jack 11
99 #define Queen 12
100 #define King 13
101 #define atabcol 11
102 #define btabcol 18
103 #define ctabcol 25
104 #define dtabcol 32
106 #define spades 's'
107 #define clubs 'c'
108 #define hearts 'h'
109 #define diamonds 'd'
110 #define black 'b'
111 #define red 'r'
113 #define stk 1
114 #define tal 2
115 #define tab 3
116 #define INCRHAND(row, col) {\
117 row -= cheightcol;\
118 if (row < ctoprow) {\
119 row = cbotrow;\
120 col += cwidthcol;\
123 #define DECRHAND(row, col) {\
124 row += cheightcol;\
125 if (row > cbotrow) {\
126 row = ctoprow;\
127 col -= cwidthcol;\
132 struct cardtype {
133 char suit;
134 char color;
135 bool visible;
136 bool paid;
137 int rank;
138 struct cardtype *next;
141 #define NIL ((struct cardtype *) -1)
143 struct cardtype *deck[decksize];
144 struct cardtype cards[decksize];
145 struct cardtype *bottom[4], *found[4], *tableau[4];
146 struct cardtype *talon, *hand, *stock, *basecard;
147 int length[4];
148 int cardsoff, base, cinhand, taloncnt, stockcnt, timesthru;
149 char suitmap[4] = {spades, clubs, hearts, diamonds};
150 char colormap[4] = {black, black, red, red};
151 char pilemap[4] = {atabcol, btabcol, ctabcol, dtabcol};
152 char srcpile, destpile;
153 int mtforigin, tempbase;
154 int coldcol, cnewcol, coldrow, cnewrow;
155 bool errmsg, done;
156 bool mtfdone, Cflag = FALSE;
157 #define INSTRUCTIONBOX 1
158 #define BETTINGBOX 2
159 #define NOBOX 3
160 int status = INSTRUCTIONBOX;
161 int uid;
164 * Basic betting costs
166 #define costofhand 13
167 #define costofinspection 13
168 #define costofgame 26
169 #define costofrunthroughhand 5
170 #define costofinformation 1
171 #define secondsperdollar 60
172 #define maxtimecharge 3
173 #define valuepercardup 5
175 * Variables associated with betting
177 struct betinfo {
178 long hand; /* cost of dealing hand */
179 long inspection; /* cost of inspecting hand */
180 long game; /* cost of buying game */
181 long runs; /* cost of running through hands */
182 long information; /* cost of information */
183 long thinktime; /* cost of thinking time */
184 long wins; /* total winnings */
185 long worth; /* net worth after costs */
187 struct betinfo this, game, total;
188 bool startedgame = FALSE, infullgame = FALSE;
189 time_t acctstart;
190 int dbfd = -1;
192 static void askquit(int);
193 static void cleanup(int);
194 static void cleanupboard(void);
195 static void clearabovemovebox(void);
196 static void clearbelowmovebox(void);
197 static void clearmsg(void);
198 static void clearstat(void);
199 static void destinerror(void);
200 static bool diffcolor(struct cardtype *, struct cardtype *);
201 static void dumberror(void);
202 static bool finish(void);
203 static void fndbase(struct cardtype **, int, int);
204 static void getcmd(int, int, const char *);
205 static void initall(void);
206 static void initdeck(struct cardtype **);
207 static void initgame(void);
208 static void instruct(void);
209 static void makeboard(void);
210 static void movebox(void);
211 static void movecard(void);
212 static void movetofound(struct cardtype **, int);
213 static void movetotalon(void);
214 static bool notempty(struct cardtype *);
215 static void printbottombettingbox(void);
216 static void printbottominstructions(void);
217 static void printcard(int, int, struct cardtype *);
218 static void printrank(int, int, struct cardtype *, bool);
219 static void printtopbettingbox(void);
220 static void printtopinstructions(void);
221 static bool rankhigher(struct cardtype *, int);
222 static bool ranklower(struct cardtype *, struct cardtype *);
223 static void removecard(int, int);
224 static bool samesuit(struct cardtype *, int);
225 static void showcards(void);
226 static void showstat(void);
227 static void shuffle(struct cardtype **);
228 static void simpletableau(struct cardtype **, int);
229 static void startgame(void);
230 static void suspend(void);
231 static bool tabok(struct cardtype *, int);
232 static void tabprint(int, int);
233 static void tabtotab(int, int);
234 static void transit(struct cardtype **, struct cardtype **);
235 static void updatebettinginfo(void);
236 static void usedstock(void);
237 static void usedtalon(void);
240 * The following procedures print the board onto the screen using the
241 * addressible cursor. The end of these procedures will also be
242 * separated from the rest of the program.
244 * procedure to set the move command box
246 static void
247 movebox(void)
249 switch (status) {
250 case BETTINGBOX:
251 printtopbettingbox();
252 break;
253 case NOBOX:
254 clearabovemovebox();
255 break;
256 case INSTRUCTIONBOX:
257 printtopinstructions();
258 break;
260 move(moverow, boxcol);
261 printw("| |");
262 move(msgrow, boxcol);
263 printw("| |");
264 switch (status) {
265 case BETTINGBOX:
266 printbottombettingbox();
267 break;
268 case NOBOX:
269 clearbelowmovebox();
270 break;
271 case INSTRUCTIONBOX:
272 printbottominstructions();
273 break;
275 refresh();
279 * print directions above move box
281 static void
282 printtopinstructions(void)
284 move(tboxrow, boxcol);
285 printw("*----------------------------------*");
286 move(tboxrow + 1, boxcol);
287 printw("| MOVES |");
288 move(tboxrow + 2, boxcol);
289 printw("|s# = stock to tableau |");
290 move(tboxrow + 3, boxcol);
291 printw("|sf = stock to foundation |");
292 move(tboxrow + 4, boxcol);
293 printw("|t# = talon to tableau |");
294 move(tboxrow + 5, boxcol);
295 printw("|tf = talon to foundation |");
296 move(tboxrow + 6, boxcol);
297 printw("|## = tableau to tableau |");
298 move(tboxrow + 7, boxcol);
299 printw("|#f = tableau to foundation |");
300 move(tboxrow + 8, boxcol);
301 printw("|ht = hand to talon |");
302 move(tboxrow + 9, boxcol);
303 printw("|c = toggle card counting |");
304 move(tboxrow + 10, boxcol);
305 printw("|b = present betting information |");
306 move(tboxrow + 11, boxcol);
307 printw("|q = quit to end the game |");
308 move(tboxrow + 12, boxcol);
309 printw("|==================================|");
313 * Print the betting box.
315 static void
316 printtopbettingbox(void)
319 move(tboxrow, boxcol);
320 printw("*----------------------------------*");
321 move(tboxrow + 1, boxcol);
322 printw("|Costs Hand Game Total |");
323 move(tboxrow + 2, boxcol);
324 printw("| Hands |");
325 move(tboxrow + 3, boxcol);
326 printw("| Inspections |");
327 move(tboxrow + 4, boxcol);
328 printw("| Games |");
329 move(tboxrow + 5, boxcol);
330 printw("| Runs |");
331 move(tboxrow + 6, boxcol);
332 printw("| Information |");
333 move(tboxrow + 7, boxcol);
334 printw("| Think time |");
335 move(tboxrow + 8, boxcol);
336 printw("|Total Costs |");
337 move(tboxrow + 9, boxcol);
338 printw("|Winnings |");
339 move(tboxrow + 10, boxcol);
340 printw("|Net Worth |");
341 move(tboxrow + 11, boxcol);
342 printw("|Return |");
343 move(tboxrow + 12, boxcol);
344 printw("|==================================|");
348 * clear info above move box
350 static void
351 clearabovemovebox(void)
353 int i;
355 for (i = 0; i <= 11; i++) {
356 move(tboxrow + i, boxcol);
357 printw(" ");
359 move(tboxrow + 12, boxcol);
360 printw("*----------------------------------*");
364 * print instructions below move box
366 static void
367 printbottominstructions(void)
369 move(bboxrow, boxcol);
370 printw("|Replace # with the number of the |");
371 move(bboxrow + 1, boxcol);
372 printw("|tableau you want. |");
373 move(bboxrow + 2, boxcol);
374 printw("*----------------------------------*");
378 * print betting information below move box
380 static void
381 printbottombettingbox(void)
383 move(bboxrow, boxcol);
384 printw("|x = toggle information box |");
385 move(bboxrow + 1, boxcol);
386 printw("|i = list playing instructions |");
387 move(bboxrow + 2, boxcol);
388 printw("*----------------------------------*");
392 * clear info below move box
394 static void
395 clearbelowmovebox(void)
397 int i;
399 move(bboxrow, boxcol);
400 printw("*----------------------------------*");
401 for (i = 1; i <= 2; i++) {
402 move(bboxrow + i, boxcol);
403 printw(" ");
408 * procedure to put the board on the screen using addressable cursor
410 static void
411 makeboard(void)
413 clear();
414 refresh();
415 move(titlerow, titlecol);
416 printw("=-> CANFIELD <-=");
417 move(fttlrow, fttlcol);
418 printw("foundation");
419 move(foundrow - 1, fttlcol);
420 printw("=---= =---= =---= =---=");
421 move(foundrow, fttlcol);
422 printw("| | | | | | | |");
423 move(foundrow + 1, fttlcol);
424 printw("=---= =---= =---= =---=");
425 move(ottlrow, sidecol);
426 printw("stock tableau");
427 move(stockrow - 1, sidecol);
428 printw("=---=");
429 move(stockrow, sidecol);
430 printw("| |");
431 move(stockrow + 1, sidecol);
432 printw("=---=");
433 move(talonrow - 2, sidecol);
434 printw("talon");
435 move(talonrow - 1, sidecol);
436 printw("=---=");
437 move(talonrow, sidecol);
438 printw("| |");
439 move(talonrow + 1, sidecol);
440 printw("=---=");
441 move(tabrow - 1, atabcol);
442 printw("-1- -2- -3- -4-");
443 movebox();
447 * clean up the board for another game
449 static void
450 cleanupboard(void)
452 int cnt, row, col;
453 struct cardtype *ptr;
455 col = 0;
456 if (Cflag) {
457 clearstat();
458 for(ptr = stock, row = stockrow;
459 ptr != NIL;
460 ptr = ptr->next, row++) {
461 move(row, sidecol);
462 printw(" ");
464 move(row, sidecol);
465 printw(" ");
466 move(stockrow + 1, sidecol);
467 printw("=---=");
468 move(talonrow - 2, sidecol);
469 printw("talon");
470 move(talonrow - 1, sidecol);
471 printw("=---=");
472 move(talonrow + 1, sidecol);
473 printw("=---=");
475 move(stockrow, sidecol);
476 printw("| |");
477 move(talonrow, sidecol);
478 printw("| |");
479 move(foundrow, fttlcol);
480 printw("| | | | | | | |");
481 for (cnt = 0; cnt < 4; cnt++) {
482 switch(cnt) {
483 case 0:
484 col = atabcol;
485 break;
486 case 1:
487 col = btabcol;
488 break;
489 case 2:
490 col = ctabcol;
491 break;
492 case 3:
493 col = dtabcol;
494 break;
496 for(ptr = tableau[cnt], row = tabrow;
497 ptr != NIL;
498 ptr = ptr->next, row++)
499 removecard(col, row);
504 * procedure to create a deck of cards
506 static void
507 initdeck(struct cardtype **ldeck)
509 int i;
510 int scnt;
511 char s;
512 int r;
514 i = 0;
515 for (scnt=0; scnt<4; scnt++) {
516 s = suitmap[scnt];
517 for (r=Ace; r<=King; r++) {
518 ldeck[i] = &cards[i];
519 cards[i].rank = r;
520 cards[i].suit = s;
521 cards[i].color = colormap[scnt];
522 cards[i].next = NIL;
523 i++;
529 * procedure to shuffle the deck
531 static void
532 shuffle(struct cardtype **ldeck)
534 int i,j;
535 struct cardtype *temp;
537 for (i=0; i<decksize; i++) {
538 ldeck[i]->visible = FALSE;
539 ldeck[i]->paid = FALSE;
541 for (i = decksize-1; i>=0; i--) {
542 j = random() % decksize;
543 if (i != j) {
544 temp = ldeck[i];
545 ldeck[i] = ldeck[j];
546 ldeck[j] = temp;
552 * procedure to remove the card from the board
554 static void
555 removecard(int a, int b)
557 move(b, a);
558 printw(" ");
562 * procedure to print the cards on the board
564 static void
565 printrank(int a, int b, struct cardtype *cp, bool inverse)
567 move(b, a);
568 if (cp->rank != 10)
569 addch(' ');
570 if (inverse)
571 standout();
572 switch (cp->rank) {
573 case 2: case 3: case 4: case 5: case 6: case 7:
574 case 8: case 9: case 10:
575 printw("%d", cp->rank);
576 break;
577 case Ace:
578 addch('A');
579 break;
580 case Jack:
581 addch('J');
582 break;
583 case Queen:
584 addch('Q');
585 break;
586 case King:
587 addch('K');
589 if (inverse)
590 standend();
594 * procedure to print out a card
596 static void
597 printcard(int a, int b, struct cardtype *cp)
599 if (cp == NIL)
600 removecard(a, b);
601 else if (cp->visible == FALSE) {
602 move(b, a);
603 printw(" ? ");
604 } else {
605 bool inverse = (cp->suit == 'd' || cp->suit == 'h');
607 printrank(a, b, cp, inverse);
608 if (inverse)
609 standout();
610 addch(cp->suit);
611 if (inverse)
612 standend();
617 * procedure to move the top card from one location to the top
618 * of another location. The pointers always point to the top
619 * of the piles.
621 static void
622 transit(struct cardtype **source, struct cardtype **dest)
624 struct cardtype *temp;
626 temp = *source;
627 *source = (*source)->next;
628 temp->next = *dest;
629 *dest = temp;
633 * Procedure to set the cards on the foundation base when available.
634 * Note that it is only called on a foundation pile at the beginning of
635 * the game, so the pile will have exactly one card in it.
637 static void
638 fndbase(struct cardtype **cp, int column, int row)
640 bool nomore;
642 if (*cp != NIL)
643 do {
644 if ((*cp)->rank == basecard->rank) {
645 base++;
646 printcard(pilemap[base], foundrow, *cp);
647 if (*cp == tableau[0])
648 length[0] = length[0] - 1;
649 if (*cp == tableau[1])
650 length[1] = length[1] - 1;
651 if (*cp == tableau[2])
652 length[2] = length[2] - 1;
653 if (*cp == tableau[3])
654 length[3] = length[3] - 1;
655 transit(cp, &found[base]);
656 if (cp == &talon)
657 usedtalon();
658 if (cp == &stock)
659 usedstock();
660 if (*cp != NIL) {
661 printcard(column, row, *cp);
662 nomore = FALSE;
663 } else {
664 removecard(column, row);
665 nomore = TRUE;
667 cardsoff++;
668 if (infullgame) {
669 this.wins += valuepercardup;
670 game.wins += valuepercardup;
671 total.wins += valuepercardup;
673 } else
674 nomore = TRUE;
675 } while (nomore == FALSE);
679 * procedure to initialize the things necessary for the game
681 static void
682 initgame(void)
684 int i;
686 for (i=0; i<18; i++) {
687 deck[i]->visible = TRUE;
688 deck[i]->paid = TRUE;
690 stockcnt = 13;
691 stock = deck[12];
692 for (i=12; i>=1; i--)
693 deck[i]->next = deck[i - 1];
694 deck[0]->next = NIL;
695 found[0] = deck[13];
696 deck[13]->next = NIL;
697 for (i=1; i<4; i++)
698 found[i] = NIL;
699 basecard = found[0];
700 for (i=14; i<18; i++) {
701 tableau[i - 14] = deck[i];
702 deck[i]->next = NIL;
704 for (i=0; i<4; i++) {
705 bottom[i] = tableau[i];
706 length[i] = tabrow;
708 hand = deck[18];
709 for (i=18; i<decksize-1; i++)
710 deck[i]->next = deck[i + 1];
711 deck[decksize-1]->next = NIL;
712 talon = NIL;
713 base = 0;
714 cinhand = 34;
715 taloncnt = 0;
716 timesthru = 0;
717 cardsoff = 1;
718 coldrow = ctoprow;
719 coldcol = cinitcol;
720 cnewrow = ctoprow;
721 cnewcol = cinitcol + cwidthcol;
725 * procedure to print the beginning cards and to start each game
727 static void
728 startgame(void)
730 int j;
732 shuffle(deck);
733 initgame();
734 this.hand = costofhand;
735 game.hand += costofhand;
736 total.hand += costofhand;
737 this.inspection = 0;
738 this.game = 0;
739 this.runs = 0;
740 this.information = 0;
741 this.wins = 0;
742 this.thinktime = 0;
743 infullgame = FALSE;
744 startedgame = FALSE;
745 printcard(foundcol, foundrow, found[0]);
746 printcard(stockcol, stockrow, stock);
747 printcard(atabcol, tabrow, tableau[0]);
748 printcard(btabcol, tabrow, tableau[1]);
749 printcard(ctabcol, tabrow, tableau[2]);
750 printcard(dtabcol, tabrow, tableau[3]);
751 printcard(taloncol, talonrow, talon);
752 move(foundrow - 2, basecol);
753 printw("Base");
754 move(foundrow - 1, basecol);
755 printw("Rank");
756 printrank(basecol, foundrow, found[0], 0);
757 for (j=0; j<=3; j++)
758 fndbase(&tableau[j], pilemap[j], tabrow);
759 fndbase(&stock, stockcol, stockrow);
760 showstat(); /* show card counting info to cheaters */
761 movetotalon();
762 updatebettinginfo();
766 * procedure to clear the message printed from an error
768 static void
769 clearmsg(void)
771 int i;
773 if (errmsg == TRUE) {
774 errmsg = FALSE;
775 move(msgrow, msgcol);
776 for (i=0; i<25; i++)
777 addch(' ');
778 refresh();
783 * procedure to print an error message if the move is not listed
785 static void
786 dumberror(void)
788 errmsg = TRUE;
789 move(msgrow, msgcol);
790 printw("Not a proper move ");
794 * procedure to print an error message if the move is not possible
796 static void
797 destinerror(void)
799 errmsg = TRUE;
800 move(msgrow, msgcol);
801 printw("Error: Can't move there");
805 * function to see if the source has cards in it
807 static bool
808 notempty(struct cardtype *cp)
810 if (cp == NIL) {
811 errmsg = TRUE;
812 move(msgrow, msgcol);
813 printw("Error: no cards to move");
814 return (FALSE);
815 } else
816 return (TRUE);
820 * function to see if the rank of one card is less than another
822 static bool
823 ranklower(struct cardtype *cp1, struct cardtype *cp2)
825 if (cp2->rank == Ace)
826 if (cp1->rank == King)
827 return (TRUE);
828 else
829 return (FALSE);
830 else if (cp1->rank + 1 == cp2->rank)
831 return (TRUE);
832 else
833 return (FALSE);
837 * function to check the cardcolor for moving to a tableau
839 static bool
840 diffcolor(struct cardtype *cp1, struct cardtype *cp2)
842 if (cp1->color == cp2->color)
843 return (FALSE);
844 else
845 return (TRUE);
849 * function to see if the card can move to the tableau
851 static bool
852 tabok(struct cardtype *cp, int des)
854 if ((cp == stock) && (tableau[des] == NIL))
855 return (TRUE);
856 else if (tableau[des] == NIL)
857 if (stock == NIL &&
858 cp != bottom[0] && cp != bottom[1] &&
859 cp != bottom[2] && cp != bottom[3])
860 return (TRUE);
861 else
862 return (FALSE);
863 else if (ranklower(cp, tableau[des]) && diffcolor(cp, tableau[des]))
864 return (TRUE);
865 else
866 return (FALSE);
870 * procedure to turn the cards onto the talon from the deck
872 static void
873 movetotalon(void)
875 int i, fin;
877 if (cinhand <= 3 && cinhand > 0) {
878 move(msgrow, msgcol);
879 printw("Hand is now empty ");
881 if (cinhand >= 3)
882 fin = 3;
883 else if (cinhand > 0)
884 fin = cinhand;
885 else if (talon != NIL) {
886 timesthru++;
887 errmsg = TRUE;
888 move(msgrow, msgcol);
889 if (timesthru != 4) {
890 printw("Talon is now the new hand");
891 this.runs += costofrunthroughhand;
892 game.runs += costofrunthroughhand;
893 total.runs += costofrunthroughhand;
894 while (talon != NIL) {
895 transit(&talon, &hand);
896 cinhand++;
898 if (cinhand >= 3)
899 fin = 3;
900 else
901 fin = cinhand;
902 taloncnt = 0;
903 coldrow = ctoprow;
904 coldcol = cinitcol;
905 cnewrow = ctoprow;
906 cnewcol = cinitcol + cwidthcol;
907 clearstat();
908 showstat();
909 } else {
910 fin = 0;
911 done = TRUE;
912 printw("I believe you have lost");
913 refresh();
914 sleep(5);
916 } else {
917 errmsg = TRUE;
918 move(msgrow, msgcol);
919 printw("Talon and hand are empty");
920 fin = 0;
922 for (i=0; i<fin; i++) {
923 transit(&hand, &talon);
924 INCRHAND(cnewrow, cnewcol);
925 INCRHAND(coldrow, coldcol);
926 removecard(cnewcol, cnewrow);
927 if (i == fin - 1)
928 talon->visible = TRUE;
929 if (Cflag) {
930 if (talon->paid == FALSE && talon->visible == TRUE) {
931 this.information += costofinformation;
932 game.information += costofinformation;
933 total.information += costofinformation;
934 talon->paid = TRUE;
936 printcard(coldcol, coldrow, talon);
939 if (fin != 0) {
940 printcard(taloncol, talonrow, talon);
941 cinhand -= fin;
942 taloncnt += fin;
943 if (Cflag) {
944 move(handstatrow, handstatcol);
945 printw("%3d", cinhand);
946 move(talonstatrow, talonstatcol);
947 printw("%3d", taloncnt);
949 fndbase(&talon, taloncol, talonrow);
955 * procedure to print card counting info on screen
957 static void
958 showstat(void)
960 int row, col;
961 struct cardtype *ptr;
963 if (!Cflag)
964 return;
965 move(talonstatrow, talonstatcol - 7);
966 printw("Talon: %3d", taloncnt);
967 move(handstatrow, handstatcol - 7);
968 printw("Hand: %3d", cinhand);
969 move(stockstatrow, stockstatcol - 7);
970 printw("Stock: %3d", stockcnt);
971 for ( row = coldrow, col = coldcol, ptr = talon;
972 ptr != NIL;
973 ptr = ptr->next ) {
974 if (ptr->paid == FALSE && ptr->visible == TRUE) {
975 ptr->paid = TRUE;
976 this.information += costofinformation;
977 game.information += costofinformation;
978 total.information += costofinformation;
980 printcard(col, row, ptr);
981 DECRHAND(row, col);
983 for ( row = cnewrow, col = cnewcol, ptr = hand;
984 ptr != NIL;
985 ptr = ptr->next ) {
986 if (ptr->paid == FALSE && ptr->visible == TRUE) {
987 ptr->paid = TRUE;
988 this.information += costofinformation;
989 game.information += costofinformation;
990 total.information += costofinformation;
992 INCRHAND(row, col);
993 printcard(col, row, ptr);
998 * procedure to clear card counting info from screen
1000 static void
1001 clearstat(void)
1003 int row;
1005 move(talonstatrow, talonstatcol - 7);
1006 printw(" ");
1007 move(handstatrow, handstatcol - 7);
1008 printw(" ");
1009 move(stockstatrow, stockstatcol - 7);
1010 printw(" ");
1011 for ( row = ctoprow ; row <= cbotrow ; row++ ) {
1012 move(row, cinitcol);
1013 printw("%56s", " ");
1018 * procedure to update card counting base
1020 static void
1021 usedtalon(void)
1023 removecard(coldcol, coldrow);
1024 DECRHAND(coldrow, coldcol);
1025 if (talon != NIL && (talon->visible == FALSE)) {
1026 talon->visible = TRUE;
1027 if (Cflag) {
1028 this.information += costofinformation;
1029 game.information += costofinformation;
1030 total.information += costofinformation;
1031 talon->paid = TRUE;
1032 printcard(coldcol, coldrow, talon);
1035 taloncnt--;
1036 if (Cflag) {
1037 move(talonstatrow, talonstatcol);
1038 printw("%3d", taloncnt);
1043 * procedure to update stock card counting base
1045 static void
1046 usedstock(void)
1048 stockcnt--;
1049 if (Cflag) {
1050 move(stockstatrow, stockstatcol);
1051 printw("%3d", stockcnt);
1056 * let 'em know how they lost!
1058 static void
1059 showcards(void)
1061 struct cardtype *ptr;
1062 int row;
1064 if (!Cflag || cardsoff == 52)
1065 return;
1066 for (ptr = talon; ptr != NIL; ptr = ptr->next) {
1067 ptr->visible = TRUE;
1068 ptr->paid = TRUE;
1070 for (ptr = hand; ptr != NIL; ptr = ptr->next) {
1071 ptr->visible = TRUE;
1072 ptr->paid = TRUE;
1074 showstat();
1075 move(stockrow + 1, sidecol);
1076 printw(" ");
1077 move(talonrow - 2, sidecol);
1078 printw(" ");
1079 move(talonrow - 1, sidecol);
1080 printw(" ");
1081 move(talonrow, sidecol);
1082 printw(" ");
1083 move(talonrow + 1, sidecol);
1084 printw(" ");
1085 for (ptr = stock, row = stockrow; ptr != NIL; ptr = ptr->next, row++) {
1086 move(row, stockcol - 1);
1087 printw("| |");
1088 printcard(stockcol, row, ptr);
1090 if (stock == NIL) {
1091 move(row, stockcol - 1);
1092 printw("| |");
1093 row++;
1095 move(handstatrow, handstatcol - 7);
1096 printw(" ");
1097 move(row, stockcol - 1);
1098 printw("=---=");
1099 if ( cardsoff == 52 )
1100 getcmd(moverow, movecol, "Hit return to exit");
1104 * procedure to update the betting values
1106 static void
1107 updatebettinginfo(void)
1109 long thiscosts, gamecosts, totalcosts;
1110 double thisreturn, gamereturn, totalreturn;
1111 time_t now;
1112 long dollars;
1114 time(&now);
1115 dollars = (now - acctstart) / secondsperdollar;
1116 if (dollars > 0) {
1117 acctstart += dollars * secondsperdollar;
1118 if (dollars > maxtimecharge)
1119 dollars = maxtimecharge;
1120 this.thinktime += dollars;
1121 game.thinktime += dollars;
1122 total.thinktime += dollars;
1124 thiscosts = this.hand + this.inspection + this.game +
1125 this.runs + this.information + this.thinktime;
1126 gamecosts = game.hand + game.inspection + game.game +
1127 game.runs + game.information + game.thinktime;
1128 totalcosts = total.hand + total.inspection + total.game +
1129 total.runs + total.information + total.thinktime;
1130 this.worth = this.wins - thiscosts;
1131 game.worth = game.wins - gamecosts;
1132 total.worth = total.wins - totalcosts;
1133 thisreturn = ((double)this.wins / (double)thiscosts - 1.0) * 100.0;
1134 gamereturn = ((double)game.wins / (double)gamecosts - 1.0) * 100.0;
1135 totalreturn = ((double)total.wins / (double)totalcosts - 1.0) * 100.0;
1136 if (status != BETTINGBOX)
1137 return;
1138 move(tboxrow + 2, boxcol + 13);
1139 printw("%4d%8d%9d", this.hand, game.hand, total.hand);
1140 move(tboxrow + 3, boxcol + 13);
1141 printw("%4d%8d%9d", this.inspection, game.inspection, total.inspection);
1142 move(tboxrow + 4, boxcol + 13);
1143 printw("%4d%8d%9d", this.game, game.game, total.game);
1144 move(tboxrow + 5, boxcol + 13);
1145 printw("%4d%8d%9d", this.runs, game.runs, total.runs);
1146 move(tboxrow + 6, boxcol + 13);
1147 printw("%4d%8d%9d", this.information, game.information,
1148 total.information);
1149 move(tboxrow + 7, boxcol + 13);
1150 printw("%4d%8d%9d", this.thinktime, game.thinktime, total.thinktime);
1151 move(tboxrow + 8, boxcol + 13);
1152 printw("%4d%8d%9d", thiscosts, gamecosts, totalcosts);
1153 move(tboxrow + 9, boxcol + 13);
1154 printw("%4d%8d%9d", this.wins, game.wins, total.wins);
1155 move(tboxrow + 10, boxcol + 13);
1156 printw("%4d%8d%9d", this.worth, game.worth, total.worth);
1157 move(tboxrow + 11, boxcol + 13);
1158 printw("%4.0f%%%7.1f%%%8.1f%%", thisreturn, gamereturn, totalreturn);
1162 * procedure to move a card from the stock or talon to the tableau
1164 static void
1165 simpletableau(struct cardtype **cp, int des)
1167 int origin;
1169 if (notempty(*cp)) {
1170 if (tabok(*cp, des)) {
1171 if (*cp == stock)
1172 origin = stk;
1173 else
1174 origin = tal;
1175 if (tableau[des] == NIL)
1176 bottom[des] = *cp;
1177 transit(cp, &tableau[des]);
1178 length[des]++;
1179 printcard(pilemap[des], length[des], tableau[des]);
1180 timesthru = 0;
1181 if (origin == stk) {
1182 usedstock();
1183 printcard(stockcol, stockrow, stock);
1184 } else {
1185 usedtalon();
1186 printcard(taloncol, talonrow, talon);
1188 } else
1189 destinerror();
1194 * print the tableau
1196 static void
1197 tabprint(int sour, int des)
1199 int dlength, slength, i;
1200 struct cardtype *tempcard;
1202 for (i=tabrow; i<=length[sour]; i++)
1203 removecard(pilemap[sour], i);
1204 dlength = length[des] + 1;
1205 slength = length[sour];
1206 if (slength == tabrow)
1207 printcard(pilemap[des], dlength, tableau[sour]);
1208 else
1209 while (slength != tabrow - 1) {
1210 tempcard = tableau[sour];
1211 for (i=1; i<=slength-tabrow; i++)
1212 tempcard = tempcard->next;
1213 printcard(pilemap[des], dlength, tempcard);
1214 slength--;
1215 dlength++;
1220 * procedure to move from the tableau to the tableau
1222 static void
1223 tabtotab(int sour, int des)
1225 struct cardtype *temp;
1227 if (notempty(tableau[sour])) {
1228 if (tabok(bottom[sour], des)) {
1229 tabprint(sour, des);
1230 temp = bottom[sour];
1231 bottom[sour] = NIL;
1232 if (bottom[des] == NIL)
1233 bottom[des] = temp;
1234 temp->next = tableau[des];
1235 tableau[des] = tableau[sour];
1236 tableau[sour] = NIL;
1237 length[des] = length[des] + (length[sour] - (tabrow - 1));
1238 length[sour] = tabrow - 1;
1239 timesthru = 0;
1240 } else
1241 destinerror();
1246 * functions to see if the card can go onto the foundation
1248 static bool
1249 rankhigher(struct cardtype *cp, int let)
1251 if (found[let]->rank == King)
1252 if (cp->rank == Ace)
1253 return(TRUE);
1254 else
1255 return(FALSE);
1256 else if (cp->rank - 1 == found[let]->rank)
1257 return(TRUE);
1258 else
1259 return(FALSE);
1263 * function to determine if two cards are the same suit
1265 static bool
1266 samesuit(struct cardtype *cp, int let)
1268 if (cp->suit == found[let]->suit)
1269 return (TRUE);
1270 else
1271 return (FALSE);
1275 * procedure to move a card to the correct foundation pile
1277 static void
1278 movetofound(struct cardtype **cp, int source)
1280 tempbase = 0;
1281 mtfdone = FALSE;
1282 if (notempty(*cp)) {
1283 do {
1284 if (found[tempbase] != NIL)
1285 if (rankhigher(*cp, tempbase)
1286 && samesuit(*cp, tempbase)) {
1287 if (*cp == stock)
1288 mtforigin = stk;
1289 else if (*cp == talon)
1290 mtforigin = tal;
1291 else
1292 mtforigin = tab;
1293 transit(cp, &found[tempbase]);
1294 printcard(pilemap[tempbase],
1295 foundrow, found[tempbase]);
1296 timesthru = 0;
1297 if (mtforigin == stk) {
1298 usedstock();
1299 printcard(stockcol, stockrow, stock);
1300 } else if (mtforigin == tal) {
1301 usedtalon();
1302 printcard(taloncol, talonrow, talon);
1303 } else {
1304 removecard(pilemap[source], 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 #ifndef SIGTSTP
1380 char *sh;
1381 #endif
1383 updatebettinginfo();
1384 move(21, 0);
1385 refresh();
1386 if (dbfd != -1) {
1387 lseek(dbfd, uid * sizeof(struct betinfo), SEEK_SET);
1388 write(dbfd, (char *)&total, sizeof(total));
1390 kill(getpid(), SIGTSTP);
1391 raw();
1392 noecho();
1396 * procedure to evaluate and make the specific moves
1398 static void
1399 movecard(void)
1401 int source, dest;
1402 char osrcpile, odestpile;
1404 source = 0;
1405 dest = 0;
1406 done = FALSE;
1407 errmsg = FALSE;
1408 do {
1409 if (talon == NIL && hand != NIL)
1410 movetotalon();
1411 if (cardsoff == 52) {
1412 refresh();
1413 srcpile = 'q';
1414 } else if (!startedgame) {
1415 move(msgrow, msgcol);
1416 errmsg = TRUE;
1417 switch (34 - taloncnt - cinhand) {
1418 default:
1419 errmsg = FALSE;
1420 break;
1421 case 1:
1422 printw("One card used from talon ");
1423 break;
1424 case 2:
1425 printw("Two cards used from talon ");
1426 break;
1427 case 3:
1428 printw(">3< cards used from talon ");
1429 break;
1431 getcmd(moverow, movecol, "Move:");
1432 } else
1433 getcmd(moverow, movecol, "Move:");
1434 clearmsg();
1435 if (srcpile >= '1' && srcpile <= '4')
1436 source = (int) (srcpile - '1');
1437 if (destpile >= '1' && destpile <= '4')
1438 dest = (int) (destpile - '1');
1439 if (!startedgame &&
1440 (srcpile == 't' || srcpile == 's' || srcpile == 'h' ||
1441 srcpile == '1' || srcpile == '2' || srcpile == '3' ||
1442 srcpile == '4')) {
1443 startedgame = TRUE;
1444 osrcpile = srcpile;
1445 odestpile = destpile;
1446 if (status != BETTINGBOX)
1447 srcpile = 'y';
1448 else do {
1449 getcmd(moverow, movecol, "Inspect game?");
1450 } while (srcpile != 'y' && srcpile != 'n');
1451 if (srcpile == 'n') {
1452 srcpile = 'q';
1453 } else {
1454 this.inspection += costofinspection;
1455 game.inspection += costofinspection;
1456 total.inspection += costofinspection;
1457 srcpile = osrcpile;
1458 destpile = odestpile;
1461 switch (srcpile) {
1462 case 't':
1463 if (destpile == 'f' || destpile == 'F')
1464 movetofound(&talon, source);
1465 else if (destpile >= '1' && destpile <= '4')
1466 simpletableau(&talon, dest);
1467 else
1468 dumberror();
1469 break;
1470 case 's':
1471 if (destpile == 'f' || destpile == 'F')
1472 movetofound(&stock, source);
1473 else if (destpile >= '1' && destpile <= '4')
1474 simpletableau(&stock, dest);
1475 else dumberror();
1476 break;
1477 case 'h':
1478 if (destpile != 't' && destpile != 'T') {
1479 dumberror();
1480 break;
1482 if (infullgame) {
1483 movetotalon();
1484 break;
1486 if (status == BETTINGBOX) {
1487 do {
1488 getcmd(moverow, movecol,
1489 "Buy game?");
1490 } while (srcpile != 'y' &&
1491 srcpile != 'n');
1492 if (srcpile == 'n') {
1493 showcards();
1494 done = TRUE;
1495 break;
1498 infullgame = TRUE;
1499 this.wins += valuepercardup * cardsoff;
1500 game.wins += valuepercardup * cardsoff;
1501 total.wins += valuepercardup * cardsoff;
1502 this.game += costofgame;
1503 game.game += costofgame;
1504 total.game += costofgame;
1505 movetotalon();
1506 break;
1507 case 'q':
1508 showcards();
1509 done = TRUE;
1510 break;
1511 case 'b':
1512 printtopbettingbox();
1513 printbottombettingbox();
1514 status = BETTINGBOX;
1515 break;
1516 case 'x':
1517 clearabovemovebox();
1518 clearbelowmovebox();
1519 status = NOBOX;
1520 break;
1521 case 'i':
1522 printtopinstructions();
1523 printbottominstructions();
1524 status = INSTRUCTIONBOX;
1525 break;
1526 case 'c':
1527 Cflag = !Cflag;
1528 if (Cflag)
1529 showstat();
1530 else
1531 clearstat();
1532 break;
1533 case '1': case '2': case '3': case '4':
1534 if (destpile == 'f' || destpile == 'F')
1535 movetofound(&tableau[source], source);
1536 else if (destpile >= '1' && destpile <= '4')
1537 tabtotab(source, dest);
1538 else dumberror();
1539 break;
1540 default:
1541 dumberror();
1543 fndbase(&stock, stockcol, stockrow);
1544 fndbase(&talon, taloncol, talonrow);
1545 updatebettinginfo();
1546 } while (!done);
1549 const char *const basicinstructions[] = {
1550 "Here are brief instuctions to the game of Canfield:\n\n",
1551 " If you have never played solitaire before, it is recom-\n",
1552 "mended that you consult a solitaire instruction book. In\n",
1553 "Canfield, tableau cards may be built on each other downward\n",
1554 "in alternate colors. An entire pile must be moved as a unit\n",
1555 "in building. Top cards of the piles are available to be able\n",
1556 "to be played on foundations, but never into empty spaces.\n\n",
1557 " Spaces must be filled from the stock. The top card of\n",
1558 "the stock also is available to be played on foundations or\n",
1559 "built on tableau piles. After the stock is exhausted, ta-\n",
1560 "bleau spaces may be filled from the talon and the player may\n",
1561 "keep them open until he wishes to use them.\n\n",
1562 " Cards are dealt from the hand to the talon by threes\n",
1563 "and this repeats until there are no more cards in the hand\n",
1564 "or the player quits. To have cards dealt onto the talon the\n",
1565 "player types 'ht' for his move. Foundation base cards are\n",
1566 "also automatically moved to the foundation when they become\n",
1567 "available.\n\n",
1568 "push any key when you are finished: ",
1569 0 };
1571 const char *const bettinginstructions[] = {
1572 " The rules for betting are somewhat less strict than\n",
1573 "those used in the official version of the game. The initial\n",
1574 "deal costs $13. You may quit at this point or inspect the\n",
1575 "game. Inspection costs $13 and allows you to make as many\n",
1576 "moves as is possible without moving any cards from your hand\n",
1577 "to the talon. (the initial deal places three cards on the\n",
1578 "talon; if all these cards are used, three more are made\n",
1579 "available) Finally, if the game seems interesting, you must\n",
1580 "pay the final installment of $26. At this point you are\n",
1581 "credited at the rate of $5 for each card on the foundation;\n",
1582 "as the game progresses you are credited with $5 for each\n",
1583 "card that is moved to the foundation. Each run through the\n",
1584 "hand after the first costs $5. The card counting feature\n",
1585 "costs $1 for each unknown card that is identified. If the\n",
1586 "information is toggled on, you are only charged for cards\n",
1587 "that became visible since it was last turned on. Thus the\n",
1588 "maximum cost of information is $34. Playing time is charged\n",
1589 "at a rate of $1 per minute.\n\n",
1590 "push any key when you are finished: ",
1591 0 };
1594 * procedure to printout instructions
1596 static void
1597 instruct(void)
1599 const char *const *cp;
1601 move(originrow, origincol);
1602 printw("This is the game of solitaire called Canfield. Do\n");
1603 printw("you want instructions for the game?");
1604 do {
1605 getcmd(originrow + 3, origincol, "y or n?");
1606 } while (srcpile != 'y' && srcpile != 'n');
1607 if (srcpile == 'n')
1608 return;
1609 clear();
1610 for (cp = basicinstructions; *cp != 0; cp++)
1611 printw(*cp);
1612 refresh();
1613 getch();
1614 clear();
1615 move(originrow, origincol);
1616 printw("Do you want instructions for betting?");
1617 do {
1618 getcmd(originrow + 2, origincol, "y or n?");
1619 } while (srcpile != 'y' && srcpile != 'n');
1620 if (srcpile == 'n')
1621 return;
1622 clear();
1623 for (cp = bettinginstructions; *cp != 0; cp++)
1624 printw(*cp);
1625 refresh();
1626 getch();
1630 * procedure to initialize the game
1632 static void
1633 initall(void)
1635 int i;
1637 if (dbfd < 0)
1638 return;
1639 srandomdev();
1640 time(&acctstart);
1641 initdeck(deck);
1642 uid = getuid();
1644 i = lseek(dbfd, uid * sizeof(struct betinfo), SEEK_SET);
1645 if (i < 0) {
1646 close(dbfd);
1647 dbfd = -1;
1648 return;
1650 i = read(dbfd, (char *)&total, sizeof(total));
1651 if (i < 0) {
1652 close(dbfd);
1653 dbfd = -1;
1654 return;
1659 * procedure to end the game
1661 static bool
1662 finish(void)
1664 int row, col;
1666 if (cardsoff == 52) {
1667 getcmd(moverow, movecol, "Hit return to exit");
1668 clear();
1669 refresh();
1670 move(originrow, origincol);
1671 printw("CONGRATULATIONS!\n");
1672 printw("You won the game. That is a feat to be proud of.\n");
1673 row = originrow + 5;
1674 col = origincol;
1675 } else {
1676 move(msgrow, msgcol);
1677 printw("You got %d card", cardsoff);
1678 if (cardsoff > 1)
1679 printw("s");
1680 printw(" off ");
1681 move(msgrow, msgcol);
1682 row = moverow;
1683 col = movecol;
1685 do {
1686 getcmd(row, col, "Play again (y or n)?");
1687 } while (srcpile != 'y' && srcpile != 'n');
1688 errmsg = TRUE;
1689 clearmsg();
1690 if (srcpile == 'y')
1691 return (FALSE);
1692 else
1693 return (TRUE);
1697 * procedure to clean up and exit
1699 static void
1700 cleanup(__unused int sig)
1703 total.thinktime += 1;
1704 status = NOBOX;
1705 updatebettinginfo();
1706 if (dbfd != -1) {
1707 lseek(dbfd, uid * sizeof(struct betinfo), SEEK_SET);
1708 write(dbfd, (char *)&total, sizeof(total));
1709 close(dbfd);
1711 clear();
1712 move(22,0);
1713 refresh();
1714 endwin();
1715 exit(0);
1716 /* NOTREACHED */
1720 * Field an interrupt.
1722 static void
1723 askquit(__unused int sig)
1725 move(msgrow, msgcol);
1726 printw("Really wish to quit? ");
1727 do {
1728 getcmd(moverow, movecol, "y or n?");
1729 } while (srcpile != 'y' && srcpile != 'n');
1730 clearmsg();
1731 if (srcpile == 'y')
1732 cleanup(0);
1733 signal(SIGINT, askquit);
1737 * Can you tell that this used to be a Pascal program?
1740 main(void)
1742 dbfd = open(_PATH_SCORE, O_RDWR);
1744 /* revoke */
1745 setgid(getgid());
1747 #ifdef MAXLOAD
1748 double vec[3];
1750 loadav(vec);
1751 if (vec[2] >= MAXLOAD) {
1752 puts("The system load is too high. Try again later.");
1753 exit(0);
1755 #endif
1756 signal(SIGINT, askquit);
1757 signal(SIGHUP, cleanup);
1758 signal(SIGTERM, cleanup);
1759 initscr();
1760 raw();
1761 noecho();
1762 initall();
1764 instruct();
1765 makeboard();
1766 for (;;) {
1767 startgame();
1768 movecard();
1769 if (finish())
1770 break;
1771 if (cardsoff == 52)
1772 makeboard();
1773 else
1774 cleanupboard();
1776 cleanup(0);
1777 /* NOTREACHED */
1778 return (EXIT_FAILURE);