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