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