-+-+-+-+-+-+-+-+ 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 +-+-+-+-+-+-+-+-
