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

Defined functions

askquit defined in line 1563; used 2 times
cleanup defined in line 1579; used 4 times
cleanupboard defined in line 362; used 1 times
clearabovemovebox defined in line 268; used 2 times
clearbelowmovebox defined in line 309; used 2 times
clearmsg defined in line 676; used 3 times
clearstat defined in line 903; used 3 times
destinerror defined in line 702; used 3 times
diffcolor defined in line 746; used 1 times
dumberror defined in line 692; used 5 times
finish defined in line 1525; used 1 times
fndbase defined in line 549; used 5 times
getcmd defined in line 1212; used 9 times
initall defined in line 1494; used 1 times
initdeck defined in line 417; used 1 times
initgame defined in line 592; used 1 times
instruct defined in line 1459; used 1 times
main defined in line 1600; never used
makeboard defined in line 324; used 2 times
movebox defined in line 167; used 1 times
movecard defined in line 1285; used 1 times
movetofound defined in line 1163; used 3 times
movetotalon defined in line 781; used 4 times
notempty defined in line 712; used 3 times
printbottombettingbox defined in line 296; used 2 times
printbottominstructions defined in line 283; used 2 times
printcard defined in line 507; used 23 times
printrank defined in line 474; used 2 times
printtopbettingbox defined in line 234; used 2 times
printtopinstructions defined in line 201; used 2 times
rankhigher defined in line 1133; used 1 times
ranklower defined in line 728; used 1 times
removecard defined in line 465; used 7 times
samesuit defined in line 1151; used 1 times
showcards defined in line 957; used 2 times
showstat defined in line 863; used 4 times
shuffle defined in line 442; used 1 times
simpletableau defined in line 1050; used 2 times
startgame defined in line 637; used 1 times
suspend defined in line 1262; used 1 times
tabok defined in line 759; used 2 times
tabprint defined in line 1082; used 1 times
tabtotab defined in line 1107; used 1 times
transit defined in line 533; used 5 times
updatebettinginfo defined in line 1004; used 3 times
usedstock defined in line 945; used 3 times
usedtalon defined in line 922; used 3 times

Defined variables

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

Defined struct's

betinfo defined in line 145; used 6 times
cardtype defined in line 101; used 52 times

Defined macros

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