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

Defined functions

askquit defined in line 1565; used 2 times
cleanup defined in line 1581; used 4 times
cleanupboard defined in line 364; used 1 times
clearabovemovebox defined in line 270; used 2 times
clearbelowmovebox defined in line 311; used 2 times
clearmsg defined in line 678; used 3 times
clearstat defined in line 905; used 3 times
destinerror defined in line 704; used 3 times
diffcolor defined in line 748; used 1 times
dumberror defined in line 694; used 5 times
finish defined in line 1527; used 1 times
fndbase defined in line 551; used 5 times
getcmd defined in line 1214; used 9 times
initall defined in line 1496; used 1 times
initdeck defined in line 419; used 1 times
initgame defined in line 594; used 1 times
instruct defined in line 1461; used 1 times
main defined in line 1602; never used
makeboard defined in line 326; used 2 times
movebox defined in line 169; used 1 times
movecard defined in line 1287; used 1 times
movetofound defined in line 1165; used 3 times
movetotalon defined in line 783; used 4 times
notempty defined in line 714; used 3 times
printbottombettingbox defined in line 298; used 2 times
printbottominstructions defined in line 285; used 2 times
printcard defined in line 509; used 23 times
printrank defined in line 476; used 2 times
printtopbettingbox defined in line 236; used 2 times
printtopinstructions defined in line 203; used 2 times
rankhigher defined in line 1135; used 1 times
ranklower defined in line 730; used 1 times
removecard defined in line 467; used 7 times
samesuit defined in line 1153; used 1 times
showcards defined in line 959; used 2 times
showstat defined in line 865; used 4 times
shuffle defined in line 444; used 1 times
simpletableau defined in line 1052; used 2 times
startgame defined in line 639; used 1 times
suspend defined in line 1264; used 1 times
tabok defined in line 761; used 2 times
tabprint defined in line 1084; used 1 times
tabtotab defined in line 1109; used 1 times
transit defined in line 535; used 5 times
updatebettinginfo defined in line 1006; used 3 times
usedstock defined in line 947; used 3 times
usedtalon defined in line 924; used 3 times

Defined variables

base defined in line 119; used 4 times
basecard defined in line 117; used 2 times
basicinstructions defined in line 1414; used 1 times
bettinginstructions defined in line 1436; used 1 times
bottom defined in line 116; used 11 times
cards defined in line 115; used 5 times
cardsoff defined in line 119; used 12 times
cinhand defined in line 119; used 12 times
cnewcol defined in line 125; used 5 times
cnewrow defined in line 125; used 5 times
coldcol defined in line 125; used 8 times
coldrow defined in line 125; used 8 times
colormap defined in line 121; used 1 times
copyright defined in line 8; never used
dbfd defined in line 160; used 12 times
deck defined in line 114; used 27 times
destpile defined in line 123; used 20 times
found defined in line 116; used 12 times
hand defined in line 117; used 13 times
length defined in line 118; used 20 times
mtforigin defined in line 124; used 5 times
pilemap defined in line 122; used 8 times
sccsid defined in line 14; never used
srcpile defined in line 123; used 35 times
status defined in line 131; used 9 times
stock defined in line 117; used 16 times
stockcnt defined in line 119; used 4 times
suitmap defined in line 120; used 1 times
tableau defined in line 116; used 27 times
talon defined in line 117; used 28 times
taloncnt defined in line 119; used 7 times
tempbase defined in line 124; used 10 times
this defined in line 157; used 34 times
timesthru defined in line 119; used 6 times
total defined in line 157; used 33 times

Defined struct's

betinfo defined in line 147; used 6 times
cardtype defined in line 103; used 52 times

Defined macros

Ace defined in line 68; used 3 times
BETTINGBOX defined in line 129; used 4 times
DECRHAND defined in line 94; used 2 times
INCRHAND defined in line 87; used 3 times
INSTRUCTIONBOX defined in line 128; used 2 times
Jack defined in line 69; never used
King defined in line 71; used 3 times
NIL defined in line 112; used 32 times
NOBOX defined in line 130; used 2 times
Queen defined in line 70; never used
atabcol defined in line 72; used 4 times
basecol defined in line 36; used 3 times
bboxrow defined in line 39; used 8 times
black defined in line 81; used 2 times
  • in line 121(2)
boxcol defined in line 37; used 47 times
btabcol defined in line 73; used 3 times
cbotrow defined in line 58; used 3 times
cheightcol defined in line 60; used 2 times
cinitcol defined in line 59; used 5 times
clubs defined in line 78; used 1 times
costofgame defined in line 138; used 2 times
costofhand defined in line 136; used 2 times
costofinformation defined in line 140; used 8 times
costofinspection defined in line 137; used 2 times
costofrunthroughhand defined in line 139; used 2 times
ctabcol defined in line 74; used 3 times
ctoprow defined in line 57; used 7 times
cwidthcol defined in line 61; used 4 times
decksize defined in line 33; used 7 times
diamonds defined in line 80; used 1 times
dtabcol defined in line 75; used 3 times
foundcol defined in line 48; used 1 times
foundrow defined in line 49; used 10 times
fttlcol defined in line 52; used 5 times
fttlrow defined in line 53; used 1 times
handstatcol defined in line 63; used 4 times
handstatrow defined in line 62; used 4 times
hearts defined in line 79; used 1 times
maxtimecharge defined in line 142; used 2 times
movecol defined in line 40; used 7 times
moverow defined in line 41; used 8 times
msgcol defined in line 42; used 10 times
msgrow defined in line 43; used 11 times
origincol defined in line 35; used 6 times
originrow defined in line 34; used 6 times
ottlrow defined in line 47; used 1 times
red defined in line 82; used 2 times
  • in line 121(2)
secondsperdollar defined in line 141; used 2 times
sidecol defined in line 46; used 21 times
spades defined in line 77; used 1 times
stk defined in line 84; used 4 times
stockcol defined in line 50; used 9 times
stockrow defined in line 51; used 13 times
stockstatcol defined in line 67; used 3 times
stockstatrow defined in line 66; used 3 times
tab defined in line 86; used 1 times
tabrow defined in line 56; used 14 times
tal defined in line 85; used 3 times
taloncol defined in line 54; used 6 times
talonrow defined in line 55; used 18 times
talonstatcol defined in line 65; used 4 times
talonstatrow defined in line 64; used 4 times
tboxrow defined in line 38; used 37 times
titlecol defined in line 44; used 1 times
titlerow defined in line 45; used 1 times
valuepercardup defined in line 143; used 6 times
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 7371
Valid CSS Valid XHTML 1.0 Strict