Annotation of researchv10no/games/canfield.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.