|
|
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.