|
|
1.1 ! root 1: /* Copyright (c) 1982 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)canfield.c 4.1 10/24/82"; ! 4: ! 5: /* ! 6: * The canfield program ! 7: * ! 8: * Authors: ! 9: * Originally written: Steve Levine ! 10: * Converted to use curses and debugged: Steve Feldman ! 11: * Card counting: Kirk McKusick and Mikey Olson ! 12: */ ! 13: ! 14: #include <curses.h> ! 15: #include <ctype.h> ! 16: #include <signal.h> ! 17: ! 18: #define decksize 52 ! 19: #define originrow 0 ! 20: #define origincol 0 ! 21: #define basecol 1 ! 22: #define boxcol 42 ! 23: #define tboxrow 2 ! 24: #define bboxrow 16 ! 25: #define movecol 43 ! 26: #define moverow 15 ! 27: #define msgcol 43 ! 28: #define msgrow 14 ! 29: #define titlecol 30 ! 30: #define titlerow 0 ! 31: #define sidecol 1 ! 32: #define ottlrow 6 ! 33: #define foundcol 11 ! 34: #define foundrow 3 ! 35: #define stockcol 2 ! 36: #define stockrow 8 ! 37: #define fttlcol 10 ! 38: #define fttlrow 1 ! 39: #define taloncol 2 ! 40: #define talonrow 13 ! 41: #define tabrow 8 ! 42: #define ctoprow 21 ! 43: #define cbotrow 23 ! 44: #define cinitcol 14 ! 45: #define cheightcol 1 ! 46: #define cwidthcol 4 ! 47: #define handstatrow 21 ! 48: #define handstatcol 7 ! 49: #define talonstatrow 22 ! 50: #define talonstatcol 7 ! 51: #define stockstatrow 23 ! 52: #define stockstatcol 7 ! 53: #define Ace 1 ! 54: #define Jack 11 ! 55: #define Queen 12 ! 56: #define King 13 ! 57: #define atabcol 11 ! 58: #define btabcol 18 ! 59: #define ctabcol 25 ! 60: #define dtabcol 32 ! 61: ! 62: #define spades 's' ! 63: #define clubs 'c' ! 64: #define hearts 'h' ! 65: #define diamonds 'd' ! 66: #define black 'b' ! 67: #define red 'r' ! 68: ! 69: #define stk 1 ! 70: #define tal 2 ! 71: #define tab 3 ! 72: #define INCRHAND(row, col) {\ ! 73: row -= cheightcol;\ ! 74: if (row < ctoprow) {\ ! 75: row = cbotrow;\ ! 76: col += cwidthcol;\ ! 77: }\ ! 78: } ! 79: #define DECRHAND(row, col) {\ ! 80: row += cheightcol;\ ! 81: if (row > cbotrow) {\ ! 82: row = ctoprow;\ ! 83: col -= cwidthcol;\ ! 84: }\ ! 85: } ! 86: ! 87: ! 88: struct cardtype { ! 89: char suit; ! 90: char color; ! 91: bool visible; ! 92: int rank; ! 93: struct cardtype *next; ! 94: }; ! 95: ! 96: #define NIL ((struct cardtype *) -1) ! 97: ! 98: struct cardtype *deck[decksize]; ! 99: struct cardtype cards[decksize]; ! 100: struct cardtype *bottom[4], *found[4], *tableau[4]; ! 101: struct cardtype *talon, *hand, *stock, *basecard; ! 102: int length[4]; ! 103: int cardsoff, base, cinhand, taloncnt, stockcnt, timesthru; ! 104: char suitmap[4] = {spades, clubs, hearts, diamonds}; ! 105: char colormap[4] = {black, black, red, red}; ! 106: char pilemap[4] = {atabcol, btabcol, ctabcol, dtabcol}; ! 107: char srcpile, destpile; ! 108: int mtforigin, tempbase; ! 109: int coldcol, cnewcol, coldrow, cnewrow; ! 110: bool errmsg, done; ! 111: bool mtfdone, Cflag = FALSE; ! 112: ! 113: ! 114: ! 115: /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! 116: * The following procedures print the board onto the screen using the ! 117: * addressible cursor. The end of these procedures will also be ! 118: * separated from the rest of the program. ! 119: */ ! 120: /* procedure to set the move command box */ ! 121: movebox() ! 122: { ! 123: move(tboxrow, boxcol); ! 124: printw("*--------------------------*"); ! 125: move(tboxrow + 1, boxcol); ! 126: printw("| MOVES |"); ! 127: move(tboxrow + 2, boxcol); ! 128: printw("|s# = stock to tableau |"); ! 129: move(tboxrow + 3, boxcol); ! 130: printw("|sf = stock to foundation |"); ! 131: move(tboxrow + 4, boxcol); ! 132: printw("|t# = talon to tableau |"); ! 133: move(tboxrow + 5, boxcol); ! 134: printw("|tf = talon to foundation |"); ! 135: move(tboxrow + 6, boxcol); ! 136: printw("|## = tableau to tableau |"); ! 137: move(tboxrow + 7, boxcol); ! 138: printw("|#f = tableau to foundation|"); ! 139: move(tboxrow + 8, boxcol); ! 140: printw("|ht = hand to talon |"); ! 141: move(tboxrow + 9, boxcol); ! 142: printw("|c = toggle card counting |"); ! 143: move(tboxrow + 10, boxcol); ! 144: printw("|q = quit to end the game |"); ! 145: move(tboxrow + 11, boxcol); ! 146: printw("|==========================|"); ! 147: move(moverow, boxcol); ! 148: printw("| |"); ! 149: move(msgrow, boxcol); ! 150: printw("| |"); ! 151: move(bboxrow, boxcol); ! 152: printw("|Replace the # with the |"); ! 153: move(bboxrow + 1, boxcol); ! 154: printw("|number of the tableau you |"); ! 155: move(bboxrow + 2, boxcol); ! 156: printw("|want, 1, 2, 3, or 4. |"); ! 157: move(bboxrow + 3, boxcol); ! 158: printw("*--------------------------*"); ! 159: refresh(); ! 160: } ! 161: ! 162: /* procedure to put the board on the screen using addressable cursor */ ! 163: makeboard() ! 164: { ! 165: clear(); ! 166: refresh(); ! 167: move(titlerow, titlecol); ! 168: printw("=-> CANFIELD <-="); ! 169: move(fttlrow, fttlcol); ! 170: printw("foundation"); ! 171: move(foundrow - 1, fttlcol); ! 172: printw("=---= =---= =---= =---="); ! 173: move(foundrow, fttlcol); ! 174: printw("| | | | | | | |"); ! 175: move(foundrow + 1, fttlcol); ! 176: printw("=---= =---= =---= =---="); ! 177: move(ottlrow, sidecol); ! 178: printw("stock tableau"); ! 179: move(stockrow - 1, sidecol); ! 180: printw("=---="); ! 181: move(stockrow, sidecol); ! 182: printw("| |"); ! 183: move(stockrow + 1, sidecol); ! 184: printw("=---="); ! 185: move(talonrow - 2, sidecol); ! 186: printw("talon"); ! 187: move(talonrow - 1, sidecol); ! 188: printw("=---="); ! 189: move(talonrow, sidecol); ! 190: printw("| |"); ! 191: move(talonrow + 1, sidecol); ! 192: printw("=---="); ! 193: move(tabrow - 1, atabcol); ! 194: printw("-1- -2- -3- -4-"); ! 195: movebox(); ! 196: } ! 197: /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ ! 198: ! 199: /* clean up the board for another game */ ! 200: cleanupboard() ! 201: { ! 202: int cnt, row, col; ! 203: struct cardtype *ptr; ! 204: ! 205: if (Cflag) { ! 206: clearstat(); ! 207: for(ptr = stock, row = stockrow; ! 208: ptr != NIL; ! 209: ptr = ptr->next, row++) { ! 210: move(row, sidecol); ! 211: printw(" "); ! 212: } ! 213: move(row, sidecol); ! 214: printw(" "); ! 215: move(stockrow + 1, sidecol); ! 216: printw("=---="); ! 217: move(talonrow - 2, sidecol); ! 218: printw("talon"); ! 219: move(talonrow - 1, sidecol); ! 220: printw("=---="); ! 221: move(talonrow + 1, sidecol); ! 222: printw("=---="); ! 223: } ! 224: move(stockrow, sidecol); ! 225: printw("| |"); ! 226: move(talonrow, sidecol); ! 227: printw("| |"); ! 228: move(foundrow, fttlcol); ! 229: printw("| | | | | | | |"); ! 230: for (cnt = 0; cnt < 4; cnt++) { ! 231: switch(cnt) { ! 232: case 0: ! 233: col = atabcol; ! 234: break; ! 235: case 1: ! 236: col = btabcol; ! 237: break; ! 238: case 2: ! 239: col = ctabcol; ! 240: break; ! 241: case 3: ! 242: col = dtabcol; ! 243: break; ! 244: } ! 245: for(ptr = tableau[cnt], row = tabrow; ! 246: ptr != NIL; ! 247: ptr = ptr->next, row++) ! 248: removecard(col, row); ! 249: } ! 250: } ! 251: ! 252: /* procedure to create a deck of cards */ ! 253: initdeck(deck) ! 254: struct cardtype *deck[]; ! 255: { ! 256: int i; ! 257: int scnt; ! 258: char s; ! 259: int r; ! 260: ! 261: i = 0; ! 262: for (scnt=0; scnt<4; scnt++) { ! 263: s = suitmap[scnt]; ! 264: for (r=Ace; r<=King; r++) { ! 265: deck[i] = &cards[i]; ! 266: cards[i].rank = r; ! 267: cards[i].suit = s; ! 268: cards[i].color = colormap[scnt]; ! 269: cards[i].next = NIL; ! 270: i++; ! 271: } ! 272: } ! 273: } ! 274: ! 275: /* procedure to shuffle the deck */ ! 276: shuffle(deck) ! 277: struct cardtype *deck[]; ! 278: { ! 279: int i,j; ! 280: struct cardtype *temp; ! 281: ! 282: for (i=0; i<decksize; i++) ! 283: deck[i]->visible = FALSE; ! 284: for (i = decksize-1; i>=0; i--) { ! 285: j = rand() % decksize; ! 286: if (i != j) { ! 287: temp = deck[i]; ! 288: deck[i] = deck[j]; ! 289: deck[j] = temp; ! 290: } ! 291: } ! 292: } ! 293: ! 294: /* procedure to remove the card from the board */ ! 295: removecard(a, b) ! 296: { ! 297: move(b, a); ! 298: printw(" "); ! 299: } ! 300: ! 301: /* procedure to print the cards on the board */ ! 302: printrank(a, b, cp) ! 303: struct cardtype *cp; ! 304: { ! 305: move(b, a); ! 306: switch (cp->rank) { ! 307: case 2: case 3: case 4: case 5: case 6: case 7: ! 308: case 8: case 9: case 10: ! 309: printw("%2d", cp->rank); ! 310: break; ! 311: case Ace: ! 312: printw(" A"); ! 313: break; ! 314: case Jack: ! 315: printw(" J"); ! 316: break; ! 317: case Queen: ! 318: printw(" Q"); ! 319: break; ! 320: case King: ! 321: printw(" K"); ! 322: } ! 323: } ! 324: ! 325: printcard(a, b, cp) ! 326: int a,b; ! 327: struct cardtype *cp; ! 328: { ! 329: if (cp == NIL) ! 330: removecard(a, b); ! 331: else if (cp->visible == FALSE) { ! 332: move(b, a); ! 333: printw(" ? "); ! 334: } else { ! 335: printrank(a, b, cp); ! 336: addch(cp->suit); ! 337: } ! 338: } ! 339: ! 340: /* ! 341: * procedure to move the top card from one location to the top ! 342: * of another location. The pointers always point to the top ! 343: * of the piles. ! 344: */ ! 345: transit(source, dest) ! 346: struct cardtype **source, **dest; ! 347: { ! 348: struct cardtype *temp; ! 349: ! 350: temp = *source; ! 351: *source = (*source)->next; ! 352: temp->next = *dest; ! 353: *dest = temp; ! 354: } ! 355: ! 356: /* ! 357: * Procedure to set the cards on the foundation base when available. ! 358: * Note that it is only called on a foundation pile at the beginning of ! 359: * the game, so the pile will have exactly one card in it. ! 360: */ ! 361: ! 362: fndbase(cp, column, row) ! 363: struct cardtype **cp; ! 364: { ! 365: bool nomore; ! 366: ! 367: if (*cp != NIL) ! 368: do { ! 369: if ((*cp)->rank == basecard->rank) { ! 370: base++; ! 371: printcard(pilemap[base], foundrow, *cp); ! 372: if (*cp == tableau[0]) ! 373: length[0] = length[0] - 1; ! 374: if (*cp == tableau[1]) ! 375: length[1] = length[1] - 1; ! 376: if (*cp == tableau[2]) ! 377: length[2] = length[2] - 1; ! 378: if (*cp == tableau[3]) ! 379: length[3] = length[3] - 1; ! 380: transit(cp, &found[base]); ! 381: if (cp == &talon) ! 382: usedtalon(); ! 383: if (cp == &stock) ! 384: usedstock(); ! 385: if (*cp != NIL) { ! 386: printcard(column, row, *cp); ! 387: nomore = FALSE; ! 388: } else { ! 389: removecard(column, row); ! 390: nomore = TRUE; ! 391: } ! 392: cardsoff++; ! 393: } else ! 394: nomore = TRUE; ! 395: } while (nomore == FALSE); ! 396: } ! 397: ! 398: /* procedure to initialize the things necessary for the game */ ! 399: initgame() ! 400: { ! 401: register i; ! 402: ! 403: for (i=0; i<18; i++) ! 404: deck[i]->visible = TRUE; ! 405: stockcnt = 13; ! 406: stock = deck[12]; ! 407: for (i=12; i>=1; i--) ! 408: deck[i]->next = deck[i - 1]; ! 409: deck[0]->next = NIL; ! 410: found[0] = deck[13]; ! 411: deck[13]->next = NIL; ! 412: for (i=1; i<4; i++) ! 413: found[i] = NIL; ! 414: basecard = found[0]; ! 415: for (i=14; i<18; i++) { ! 416: tableau[i - 14] = deck[i]; ! 417: deck[i]->next = NIL; ! 418: } ! 419: for (i=0; i<4; i++) { ! 420: bottom[i] = tableau[i]; ! 421: length[i] = tabrow; ! 422: } ! 423: hand = deck[18]; ! 424: for (i=18; i<decksize-1; i++) ! 425: deck[i]->next = deck[i + 1]; ! 426: deck[decksize-1]->next = NIL; ! 427: talon = NIL; ! 428: base = 0; ! 429: cinhand = 34; ! 430: taloncnt = 0; ! 431: timesthru = 0; ! 432: cardsoff = 1; ! 433: coldrow = ctoprow; ! 434: coldcol = cinitcol; ! 435: cnewrow = ctoprow; ! 436: cnewcol = cinitcol + cwidthcol; ! 437: } ! 438: ! 439: /* procedure to print the beginning cards and to start each game */ ! 440: startgame() ! 441: { ! 442: register int j; ! 443: ! 444: shuffle(deck); ! 445: initgame(); ! 446: printcard(foundcol, foundrow, found[0]); ! 447: printcard(stockcol, stockrow, stock); ! 448: printcard(atabcol, tabrow, tableau[0]); ! 449: printcard(btabcol, tabrow, tableau[1]); ! 450: printcard(ctabcol, tabrow, tableau[2]); ! 451: printcard(dtabcol, tabrow, tableau[3]); ! 452: printcard(taloncol, talonrow, talon); ! 453: move(foundrow - 2, basecol); ! 454: printw("Base"); ! 455: move(foundrow - 1, basecol); ! 456: printw("Rank"); ! 457: printrank(basecol, foundrow, found[0]); ! 458: for (j=0; j<=3; j++) ! 459: fndbase(&tableau[j], pilemap[j], tabrow); ! 460: fndbase(&stock, stockcol, stockrow); ! 461: showstat(); /* show card counting info to cheaters */ ! 462: } ! 463: ! 464: ! 465: /* procedure to clear the message printed from an error */ ! 466: clearmsg() ! 467: { ! 468: int i; ! 469: ! 470: if (errmsg == TRUE) { ! 471: errmsg = FALSE; ! 472: move(msgrow, msgcol); ! 473: for (i=0; i<25; i++) ! 474: addch(' '); ! 475: refresh(); ! 476: } ! 477: } ! 478: ! 479: /* procedure to print an error message if the move is not listed */ ! 480: dumberror() ! 481: { ! 482: errmsg = TRUE; ! 483: move(msgrow, msgcol); ! 484: printw("Not a proper move "); ! 485: } ! 486: ! 487: /* procedure to print an error message if the move is not possible */ ! 488: destinerror() ! 489: { ! 490: errmsg = TRUE; ! 491: move(msgrow, msgcol); ! 492: printw("Error: Can't move there"); ! 493: } ! 494: ! 495: /* function to see if the source has cards in it */ ! 496: bool ! 497: notempty(cp) ! 498: struct cardtype *cp; ! 499: { ! 500: if (cp == NIL) { ! 501: errmsg = TRUE; ! 502: move(msgrow, msgcol); ! 503: printw("Error: no cards to move"); ! 504: return (FALSE); ! 505: } else ! 506: return (TRUE); ! 507: } ! 508: ! 509: ! 510: /* function to see if the rank of one card is less than another */ ! 511: ! 512: bool ! 513: ranklower(cp1, cp2) ! 514: struct cardtype *cp1, *cp2; ! 515: { ! 516: if (cp2->rank == Ace) ! 517: if (cp1->rank == King) ! 518: return (TRUE); ! 519: else ! 520: return (FALSE); ! 521: else if (cp1->rank + 1 == cp2->rank) ! 522: return (TRUE); ! 523: else ! 524: return (FALSE); ! 525: } ! 526: ! 527: /* function to check the cardcolor for moving to a tableau */ ! 528: bool ! 529: diffcolor(cp1, cp2) ! 530: struct cardtype *cp1, *cp2; ! 531: { ! 532: if (cp1->color == cp2->color) ! 533: return (FALSE); ! 534: else ! 535: return (TRUE); ! 536: } ! 537: ! 538: /* function to see if the card can move to the tableau */ ! 539: bool ! 540: tabok(cp, des) ! 541: struct cardtype *cp; ! 542: { ! 543: if ((cp == stock) && (tableau[des] == NIL)) ! 544: return (TRUE); ! 545: else if (tableau[des] == NIL) ! 546: if (stock == NIL) ! 547: return (TRUE); ! 548: else ! 549: return (FALSE); ! 550: else if (ranklower(cp, tableau[des]) && diffcolor(cp, tableau[des])) ! 551: return (TRUE); ! 552: else ! 553: return (FALSE); ! 554: } ! 555: ! 556: ! 557: /* procedure to turn the cards onto the talon from the deck */ ! 558: movetotalon() ! 559: { ! 560: int i, fin; ! 561: ! 562: if (cinhand >= 3) ! 563: fin = 3; ! 564: else if (cinhand > 0) ! 565: fin = cinhand; ! 566: else if (talon != NIL) { ! 567: timesthru++; ! 568: errmsg = TRUE; ! 569: move(msgrow, msgcol); ! 570: if (timesthru != 4) { ! 571: printw("Talon is now the new hand"); ! 572: while (talon != NIL) { ! 573: transit(&talon, &hand); ! 574: cinhand++; ! 575: } ! 576: if (cinhand >= 3) ! 577: fin = 3; ! 578: else ! 579: fin = cinhand; ! 580: taloncnt = 0; ! 581: coldrow = ctoprow; ! 582: coldcol = cinitcol; ! 583: cnewrow = ctoprow; ! 584: cnewcol = cinitcol + cwidthcol; ! 585: clearstat(); ! 586: showstat(); ! 587: } else { ! 588: fin = 0; ! 589: done = TRUE; ! 590: printw("I believe you have lost"); ! 591: refresh(); ! 592: sleep(5); ! 593: } ! 594: } else { ! 595: errmsg = TRUE; ! 596: move(msgrow, msgcol); ! 597: printw("Talon and hand are empty"); ! 598: fin = 0; ! 599: } ! 600: for (i=0; i<fin; i++) { ! 601: transit(&hand, &talon); ! 602: INCRHAND(cnewrow, cnewcol); ! 603: INCRHAND(coldrow, coldcol); ! 604: removecard(cnewcol, cnewrow); ! 605: if (i == fin - 1) ! 606: talon->visible = TRUE; ! 607: if (Cflag) ! 608: printcard(coldcol, coldrow, talon); ! 609: } ! 610: if (fin != 0) { ! 611: printcard(taloncol, talonrow, talon); ! 612: cinhand -= fin; ! 613: taloncnt += fin; ! 614: if (Cflag) { ! 615: move(handstatrow, handstatcol); ! 616: printw("%3d", cinhand); ! 617: move(talonstatrow, talonstatcol); ! 618: printw("%3d", taloncnt); ! 619: } ! 620: fndbase(&talon, taloncol, talonrow); ! 621: } ! 622: } ! 623: ! 624: ! 625: /* procedure to print card counting info on screen */ ! 626: showstat() ! 627: { ! 628: int row, col; ! 629: register struct cardtype *ptr; ! 630: ! 631: if (Cflag) { ! 632: move(talonstatrow, talonstatcol - 7); ! 633: printw("Talon: %3d", taloncnt); ! 634: move(handstatrow, handstatcol - 7); ! 635: printw("Hand: %3d", cinhand); ! 636: move(stockstatrow, stockstatcol - 7); ! 637: printw("Stock: %3d", stockcnt); ! 638: for ( row = coldrow, col = coldcol, ptr = talon; ! 639: ptr != NIL; ! 640: ptr = ptr->next ) { ! 641: printcard(col, row, ptr); ! 642: DECRHAND(row, col); ! 643: } ! 644: for ( row = cnewrow, col = cnewcol, ptr = hand; ! 645: ptr != NIL; ! 646: ptr = ptr->next ) { ! 647: INCRHAND(row, col); ! 648: printcard(col, row, ptr); ! 649: } ! 650: } ! 651: } ! 652: ! 653: ! 654: /* procedure to clear card counting info from screen */ ! 655: clearstat() ! 656: { ! 657: int row; ! 658: ! 659: move(talonstatrow, talonstatcol - 7); ! 660: printw(" "); ! 661: move(handstatrow, handstatcol - 7); ! 662: printw(" "); ! 663: move(stockstatrow, stockstatcol - 7); ! 664: printw(" "); ! 665: for ( row = ctoprow ; row <= cbotrow ; row++ ) { ! 666: move(row, cinitcol); ! 667: printw("%56s", " "); ! 668: } ! 669: } ! 670: ! 671: ! 672: /* procedure to update card counting base */ ! 673: usedtalon() ! 674: { ! 675: removecard(coldcol, coldrow); ! 676: DECRHAND(coldrow, coldcol); ! 677: if (talon != NIL && (talon->visible == FALSE)) { ! 678: talon->visible = TRUE; ! 679: if (Cflag) ! 680: printcard(coldcol, coldrow, talon); ! 681: } ! 682: taloncnt--; ! 683: if (Cflag) { ! 684: move(talonstatrow, talonstatcol); ! 685: printw("%3d", taloncnt); ! 686: } ! 687: } ! 688: ! 689: ! 690: /* procedure to update stock card counting base */ ! 691: usedstock() ! 692: { ! 693: stockcnt--; ! 694: if (Cflag) { ! 695: move(stockstatrow, stockstatcol); ! 696: printw("%3d", stockcnt); ! 697: } ! 698: } ! 699: ! 700: ! 701: /* let 'em know how they lost! */ ! 702: showcards() ! 703: { ! 704: register struct cardtype *ptr; ! 705: int row; ! 706: ! 707: if (!Cflag) ! 708: return; ! 709: for (ptr = talon; ptr != NIL; ptr = ptr->next) ! 710: ptr->visible = TRUE; ! 711: for (ptr = hand; ptr != NIL; ptr = ptr->next) ! 712: ptr->visible = TRUE; ! 713: showstat(); ! 714: move(stockrow + 1, sidecol); ! 715: printw(" "); ! 716: move(talonrow - 2, sidecol); ! 717: printw(" "); ! 718: move(talonrow - 1, sidecol); ! 719: printw(" "); ! 720: move(talonrow, sidecol); ! 721: printw(" "); ! 722: move(talonrow + 1, sidecol); ! 723: printw(" "); ! 724: for (ptr = stock, row = stockrow; ptr != NIL; ptr = ptr->next, row++) { ! 725: move(row, stockcol - 1); ! 726: printw("| |"); ! 727: printcard(stockcol, row, ptr); ! 728: } ! 729: if (stock == NIL) { ! 730: move(row, stockcol - 1); ! 731: printw("| |"); ! 732: row++; ! 733: } ! 734: move(handstatrow, handstatcol - 7); ! 735: printw(" "); ! 736: move(row, stockcol - 1); ! 737: printw("=---="); ! 738: getcmd(moverow, movecol, "Hit return to exit"); ! 739: } ! 740: ! 741: ! 742: /* procedure to move a card from the stock or talon to the tableau */ ! 743: simpletableau(cp, des) ! 744: struct cardtype **cp; ! 745: { ! 746: int origin; ! 747: ! 748: if (notempty(*cp)) { ! 749: if (tabok(*cp, des)) { ! 750: if (*cp == stock) ! 751: origin = stk; ! 752: else ! 753: origin = tal; ! 754: if (tableau[des] == NIL) ! 755: bottom[des] = *cp; ! 756: transit(cp, &tableau[des]); ! 757: length[des]++; ! 758: printcard(pilemap[des], length[des], tableau[des]); ! 759: timesthru = 0; ! 760: if (origin == stk) { ! 761: usedstock(); ! 762: printcard(stockcol, stockrow, stock); ! 763: } else { ! 764: usedtalon(); ! 765: printcard(taloncol, talonrow, talon); ! 766: } ! 767: } else ! 768: destinerror(); ! 769: } ! 770: } ! 771: ! 772: ! 773: tabprint(sour, des) ! 774: { ! 775: int dlength, slength, i; ! 776: struct cardtype *tempcard; ! 777: ! 778: for (i=tabrow; i<=length[sour]; i++) ! 779: removecard(pilemap[sour], i); ! 780: dlength = length[des] + 1; ! 781: slength = length[sour]; ! 782: if (slength == tabrow) ! 783: printcard(pilemap[des], dlength, tableau[sour]); ! 784: else ! 785: while (slength != tabrow - 1) { ! 786: tempcard = tableau[sour]; ! 787: for (i=1; i<=slength-tabrow; i++) ! 788: tempcard = tempcard->next; ! 789: printcard(pilemap[des], dlength, tempcard); ! 790: slength--; ! 791: dlength++; ! 792: } ! 793: } ! 794: ! 795: /* procedure to move from the tableau to the tableau */ ! 796: tabtotab(sour, des) ! 797: { ! 798: struct cardtype *temp; ! 799: ! 800: if (notempty(tableau[sour])) { ! 801: if (tabok(bottom[sour], des)) { ! 802: tabprint(sour, des); ! 803: temp = bottom[sour]; ! 804: bottom[sour] = NIL; ! 805: temp->next = tableau[des]; ! 806: tableau[des] = tableau[sour]; ! 807: tableau[sour] = NIL; ! 808: length[des] = length[des] + (length[sour] - (tabrow - 1)); ! 809: length[sour] = tabrow - 1; ! 810: timesthru = 0; ! 811: } else ! 812: destinerror(); ! 813: } ! 814: } ! 815: ! 816: ! 817: /* functions to see if the card can go onto the foundation */ ! 818: bool ! 819: rankhigher(cp, let) ! 820: struct cardtype *cp; ! 821: { ! 822: if (found[let]->rank == King) ! 823: if (cp->rank == Ace) ! 824: return(TRUE); ! 825: else ! 826: return(FALSE); ! 827: else if (cp->rank - 1 == found[let]->rank) ! 828: return(TRUE); ! 829: else ! 830: return(FALSE); ! 831: } ! 832: ! 833: samesuit(cp, let) ! 834: struct cardtype *cp; ! 835: { ! 836: if (cp->suit == found[let]->suit) ! 837: return (TRUE); ! 838: else ! 839: return (FALSE); ! 840: } ! 841: ! 842: /* procedure to move a card to the correct foundation pile */ ! 843: ! 844: movetofound(cp, source) ! 845: struct cardtype **cp; ! 846: { ! 847: tempbase = 0; ! 848: mtfdone = FALSE; ! 849: if (notempty(*cp)) { ! 850: do { ! 851: if (found[tempbase] != NIL) ! 852: if (rankhigher(*cp, tempbase) ! 853: && samesuit(*cp, tempbase)) { ! 854: if (*cp == stock) ! 855: mtforigin = stk; ! 856: else if (*cp == talon) ! 857: mtforigin = tal; ! 858: else ! 859: mtforigin = tab; ! 860: transit(cp, &found[tempbase]); ! 861: printcard(pilemap[tempbase], ! 862: foundrow, found[tempbase]); ! 863: timesthru = 0; ! 864: if (mtforigin == stk) { ! 865: usedstock(); ! 866: printcard(stockcol, stockrow, stock); ! 867: } else if (mtforigin == tal) { ! 868: usedtalon(); ! 869: printcard(taloncol, talonrow, talon); ! 870: } else { ! 871: removecard(pilemap[source], length[source]); ! 872: length[source]--; ! 873: } ! 874: cardsoff++; ! 875: mtfdone = TRUE; ! 876: } else ! 877: tempbase++; ! 878: else ! 879: tempbase++; ! 880: } while ((tempbase != 4) && !mtfdone); ! 881: if (!mtfdone) ! 882: destinerror(); ! 883: } ! 884: } ! 885: ! 886: ! 887: /* procedure to get a command */ ! 888: ! 889: getcmd(row, col, cp) ! 890: int row, col; ! 891: char *cp; ! 892: { ! 893: char cmd[2], ch; ! 894: int i; ! 895: ! 896: i = 0; ! 897: move(row, col); ! 898: printw("%-24s", cp); ! 899: col += 1 + strlen(cp); ! 900: move(row, col); ! 901: refresh(); ! 902: do { ! 903: ch = getch() & 0177; ! 904: if (ch >= 'A' && ch <= 'Z') ! 905: ch += ('a' - 'A'); ! 906: if (ch == '\f') { ! 907: wrefresh(curscr); ! 908: refresh(); ! 909: } else if (i >= 2 && ch != _tty.sg_erase && ch != _tty.sg_kill) { ! 910: if (ch != '\n' && ch != '\r' && ch != ' ') ! 911: write(1, "\007", 1); ! 912: } else if (ch == _tty.sg_erase && i > 0) { ! 913: printw("\b \b"); ! 914: refresh(); ! 915: i--; ! 916: } else if (ch == _tty.sg_kill && i > 0) { ! 917: while (i > 0) { ! 918: printw("\b \b"); ! 919: i--; ! 920: } ! 921: refresh(); ! 922: } else if (ch == '\032') { /* Control-Z */ ! 923: suspend(); ! 924: move(row, col + i); ! 925: refresh(); ! 926: } else if (isprint(ch)) { ! 927: cmd[i++] = ch; ! 928: addch(ch); ! 929: refresh(); ! 930: } ! 931: } while (ch != '\n' && ch != '\r' && ch != ' '); ! 932: srcpile = cmd[0]; ! 933: destpile = cmd[1]; ! 934: } ! 935: ! 936: /* Suspend the game (shell escape if no process control on system) */ ! 937: ! 938: suspend() ! 939: { ! 940: #ifndef SIGTSTP ! 941: char *sh; ! 942: #endif ! 943: ! 944: move(21, 0); ! 945: refresh(); ! 946: endwin(); ! 947: fflush(stdout); ! 948: #ifdef SIGTSTP ! 949: kill(getpid(), SIGTSTP); ! 950: #else ! 951: sh = getenv("SHELL"); ! 952: if (sh == NULL) ! 953: sh = "/bin/sh"; ! 954: system(sh); ! 955: #endif ! 956: raw(); ! 957: noecho(); ! 958: } ! 959: ! 960: /* procedure to evaluate and make the specific moves */ ! 961: ! 962: movecard() ! 963: { ! 964: int source, dest; ! 965: ! 966: done = FALSE; ! 967: errmsg = FALSE; ! 968: do { ! 969: if (cardsoff == 52) { ! 970: refresh(); ! 971: srcpile = 'q'; ! 972: } else ! 973: getcmd(moverow, movecol, "Move:"); ! 974: clearmsg(); ! 975: if (srcpile >= '1' && srcpile <= '4') ! 976: source = (int) (srcpile - '1'); ! 977: if (destpile >= '1' && destpile <= '4') ! 978: dest = (int) (destpile - '1'); ! 979: switch (srcpile) { ! 980: case 't': ! 981: if (destpile == 'f' || destpile == 'F') ! 982: movetofound(&talon, source); ! 983: else if (destpile >= '1' && destpile <= '4') ! 984: simpletableau(&talon, dest); ! 985: else ! 986: dumberror(); ! 987: break; ! 988: case 's': ! 989: if (destpile == 'f' || destpile == 'F') ! 990: movetofound(&stock, source); ! 991: else if (destpile >= '1' && destpile <= '4') ! 992: simpletableau(&stock, dest); ! 993: else dumberror(); ! 994: break; ! 995: case 'h': ! 996: if (destpile == 't' || destpile == 'T') ! 997: movetotalon(); ! 998: else dumberror(); ! 999: break; ! 1000: case 'q': ! 1001: showcards(); ! 1002: done = TRUE; ! 1003: break; ! 1004: case 'c': ! 1005: Cflag = !Cflag; ! 1006: if (Cflag) ! 1007: showstat(); ! 1008: else ! 1009: clearstat(); ! 1010: break; ! 1011: case '1': case '2': case '3': case '4': ! 1012: if (destpile == 'f' || destpile == 'F') ! 1013: movetofound(&tableau[source], source); ! 1014: else if (destpile >= '1' && destpile <= '4') ! 1015: tabtotab(source, dest); ! 1016: else dumberror(); ! 1017: break; ! 1018: default: ! 1019: dumberror(); ! 1020: } ! 1021: fndbase(&stock, stockcol, stockrow); ! 1022: fndbase(&talon, taloncol, talonrow); ! 1023: } while (!done); ! 1024: } ! 1025: ! 1026: /* procedure to printout instructions */ ! 1027: instruct() ! 1028: { ! 1029: move(originrow, origincol); ! 1030: printw("This is the game of solitaire called Canfield. Do\n"); ! 1031: printw("you want instructions for the game?"); ! 1032: do { ! 1033: getcmd(originrow + 3, origincol, "y or n?"); ! 1034: } while (srcpile != 'y' && srcpile != 'n'); ! 1035: if (srcpile == 'y') { ! 1036: clear(); ! 1037: refresh(); ! 1038: printw("Here are brief instuctions to the game of Canfield:\n"); ! 1039: printw("\n"); ! 1040: printw(" If you have never played solitaire before, it is recom-\n"); ! 1041: printw("mended that you consult a solitaire instruction book. In\n"); ! 1042: printw("Canfield, tableau cards may be built on each other downward\n"); ! 1043: printw("in alternate colors. An entire pile must be moved as a unit\n"); ! 1044: printw("in building. Top cards of the piles are available to be able\n"); ! 1045: printw("to be played on foundations, but never into empty spaces.\n"); ! 1046: printw("\n"); ! 1047: printw(" Spaces must be filled from the stock. The top card of\n"); ! 1048: printw("the stock also is available to be played on foundations or\n"); ! 1049: printw("built on tableau piles. After the stock is exhausted, ta-\n"); ! 1050: printw("bleau spaces may be filled from the talon and the player may\n"); ! 1051: printw("keep them open until he wishes to use them.\n"); ! 1052: printw("\n"); ! 1053: printw(" Cards are dealt from the hand to the talon by threes\n"); ! 1054: printw("and this repeats until there are no more cards in the hand\n"); ! 1055: printw("or the player quits. To have cards dealt onto the talon the\n"); ! 1056: printw("player types 'ht' for his move. Foundation base cards are\n"); ! 1057: printw("also automatically moved to the foundation when they become\n"); ! 1058: printw("available.\n\n"); ! 1059: printw("push any key when you are finished: "); ! 1060: refresh(); ! 1061: getch(); ! 1062: } ! 1063: } ! 1064: ! 1065: /* procedure to initialize the game */ ! 1066: initall() ! 1067: ! 1068: { ! 1069: srand(getpid()); ! 1070: initdeck(deck); ! 1071: } ! 1072: ! 1073: /* procedure to end the game */ ! 1074: bool ! 1075: finish() ! 1076: { ! 1077: int row, col; ! 1078: ! 1079: if (cardsoff == 52) { ! 1080: clear(); ! 1081: refresh(); ! 1082: move(originrow, origincol); ! 1083: printw("CONGRATULATIONS!\n"); ! 1084: printw("You won the game. That is a feat to be proud of.\n"); ! 1085: move(originrow + 4, origincol); ! 1086: printw("Wish to play again? "); ! 1087: row = originrow + 5; ! 1088: col = origincol; ! 1089: } else { ! 1090: move(msgrow, msgcol); ! 1091: printw("You got %d card", cardsoff); ! 1092: if (cardsoff > 1) ! 1093: printw("s"); ! 1094: printw(" off "); ! 1095: getcmd(moverow, movecol, "Hit return to continue"); ! 1096: move(msgrow, msgcol); ! 1097: printw("Wish to play again? "); ! 1098: row = moverow; ! 1099: col = movecol; ! 1100: } ! 1101: do { ! 1102: getcmd(row, col, "y or n?"); ! 1103: } while (srcpile != 'y' && srcpile != 'n'); ! 1104: errmsg = TRUE; ! 1105: clearmsg(); ! 1106: if (srcpile == 'y') ! 1107: return (FALSE); ! 1108: else ! 1109: return (TRUE); ! 1110: } ! 1111: ! 1112: main(argc, argv) ! 1113: int argc; ! 1114: char *argv[]; ! 1115: { ! 1116: #ifdef MAXLOAD ! 1117: double vec[3]; ! 1118: ! 1119: loadav(vec); ! 1120: if (vec[2] >= MAXLOAD) { ! 1121: puts("The system load is too high. Try again later."); ! 1122: exit(0); ! 1123: } ! 1124: #endif ! 1125: initscr(); ! 1126: raw(); ! 1127: noecho(); ! 1128: initall(); ! 1129: instruct(); ! 1130: makeboard(); ! 1131: for (;;) { ! 1132: startgame(); ! 1133: movecard(); ! 1134: if (finish()) ! 1135: break; ! 1136: if (cardsoff == 52) ! 1137: makeboard(); ! 1138: else ! 1139: cleanupboard(); ! 1140: } ! 1141: clear(); ! 1142: move(22,0); ! 1143: refresh(); ! 1144: endwin(); ! 1145: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.