-+-+-+-+-+-+-+-+ START OF PART 3 -+-+-+-+-+-+-+-+ X * Modified by Chris Yoder to allow for the removal of displayed hands. X * whose -> whose card is being played. X */ X`7B X`09/** mark card in hand as being played. Return non-zero if card not X`09 in hand! **/ X`09int win_num; X`09register int i; X X`09win_num = 0; X`09for (i=0;i<4;i++) `7B X`09 if (hand->card`5Bi`5D == card && hand->status`5Bi`5D == AVAILABLE) `7B X`09 hand->status`5Bi`5D = PLAYED; X`09 if (whose == ME) X`09 remove_card(my_card_win,0,ME); X`09 else X`09 remove_card(your_card_win,win_num,YOU); X`09 return(0); X`09 `7D X`09 if (hand->status`5Bi`5D == AVAILABLE) win_num++; X `7D X`09return(1); X`7D X Xget_exceptions(full_hand, partial_hand, v0, v1) Xstruct card_hand full_hand, partial_hand; Xint *v0, *v1; X`7B X`09/** return index of two elements in full_hand NOT in partial_hand **/ X`09int i, i1=0, a, b; X`09 X`09a = (-1); X`09for (i=0; i<6; i++) `7B X`09 if (full_hand.card`5Bi`5D != partial_hand.card`5Bi1`5D) `7B X`09 if (a >= 0) b = i; X`09 else a = i; X`09 `7D X`09 else i1++; X`09`7D X`09*v0 = a; X`09*v1 = b; X`7D X Xcompress(hand) Xstruct card_hand *hand; X`7B X`09/** compress hand to ensure that there are no 'holes' from X`09 the crib selection process **/ X`09int buffer`5B4`5D, i, j=0; X X`09for (i=0;i<6;i++) X`09 if (hand->status`5Bi`5D != DISCARDED) buffer`5Bj++`5D = hand->card`5Bi` V5D; X`09for (i=0;i<4;i++) `7B X`09 hand->card`5Bi`5D = buffer`5Bi`5D; X`09 hand->status`5Bi`5D = AVAILABLE; X`09`7D X`7D X Xint Xstuck(hand, sum) Xstruct card_hand hand; Xint sum; X`7B X`09/** returns zero if one of the cards in the given hand X`09 can be added to sum without breaking '31' else returns one **/ X`09register int i; X X`09for (i=0;i<4;i++) X`09 if (hand.status`5Bi`5D == AVAILABLE) X`09 if (sum + value_of(hand.card`5Bi`5D) < 32) return(0); X`09return(1); X`7D X Xadd_to_played(who, card, played_cards, index, sum, total_cards) Xint who, card, played_cards`5B`5D, *index, *sum, total_cards; X`7B X`09/** add card... also give points to the appropriate player X`09 if 15, pair, triple, run, 31, or last card is played. **/ X`09int point_value = 0, i; X`09 X`09point_value = value(card, played_cards, *index, *sum, 1); X X`09*sum += value_of(card); X`09played_cards`5B*index`5D = card; X`09*index += 1; X X`09wprintw(i_o_win,"%s ", say(*sum)); X`09if (point_value) `7B X`09 wprintw(i_o_win,"for %s\n",say(point_value)); X`09 add_points(who, point_value); X`09`7D X`09else X`09 wprintw(i_o_win,"\n"); X X`09if (stuck(your_hand, *sum) && X`09 stuck(my_hand, *sum)) `7B X`09 *sum = 0; X`09 *index = 0; X`09 if (total_cards < 8) X`09 wprintw(i_o_win,"\nback to zero...\n\n"); X`09 wrefresh(i_o_win); X`09`7D X`7D X`09 Xint Xpick_discard(played, index, sum) Xint played`5B`5D, index, sum; X`7B X`09/** pick best card in hand to play, given 'played' as the stack X`09 of cards played so far, and sum as the current sum... **/ X X`09/** simply try putting each of the available cards against the X`09 current played cards and use highest value if possible, if X`09 not, use the highest value card first.. **/ X X`09int i, best=0, best_card=0, valid_card; X X`09/** Remove the card on the display. **/ X`09remove_card(my_card_win,0,ME); X X`09for (i=0;i<4;i++)`20 X`09 if (my_hand.status`5Bi`5D == AVAILABLE)`20 X`09 if (value_of(my_hand.card`5Bi`5D) + sum < 32) `7B X`09 if ((valid_card = value(my_hand.card`5Bi`5D, X played,index,sum,0)) > best) `7B X`09 best_card = i; X`09 best = valid_card; X`09 `7D X`09 `7D X X`09if (best > 0) `7B /* actually can make some points! Let's do it! */ X`09 my_hand.status`5Bbest_card`5D = PLAYED; X`09 return(my_hand.card`5Bbest_card`5D); X`09`7D X`09else `7B /* no choices are inspiring...let's put down the highest */ X`09 for (i=3;i>-1;i--) X`09 if (my_hand.status`5Bi`5D == AVAILABLE)`20 X if (value_of(my_hand.card`5Bi`5D) + sum < 32) `7B X`09 my_hand.status`5Bi`5D = PLAYED; X`09 return(my_hand.card`5Bi`5D); X`09 `7D X`09`7D X`09wprintw(i_o_win,"couldn't pick a card!\n"); X`09wrefresh(i_o_win); X`09return(-2); X`7D X Xint Xvalue(card, played_cards, i, sum, not_computing) Xint card, played_cards`5B`5D, i, sum, not_computing; X`7B X`09/** compute the value of adding the card to the stack of played X`09 cards given the sum and whether or not this is a 'real' X`09 calculation (ie for point changes, not to figure best card) **/ X X`09int point_value = 0, scratch; X`09 X`09sum += value_of(card); X`09played_cards`5Bi`5D = card; X X`09/** check for fifteen **/ X X`09if (sum == 15) point_value += 2; X X`09/** check for four of a kind, three of a kind, pairs.. **/ X X`09scratch = 0; X`09if (i>0) X`09 if (rank(played_cards`5Bi-1`5D) == rank(played_cards`5Bi`5D)) X`09 scratch = 2; X`09if (i>1 && scratch) X`09 if (rank(played_cards`5Bi-2`5D) == rank(played_cards`5Bi`5D)) X`09 scratch += 4; X if (i>2 && scratch == 6) X`09 if (rank(played_cards`5Bi-3`5D)==rank(played_cards`5Bi`5D)) X`09 scratch += 6; X X`09point_value += scratch; X X`09/** okay, now check for runs... **/ X X`09scratch = check_for_runs(played_cards, i+1); X`09 X`09if (scratch > 0)`20 X`09 point_value += scratch; X X`09/** and how about to 31? **/ X`09 X`09if (sum == 31)`20 X`09 if (not_computing) point_value += 1; X`09 else `09`09 point_value += 2; X X`09/** last card (only if real counting...otherwise the computer would`20 X`09 cheat! **/ X X`09if (not_computing)`20 X`09 if (stuck(your_hand, sum) && stuck(my_hand, sum))`20 X`09 point_value += 1; X X`09return(point_value); X`7D X Xchar *say(n) Xint n; X`7B X`09/** output number 'n' as a word...return string containing the X`09 word. IE 14 = 'fourteen', 30 = 'thirty' etc etc.. **/ X X`09static char buffer`5B30`5D; X X`09if (n>=10 && n<20) `7B X`09 switch (n) `7B X`09 case 10: strcpy(buffer,"ten");`09 break; X`09 case 11: strcpy(buffer,"eleven"); break; X`09 case 12: strcpy(buffer,"twelve"); break; X`09 case 13: strcpy(buffer,"thirteen"); break; X`09 case 14: strcpy(buffer,"fourteen"); break; X`09 case 15: strcpy(buffer,"fifteen"); break; X`09 case 16: strcpy(buffer,"sixteen"); break; X`09 case 17: strcpy(buffer,"seventeen"); break; X`09 case 18: strcpy(buffer,"eighteen"); break; X`09 case 19: strcpy(buffer,"nineteen"); break; X`09 `7D X`09 return((char *) buffer); X`09`7D X X`09/** okay... normal word, so let's build it up backwards.. **/ X X`09switch ((int) n / 10) `7B X`09 case 0 : buffer`5B0`5D = '\0';`09`09break; X`09 case 2 : strcpy(buffer,"twenty");`09break; X`09 case 3 : strcpy(buffer,"thirty");`09break; X`09 case 4 : strcpy(buffer,"forty");`09break; X`09 case 5 : strcpy(buffer,"fifty");`09break; X`09 case 6 : strcpy(buffer,"sixty");`09break; X`09 case 7 : strcpy(buffer,"seventy");`09break; X`09 case 8 : strcpy(buffer,"eighty");`09break; X`09 case 9 : strcpy(buffer,"ninety");`09break; X`09 default: sprintf(buffer,"%d", n); X`09`09 return( (char *) buffer); X`09`7D X X`09if (n>20 && n != 30) strcat(buffer,"-"); X X`09switch(n % 10) `7B X`09 case 0 : break; X`09 case 1 : strcat(buffer,"one");`09break; X`09 case 2 : strcat(buffer,"two");`09break; X`09 case 3 : strcat(buffer,"three");`09break; X`09 case 4 : strcat(buffer,"four");`09break; X`09 case 5 : strcat(buffer,"five");`09break; X`09 case 6 : strcat(buffer,"six");`09break; X`09 case 7 : strcat(buffer,"seven");`09break; X`09 case 8 : strcat(buffer,"eight");`09break; X`09 case 9 : strcat(buffer,"nine");`09break; X`09`7D X X`09if (strlen(buffer) == 0) strcpy(buffer,"zero"); X X`09return((char *) buffer); X`7D X Xwinner(who) Xint who; X`7B X`09/** show winner and leave **/ X X`09wprintw(i_o_win,"\n\n%s won, reaching %s points first!\n\n", X`09`09who==ME? "I":"You", say(limit)); X`09wrefresh(i_o_win); X`09cleanup(); X`7D X Xleave() X`7B X`09/** get the heck outta here! **/ X X`09wprintw(i_o_win,"\n\nFinal scores were:\n"); X`09wprintw(i_o_win,"\nYou had %d point%s and I had %d point%s\n", X`09`09 points`5BYOU`5D, plural(points`5BYOU`5D),`20 X`09`09 points`5BME`5D, plural(points`5BME`5D)); X`09wrefresh(i_o_win); X`09cleanup(); X`7D X Xint Xcheck_for_runs(stack, elements) Xint stack`5B`5D, elements; X`7B X`09int i, found`5B14`5D, min, max, len, seq_len; X X`09if (elements < 3) return(0); X X`09for (i=0;i<14;i++) found`5Bi`5D = 0; X X`09min=14; X`09max=0; X`09seq_len=0; X X`09for (i=elements-1;i>-1;i--) `7B X`09 len = elements - i; X X`09 min = ( min < rank(stack`5Bi`5D)) ? min : rank(stack`5Bi`5D); X`09 max = ( max > rank(stack`5Bi`5D)) ? max : rank(stack`5Bi`5D); X `20 X`09 if (++found`5Brank(stack`5Bi`5D)`5D > 1) break; X `20 X`09 if ((len > 2) && (max-min+1 == len)) seq_len = len; X`09`7D X`09return(seq_len); X`7D X Xint Xrank(n) Xint n; X`7B X`09return(n % 13 == 0? KING : n % 13); X`7D X X/* X *`09 The following procedures were written by Chris Yoder for display X *`09purposes. X */ X X/*************************************************************************** V***/ X Xsetup_screen() X/* X * This procedure will setup the screen so that we can play. X */ X`7B X int i; X X initscr(); X for (i=0;i<7;i++) your_card_win`5Bi`5D = NULL; X for (i=0;i<7;i++) my_card_win`5Bi`5D = NULL; X i_o_win = newwin(22,40,I_O_TOP,I_O_EDGE); X create_board(); X scrollok(i_o_win,TRUE); X wmove(i_o_win,0,0); X`7D X X/*************************************************************************** V***/ X Xcreate_board() X/* X * This procedure will create the initial board and position of it. X */ X`7B X board_win = newwin(7,39,BOARD_TOP,BOARD_EDGE); X mvwaddstr(board_win, 0, 0,"+-+-----+-----+-----+-----+-----+-----+"); X mvwaddstr(board_win, 1, 0,"`7Ch`7C.....`7C.....`7C.....`7C.....`7C.....`7C V.....`7C"); X mvwaddstr(board_win, 2, 0,"`7Cc`7C.....`7C.....`7C.....`7C.....`7C.....`7C V.....`7C"); X mvwaddstr(board_win, 3, 0,"+-+-----+-----+-----+-----+-----+-----+"); X mvwaddstr(board_win, 4, 0,"`7Ch`7C.....`7C.....`7C.....`7C.....`7C.....`7C V.....`7C"); X mvwaddstr(board_win, 5, 0,"`7Cc`7C.....`7C.....`7C.....`7C.....`7C.....`7C V.....`7C"); X mvwaddstr(board_win, 6, 0,"+-+-----+-----+-----+-----+-----+-----+"); X wrefresh(board_win); X`7D X X/*************************************************************************** V***/ X Xpeg(who, num) X/* X *`09This procedure will do the actual moving of the pegs w/i the program. X */ Xint who, num; X`7B X int`09hold_val; /* Holding variable when switching forward and back pegs. V */ X X if (num == 0) return; /* So we don't try to move when we aren't moving. */ X X if (who == ME) X `7B /* Move my piece. */ X hold_val = my_for_peg;`09`09/* Hang onto this location. */ X my_for_peg += num;`09`09/* Figure out where we're going to. */ X remove_peg(ME,my_bck_peg);`09/* Take out the back peg. */ X place_peg(ME,my_for_peg);`09`09/* Place it in front. */ X my_bck_peg = hold_val;`09`09/* The back peg is now located where the X`09`09`09`09`09 * front peg used to be. */ X `7D X else X `7B /* Move your piece. (See above coments). */ X hold_val = your_for_peg; X your_for_peg += num; X remove_peg(YOU,your_bck_peg); X place_peg(YOU,your_for_peg); X your_bck_peg = hold_val; X `7D X`7D X X/*************************************************************************** V***/ X Xremove_peg(who,where) X/* X *`09This procedure will remove a peg from the board. X */ Xint`09who, where; X/* X *`09who -> owner of the peg X *`09where -> where the peg is X */ X`7B X int`09temp, temp2; X X if (where == -1) X `7B X temp = 5 - who; X wmove(board_win,temp,1); X wdelch(board_win); X winsch(board_win,'.'); X wrefresh(board_win); X return; X `7D X if (where == 0) X `7B X temp = 2 - who; X wmove(board_win,temp,1); X wdelch(board_win); X winsch(board_win,'.'); X wrefresh(board_win); X return; X `7D X switch((where-1)/30) `7B X case 0 : /* first segment (top) */ X temp = 2 - who; X temp2 = 2 + where + ((where-1)/5); X wmove(board_win,temp,temp2); X break; X case 1 : /* second segment (bottom) */ X temp = 5 - who; X temp2 = 61 - where; X temp2 = 2 + temp2 + ((temp2-1)/5); X wmove(board_win,temp,temp2); X break; X case 2 : /* third segment (top) */ X temp = 2 - who; X temp2 = where - 60; X temp2 = 2 + temp2 + ((temp2-1)/5); X wmove(board_win,temp,temp2); X break; X case 3 : /* fourth segment (bottom) */ X temp = 5 - who; X temp2 = 121 - where; X temp2 = 2 + temp2 + ((temp2-1)/5); X wmove(board_win,temp,temp2); X break; X default : /* sound the alarm, we're dead! */ X return; X `7D X wdelch(board_win); X winsch(board_win,'.'); X wrefresh(board_win); X return; X`7D X X/*************************************************************************** V***/ X Xplace_peg(who,where) X/* X *`09This procedure will place a peg on the board. X */ Xint`09who, where; X/* X *`09who -> owner of the peg X *`09where -> where the peg is X */ X`7B X int`09temp, temp2; X X switch((where-1)/30) `7B X case 0 : /* first segment (top) */ X temp = 2 - who; X temp2 = 2 + where + ((where-1)/5); X wmove(board_win,temp,temp2); X break; X case 1 : /* second segment (bottom) */ X temp = 5 - who; X temp2 = 61 - where; X temp2 = 2 + temp2 + ((temp2-1)/5); X wmove(board_win,temp,temp2); X break; X case 2 : /* third segment (top) */ X temp = 2 - who; X temp2 = where - 60; X temp2 = 2 + temp2 + ((temp2-1)/5); X wmove(board_win,temp,temp2); X break; X case 3 : /* fourth segment (bottom) */ X temp = 5 - who; X temp2 = 121 - where; X temp2 = 2 + temp2 + ((temp2-1)/5); X wmove(board_win,temp,temp2); X break; X default : /* We just won! */ X wmove(board_win,5-who,1); X break; X `7D X wdelch(board_win); X winsch(board_win,who == ME? 'c' : 'h'); +-+-+-+-+-+-+-+- END OF PART 3 +-+-+-+-+-+-+-+-