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