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