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