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