[comp.sources.games] v07i018: poker - five card draw poker, Part01/02

billr@saab.CNA.TEK.COM (Bill Randle) (07/13/89)

Submitted-by: Metal Head <csx43%seq1.keele.ac.uk@nsfnet-relay.ac.uk>
Posting-number: Volume 7, Issue 18
Archive-name: poker/Part01

	
	[The author said he was losing net access shortly, so he may
	 not be able to respond to bug reports.  After I made a few
	 minor fixes, it ran OK on my Sun 3/60, OS 3.5.  -br]

	[[The game was written, and therefore works, under BSD4.2
	(DYNIX).
	  Due to differences in curses, it compiles, but does not work
	under System V release 2.0.
	  The style of play may differ from what some people expect, but
	it is close to the most general versions I have played. The
	rules are included.
	  The game is completely honest, but is quite tough to beat.
	The strategy can be easily modifyed, by examining the first
	lines of the file p_decide.c.
	  All the useful information I could think of, relating to
	compiling, has been included in the README file.]]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  README MANIFEST makefile p_decide.c p_hand.c p_scr.c
#   p_strat.c poker.c
# Wrapped by billr@saab on Wed Jul 12 10:54:32 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(974 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X  	This vesion of poker was written under early BSD 4.2 (DYNIX),
X    with a UCB universe.
X	It is not guaranteed to work when compiled in the att universe 
X    (System V release 2) due to differences in curses.
X
X	The file poker.h should be edited to define how the instructions
X    are to be displayed. /usr/ucb/more is used, but this can be altered,
X    and so must the path to the file poker_rules.
X	
X	The title screen (with the implementors address) is displayed
X    by the procedure title(), which is in p_scr.c
X
X	Most bugs have been removed, any that exist are in the hand
X    recognition routines, and do not appear often. Anything that looks 
X    suspicious is probably just a design feature that you do not agree 
X    with, or is due to the compiler and universe used.
X
X	I make this statement because I will soon loose my account, and
X    will not be able to help with queries. The code is however, fairly
X    well structured, so it should not be too hard to modify.
END_OF_FILE
if test 974 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(486 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	This shipping list
X README                     1	
X input.c                    2	
X makefile                   1	
X p_deal.c                   2	
X p_decide.c                 1	
X p_hand.c                   1	
X p_scr.c                    1	
X p_strat.c                  1	
X poker.c                    1	
X poker.h                    2	
X poker_rules                2	
END_OF_FILE
if test 486 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(469 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
Xpoker:	poker.o  p_scr.o  p_deal.o  p_hand.o p_strat.o p_decide.o input.o
X	cc -o poker p_scr.o poker.o p_deal.o  p_hand.o p_strat.o p_decide.o input.o -lcurses -ltermcap
X# 
X# remove the -ltermcap from the above line, to compile in System V version 2
X#
X
Xpoker.o:	poker.c poker.h
X
Xp_scr.o:	p_scr.c poker.h
X
Xp_deal.o:	p_deal.c poker.h
X
Xp_strat.o:      p_strat.c poker.h
X
Xp_hand.o:       p_hand.c poker.h
X
Xp_decide.o:     p_decide.c poker.h
X
Xinput.o:        input.c poker.h
END_OF_FILE
if test 469 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
if test -f 'p_decide.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'p_decide.c'\"
else
echo shar: Extracting \"'p_decide.c'\" \(7959 characters\)
sed "s/^X//" >'p_decide.c' <<'END_OF_FILE'
X#include "poker.h" 
X
Xlong rand();
X
Xstatic int percent[18] = {92,92,92,100,70,67,80,90,88,97,
X			  50,85,85,50,85,90,85,70};
X
X/*   Percent  is an array of percentages, used in the decision making */
X/*  routine */
X
X
X
Xint  decision_A(first_deal)
X
X{
X     /*  decide between hi pair or 4 flush   */
X     /*  with a 70:30 bias to a pair         */
X
X   if(!first_deal)
X       return  11;
X
X   else
X   
X      return  ((rand()%100 < 30) ? 10:11);
X
X}/*  decision A */
X
X
X
X
Xint  decision_B()
X
X{
X     /* decide between using 3 card straight flush  or 3 high cards */
X     /* with a bias of 60:40 for 3 high cards  */
X
X
X     return  ((rand()%100 < 40) ? 7:6);
X
X}/*  decision B */
X
X
X
X
Xint  decision_C()
X
X{
X    /* decide whether to use 2 high cards or 3 card flush */
X    /* there is a bias of 70:30 for 2 high cards   */
X
X
X    return  ((rand()%100 < 30) ? 3:4);
X
X}/* decision C */
X
X
X
X
Xint  decision_D()
X
X{
X    /* decide between 3 card run and 1 high card */
X    /* there is a bias of 70:30 for 1 high cards   */
X
X
X    return  ((rand()%100 < 30) ? 2:1);
X
X}/* decision D */
X
X
X
X
Xint  stay (Hv,last_act,deal,winnings)
X     int  Hv,last_act,deal,winnings;
X
X{
X  /*******************************************************/
X  /*   Do I stay ?                                       */
X  /*                               			 */
X  /* Only if Hv (Handvalue) == 0 and 			 */
X  /*if last_act == 1 or 0 (i.e last was a stay, or 	 */
X  /*you go first). 					 */
X  /*                               			 */
X  /* Which deal also determines staying, as on first deal*/
X  /*there is room for improvement			 */
X  /*                               			 */
X  /*******************************************************/
X
X
X   int result;
X
X   result = 0;  /* don't stay */
X
X   switch (deal) {
X   case 1 : /* first deal */
X            if(Hv < 13 && Hv != 11 && Hv != 8)
X	       /* i.e nothing in hand */
X	      {
X	        if(last_act == 0) /* I go first */
X		   result = (rand()%100 < percent[0]);
X
X	        if(last_act == 1) /* opponent stayed */
X		    result = (rand()%100) < percent[1];
X
X	      }
X	    break;
X
X   case 0 : /* second deal */
X            if(Hv < 13 && Hv != 11 && Hv != 8)
X	       /* i.e nothing in hand */
X	      {
X	        if(last_act == 0) /* I go first */
X		   result = (rand()%100 < percent[2]);
X
X	        if(last_act == 1) /* opponent stayed */
X		  if(winnings >=0 )
X		     result = (rand()%100 < percent[3]);
X
X	      }
X	     else /* some thing in hand */
X
X	       if(Hv < 13) /* only consider if < 2 pair */
X	       {
X	        if(last_act == 0) /* I go first */
X		   result = (rand()%100 < percent[4]);
X
X	       };
X	    break;
X    }/* switch */
X
X
X    return result;
X
X} /* stay */
X
X
X
Xint  drop(deal,cards_taken,Hv,last_act,winnings,turn)
X     int  deal,Hv;
X     int  cards_taken,last_act;
X     int  winnings,turn;
X
X{
X  /**********************************************/
X  /*  Do i drop my cards ?			*/
X  /*						*/
X  /*  Only consider if nothing in hand and last */
X  /*action was increase. Number of cards taken  */
X  /*by opponent, if second deal, is important.	*/
X  /* If presently losing money, then be more	*/
X  /*cautious, and drop more often.		*/
X  /*						*/
X  /*   Follow through with a bluff, so never    */
X  /* drop if have previously bet. 		*/
X  /*						*/
X  /**********************************************/
X
X  int  result;
X
X  result = 0; /* do not drop */
X
X  if(last_act < 9)  
X          /*  If the last action was a raise, i.e. >= 9, then I must have*/
X	  /* previously bet, so it is important to carry the bet on      */
X	  /* and not go back on a bluff.				 */
X	  /*  Otherwise, I have added no money to the pot, and can 	 */
X	  /* consider dropping.						 */
X
X  switch (deal) {
X
X  case 1 : /* first deal */
X
X            if(Hv < 13 && Hv != 11 && Hv != 8)
X	       /* i.e nothing in hand */
X              {
X                if(last_act ==0) /* go first */
X		    if(winnings >= 0)
X			result = (rand()%100) < percent[5];
X		    else
X			result = (rand()%100) < percent[6];
X		
X		if(last_act > 3) /* opponent bet */
X		    if(winnings < 0)
X			result = (rand()%100) < percent[7];
X		    else
X			result = (rand()%100) < percent[8];
X	       }
X	    
X	    break;
X	    
X  case 0 : /* second deal */
X
X            if(Hv < 13 && Hv != 11 && Hv != 8)
X	       /* i.e nothing in hand */
X
X              {
X	       if(last_act == 0) /* go first */
X
X	           if(cards_taken == 0) /* opponent took no cards */
X			result = (rand()%100) < percent[9];
X		    else
X		      if(winnings >=0 )
X			  result = (rand()%100) < percent[10];
X		      else
X			  result = (rand()%100) < percent[11];
X
X	      if(last_act > 3)
X		 if(winnings <0)
X		    result = (rand()%100) < percent[12];
X		    else
X	               result = (rand()%100 < percent[13]);
X              }
X
X             else /* have some thing */
X	       if(cards_taken == 0 && Hv <15 )
X		  result = (rand()%100 < percent[14]);
X   }
X		  
X    return result;
X
X}/* drop */
X
X
X
Xint  calling(Hv,turn,first_deal,cards_taken)
X     int Hv,turn,cards_taken,first_deal;
X
X{
X   /* calling is determined by hand value and pot */
X   /* on turn 6 of the betting the only options will be */
X   /* drop or call, so automatically call on 6 */
X
X   int action;
X
X
X   action =0;  /* do not call */
X
X   if (turn == 6)
X      action = 1;
X
X    else
X    {
X        if(Hv < 13 && Hv != 11 && Hv != 8)
X	       /* i.e nothing in hand */
X
X	  action = (rand()%100 < percent[15]); /* nearly always call */
X	else
X	   if(Hv < 13)  /*  less than 2 pair */
X	      if(!first_deal && cards_taken == 0)
X                 action = (rand()%100 < percent[16]);  /* likely to call */
X		else
X	           action = (rand()%100 < percent[17]);
X     }
X
X     return action;
X
X}/* calling */
X
X
X
Xint   increase(Hv,first_deal,cards_taken)
X      int Hv,first_deal,cards_taken;
X
X
X{   /*  increase current bet by one of three amounts  */
X    /*   Small , Medium , Large .                     */
X    /*						      */
X    /*  returned amounts are :-			      */
X    /*						      */
X    /*   1 - 5 , corresponding to bets of             */
X    /*   5,10,15,20,25  respectively		      */
X    /*						      */
X
X    int  amount;
X
X
X    switch (Hv) {
X
X    case 20 : case 19 : case 18 : case 17 : case 16 :  /* all 5 cards */
X	      if( rand()%100 < 75) /* 75% of the time */
X	          amount = 1 + (rand()%3); /* 1,2 or 3 */
X	      else
X		  amount = 4 + (rand()&01);  /*  4 or 5 */
X
X	      break;
X
X    case 15 : case 14 : case 13 :  /*  more than a hi pair  */
X	      if( rand()%100 < 75) /* 75% of the time */
X	          amount = 1 + (rand()%3); /* 1,2 or 3 */
X	      else
X		  amount = 4 + (rand()&01);  /*  4 or 5 */
X
X	      break;
X
X    case 8 :    /*  lo pair */
X	      if (first_deal)
X		{
X                 if( rand()%100 < 75) /* 75% of the time */
X		     amount = 1 + (rand()&01);  /*  1 or 2 */
X	         else
X		     amount = 3;
X		}
X	       else  /* second_deal */
X		{
X		   if(cards_taken ==0 )
X		     {
X	              if( rand()%100 < 75) /* 75% of the time */
X			  amount = 1;
X			else
X			   amount = 2;
X		     }
X		   else  /*  some cards taken */
X		      {
X	              if( rand()%100 < 75) /* 75% of the time */
X			  amount = 1 + (rand()&01);  /* 1 or 2 */
X			else
X			   amount = 3;
X		      }
X		 }
X
X	      break;
X
X    case 11 :    /*  hi pair */
X	      if (first_deal)
X		 {
X	         if( rand()%100 < 75) /* 75% of the time */
X		     amount = 1 + (rand()&01);  /*  1 or 2 */
X	         else
X		     amount = 3;
X		 }
X
X	       else  /* second_deal */
X		  {
X		   if(cards_taken ==0 )
X		     {
X	              if( rand()%100 < 75) /* 75% of the time */
X			  amount = 1 + (rand()&01);
X			else
X			   amount = 3;
X		      }
X		   else  /*  some cards taken */
X		      {
X	              if( rand()%100 < 75) /* 75% of the time */
X			  amount = 1 + (rand()%3);  /* 1,2 or 3 */
X			else
X			   amount = 4 + (rand()&01);  /* 4 or 5 */
X		      }
X		   }
X
X	      break;
X
X    default : /*  nothing in hand */
X	      amount = 1 + (rand()%5); /* 1 to 5 */
X	      break;
X    }/* switch */
X
X
X    return amount;
X
X}/* increase bet */
X
X
END_OF_FILE
if test 7959 -ne `wc -c <'p_decide.c'`; then
    echo shar: \"'p_decide.c'\" unpacked with wrong size!
fi
# end of 'p_decide.c'
fi
if test -f 'p_hand.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'p_hand.c'\"
else
echo shar: Extracting \"'p_hand.c'\" \(6808 characters\)
sed "s/^X//" >'p_hand.c' <<'END_OF_FILE'
X#include "poker.h"
X
X/*  p_hand.c  what is in the hand  */
X
X
X
Xflush  flusher(hand)
X      playing_card *hand;
X
X/* Identify the xistence of a (partial)flush, and record the cards involved */
X{
X   flush  result;
X
X   int count1,count2,x_posn;
X   int suit_matrix[4][HAND_SIZE + 1];
X
X/* suit_matrix holds the no. of cards in each suit */
X
X   result.flush_of = 0;
X
X /* clear suit_matrix */
X
X   for(count1=0;count1<4;count1++)
X       suit_matrix[count1][0] = 0;
X
X/* fill in suit_matrix */
X
X   for(count1=0;count1 < HAND_SIZE;count1++)
X      {
X	x_posn = hand[count1].suit_value;
X
X	suit_matrix[x_posn][(++suit_matrix[x_posn][0])] = count1;
X
X      }
X
X   for(count1=0;count1<4;count1++)
X
X	if((result.flush_of = suit_matrix[count1][0]) >= 3)
X	  {
X	    for(count2=1;count2 <= result.flush_of; count2++)
X	       result.cards[count2 - 1] = suit_matrix[count1][count2];
X
X	    break;
X	   }
X
X    return result;
X
X}/* flusher */
X
X
Xint  high_straight(hand)
X     playing_card  *hand;
X
X/* Identify the existence of a five card straight */
X{
X
X    int have,ace;
X    int total,mean,count;
X
X    total=0;
X    ace=0;
X
X    ace = (hand[0].face_value == 1);
X
X    for(count=0;count<HAND_SIZE;count++)
X	 total += hand[count].face_value;
X
X    mean = total/HAND_SIZE;
X
X    have=1;
X
X    if(!(total == 47 &&  ace)) /* i.e not AKQJT */
X      for (count=0;count<HAND_SIZE;count++)
X	 if (hand[count].face_value > (mean + 2)  ||
X	     hand[count].face_value < (mean - 2))
X
X	     have =0;
X
X    return have;
X
X}/* high straight */
X
X
X
Xprile  pairs(hand)
X      playing_card  *hand;
X
X/* find any pairs, or groupings of pairs */
X{
X   int count,card_count,res,card;
X   int check[13];
X   prile  result;
X
X
X   for(count=0;count<13;count++)
X      check[count] = 0;  /*  clear check  */
X
X   res = 2;
X   result.no_of_cards = 0;
X
X   check[hand[0].face_value - 1] = 2;
X
X   for(count=1;count<HAND_SIZE;count++)
X      {
X	card = hand[count].face_value - 1;
X	if (check[card] >= 2)
X	  {
X	    res *= check[card];
X	    check[card] = res;
X	  }
X	  else
X	    check[card] = 2;
X       }
X
X    result.p_type  = res;
X    if (res > 2)
X       {
X	 card_count = 0;
X	 for(count =0;count<HAND_SIZE;count++)
X	   if(check[hand[count].face_value - 1] > 2)
X	      result.cards[card_count++] = count;
X       }
X
X
X    return result;
X}/* pairs  */
X
X
X
Xrun   runs(in_hand,pair,posn)
X     playing_card  *in_hand;
X     int  pair;
X     int  posn;
X
X/* Identify any partial runs, of length >= 3 */
X/* It uses a sliding window, of varying size, to isolate */
X/* any runs, then does specific checks at the end for open */
X/* runs, such as 34_67 */
X
X{
X   playing_card  hand[HAND_SIZE];
X
X   int  start,window,sum,mean;
X   int  remove,compare,limit;
X   int  straight,count;
X   int  diff,begin;
X
X   run  result;
X
X
X   for(count=0;count<HAND_SIZE;count++)
X     /*  move in_hand to hand */
X     /* so as not to corrupt hand */
X
X	 hand[count] = in_hand[count];
X
X	
X   start = 0;
X   window = 3;
X
X   result.length = 0;
X   result.open_str = 0;
X   begin = 0;
X
X   if (pair)  /* if a pair is present */
X     {
X       if(posn == 0)  /* check if card is first in hand */
X		      /* then find a card to compare suits with */
X	   compare = 2;
X	else
X	   compare = posn - 1;
X       
X       /* preserve any straight flushes */
X
X       if(hand[posn].suit == hand[compare].suit)
X	    remove = posn + 1;
X	else
X	    remove = posn;
X       
X       /* shift chosen card to right of hand */
X
X       for(count=remove+1;count < HAND_SIZE;count++)
X	   swap((hand + count -1),(hand+count));
X     }
X   
X   limit = HAND_SIZE - pair;  /* 4 or 5 */
X   /* limit is the number of cards, in the possibly altered hand */
X
X   do
X   {
X	  sum =0;
X	  for (count = start;count < (start +  window);count++)
X	      sum += hand[count].face_value;
X	  
X	  mean = sum/window;
X
X	  straight = 1;  /* disprove that a straight is present */
X	  diff = window/2;
X
X	  for(count = start;(count < (start + window) && straight );count++)
X	      
X	      straight = !(hand[count].face_value < mean - diff  ||
X		           hand[count].face_value > mean + diff);
X		         /* i.e is there a  run present */
X
X
X	  if (straight)
X	      {
X	        result.length = window++;
X	        begin = start;
X	      }
X	  else
X	       start++;
X   }
X   while(start + window  <= limit);
X
X   
X   if(result.length > 0) /* identify cards in run */
X
X       for (count = 0;count < result.length;count++)
X	   result.card[count] = begin + count;
X
X
X    if(result.length == 3) /* look for open straight */
X      {
X	if (begin > 0)
X	     {
X	     /* check card to left */
X
X	     if(hand[(begin - 1)].face_value == hand[begin].face_value - 2)
X	       {
X		 result.card[ result.length++ ] = begin - 1;
X		 result.open_str = 1;
X	       }
X	      if((begin + 2) < (limit - 1))
X	      /* check card to right if 3 run is in middle of hand */
X
X	        if(hand[limit].face_value == hand[limit - 1].face_value + 2)
X	          {
X		    result.card[ result.length++ ] = limit;
X		    result.open_str = 1;
X	          }
X
X             }
X	  else
X	    /*  begin = 0 */
X	     if (hand[3].face_value == hand[2].face_value + 2)
X	       {
X		 result.card[result.length++ ] = 3;
X		 result.open_str = 1;
X	       }
X	}
X
X
X   if(hand[0].face_value == 1)  /* handle any possible top straight */
X      
X      {
X	
X	if(hand[limit].face_value == 13 && hand[limit-1].face_value == 12)
X	   if (hand[limit-2].face_value == 11)
X	      {
X		result.length = 4;
X		result.card[0] = 0;
X		result.card[1] = limit-2;
X		result.card[2] = limit-1;
X		result.card[3] = limit;
X	      }
X	    else
X	      {
X		result.length = 3;
X		result.card[0] = 0;
X		result.card[1] = limit-1;
X		result.card[2] = limit;
X	      }
X         else /* look for TJQA */
X	   {
X	     if (hand[limit].face_value == 12 && hand[limit-1].face_value == 11)
X		if (hand[limit-2].face_value == 10)
X		   {
X		     result.length = 4;
X		     result.card[0] = 0;
X     		     result.card[1] = limit-2;
X		     result.card[2] = limit-1;
X		     result.card[3] = limit;
X		     result.open_str = 1;
X		   }
X	    }
X      }
X
X   if(pair)
X       /* undo shifting of cards */
X       /* by incrementing the positon of cards to the right of the */
X       /* moved card */
X
X       for(count=0;count<result.length;count++)
X	   result.card[count] += (count >= remove);
X
X
X   return result;
X
X }/* runs */
X
X
X
X
Xhigh  high_cards(hand)
X
X     playing_card *hand;
X
X/* find all the High cards, i.e. >= 10 */
X
X{
X    int   count;
X    high  result;
X
X    result.number = 0;
X
X    for(count=0;count<HAND_SIZE;count++)
X       if(hand[count].face_value >= 10 || hand[count].face_value == 1)
X	  result.cards[result.number++] = count;
X
X    if(result.number == 1) /* choose a 2nd card to keep,but don`t report */
X       result.cards[1] = (hand[0].face_value == 1)?4:3;
X
X    if(result.number == 0)
X       {
X	result.cards[0] = 3;
X	result.cards[1] = 4;  /* keep top highest two cards */
X       }
X
X    return  result;
X
X}/* high cards */
X
END_OF_FILE
if test 6808 -ne `wc -c <'p_hand.c'`; then
    echo shar: \"'p_hand.c'\" unpacked with wrong size!
fi
# end of 'p_hand.c'
fi
if test -f 'p_scr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'p_scr.c'\"
else
echo shar: Extracting \"'p_scr.c'\" \(11110 characters\)
sed "s/^X//" >'p_scr.c' <<'END_OF_FILE'
X#include "poker.h"
X#include <curses.h>
X#include <signal.h>
X#define x_pos(card_num) (((card_num)%5) * 8 + 1)
X#define y_pos(card_num) (((card_num)/5) * 18)
X#define WHERE(a,b) ((a) + (5 * ((b) != 0)))
X#define MES_Y 1
X#define MES_X 1
X
X
X
X/* These functions will handle the display */
X
XWINDOW  *_card[10];
X
X/* a window for each card */
X
X
Xreally()
X
X/* Do you really want to quit ? */
X
X{
X   int old_x, old_y;
X   char  reply;
X
X   getyx(stdscr,old_y,old_x);
X   move(23,0);
X   printw("Do you really want to quit ? ");
X   refresh();
X   do
X      get_input(0,&reply);
X   while(reply != 'y' && reply != 'n');
X   move(23,0);
X   printw("                             ");
X   refresh();
X   if(reply == 'y')
X	die();
X   else
X      {
X        move(old_y,old_x);
X        refresh();
X	redraw_screen();
X      }
X
X}
X
X
Xdie ()
X{  /* what to do if user interupts */
X   /* and really wants to quit     */
X
X   signal(SIGINT,SIG_IGN);
X   echo();
X   nocrmode();
X   mvcur(0,COLS-1,LINES-1,0);
X   endwin();
X   exit();
X}
X
X
Xinitialise_screen()
X
X/* init. screen and signals */
X{
X   initscr();
X
X   /*  initscr() has problems when compiled under att SysV  */
X
X   if (ERR)
X       {
X	 printf("Error in initialising curses\n");
X	 die();
X       }
X
X   nl();
X   noecho();
X   crmode();
X   leaveok(stdscr,TRUE);
X   scrollok(stdscr,FALSE);
X   signal(SIGINT,really);
X   signal(SIGQUIT,really);
X   /*  these signals have problems when compiled under att SysV  */
X
X}/* init */
X
X
Xtitle_screen()
X{
X
X   char key_press;
X
X   clear();
X   move(10,0);
X   printw("          +----------------------------------------------------+\n");
X   printw("          |           Welcome to 5 Card Draw Poker             |\n");
X   printw("          |                                                    |\n");
X   printw("          | This is the Final Year Project of Nic Smith.       |\n");
X   printw("          | Written for BSD 4.2 Unix                           |\n");
X   printw("          | Please mail any comments or bugs to :-             |\n");
X   printw("          |             csx43@uk.ac.kl.seq1                    |\n");
X   printw("          +----------------------------------------------------+\n");
X
X   move(22,0);
X   printw("---More---");
X   refresh();
X   do
X      get_input(0,&key_press);
X   while (key_press != ' ');
X
X}
X
X
X
Xredraw_screen()
X
X{
X   wrefresh(curscr);
X}
X
X
Xinstruct()
X
X/*  display instructions and rules. The position of the file used is */
X/* defined in poker.h  as INSTRUCTIONS			  	     */
X{
X     char  *inst[100];
X     char  reply;
X
X
X     clear();
X     move(1,0);
X     printw("Do you want instructions and rules ? [y/n] : ");
X     move(1,45);
X     refresh();
X     do
X	get_input(0,&reply);
X     while(reply != 'y' && reply != 'n');
X     printw("%c",reply);
X     refresh();
X     if(reply == 'y')
X       {
X         sprintf(inst,INSTRUCTIONS);
X         clear();
X         refresh();
X         system(inst);
X       }
X
X}
X
X
X
Xdraw_screen()
X
X    /* set up the screen for the game. */
X
X{
X   int count;
X
X
X   clear();
X   refresh();
X
X   /* first, draw the ten windows for the cards  */
X
X   for (count =0;count<10;count++)  /* places for the two hands */
X      {
X	_card[count]=subwin(stdscr,5,5,y_pos(count),x_pos(count));
X	scrollok(_card[count],FALSE);
X	leaveok(_card[count],FALSE);
X	box(_card[count],'|','-');
X
X	wmove(_card[count],0,0);
X	waddch(_card[count],'+');
X
X	wmove(_card[count],4,0);
X	waddch(_card[count],'+');
X
X	wmove(_card[count],0,4);
X	waddch(_card[count],'+');
X
X	wmove(_card[count],4,4);
X	waddch(_card[count],'+');
X      };
X
X/* Then number the cards */
X
X   for (count =0;count< HAND_SIZE;count++)
X   {
X       move(5,(x_pos(count) + 2));
X       printw("%d",count + 1);
X
X       move(17,(x_pos(count) + 2));
X       printw("%d",count + 1);
X
X       refresh();
X   }
X
X
X/* Finally set up other screen messages, such as stake etc. */
X
X   move(3,49);
X   printw("Stake : ");
X
X   move(7,13);
X   printw("Your cards.");
X
X   move(12,55);
X   printw("Pot : ");
X
X   move (15,13);
X   printw("My cards.");
X
X   move(20,49);
X   printw("Stake : ");
X
X   refresh();
X
X}
X
X
X
Xshow_hand (hand,at_bottom)
X
X   playing_card *hand;
X   int at_bottom;
X
X  /* display the given hand at the top/bottom of sreen */
X  /* at_bottom, refers to where on the screen, and is boolean */
X
X{
X   int count;
X
X   for (count=0;count<HAND_SIZE;count++) {
X       
X	wmove(_card[WHERE(count,at_bottom)],1,1);
X	waddch(_card[WHERE(count,at_bottom)],hand[count].suit);
X
X	wmove(_card[WHERE(count,at_bottom)],2,2);
X	waddch(_card[WHERE(count,at_bottom)],hand[count].face);
X
X	wmove(_card[WHERE(count,at_bottom)],3,3);
X	waddch(_card[WHERE(count,at_bottom)],hand[count].suit);
X       };
X   refresh();
X
X}/*show_hand*/
X
X
X
Xclear_my_hand ()
X
X/*  wipe out the cards that appeared in the computer's position */
X
X{
X   int count;
X
X   for (count=0;count<HAND_SIZE;count++) {
X       
X	wmove(_card[HAND_SIZE + count],1,1);
X	waddch(_card[HAND_SIZE + count],' ');
X
X	wmove(_card[HAND_SIZE + count],2,2);
X	waddch(_card[HAND_SIZE + count],' ');
X
X	wmove(_card[HAND_SIZE + count],3,3);
X	waddch(_card[HAND_SIZE + count],' ');
X
X       };
X   refresh();
X
X}/* clear_my_hand */
X
X
X
Xvoid money(you,me,pot)
X     int you,me,pot;
X
X/*  Display all the information about the current distribution of wealth */
X
X{
X   move(3,58);
X   printw("%6d",you);
X   move(12,61);
X   printw("%6d",pot);
X   move(20,58);
X   printw("%6d",me);
X   refresh();
X
X}/*money */
X
X
X
Xvoid  show_winner(win)
X      int  win;
X
X/* Declare the winner, after a hand is played */
X
X{
X    int pause;
X
X    for(pause=0;pause<900000;pause++);
X    move(13,0);
X    if(win == -1)
X      printw("It is a draw, the pot stays. ");
X     else
X	printw("%s win.                ",win?"I ":"You ");
X
X    refresh();
X    for(pause=0;pause<900000;pause++);
X
X}/* show_winner  */
X
X
X
Xvoid  show_over_win(win)
X      int  win;
X
X/*  declare the over all winner, when all of a stake is lost, or no more */
X/*  games are required							 */
X
X{
X    int pause;
X
X
X    clear_mid();
X    move(9,0);
X    if(win == -1)
X      printw("It is a draw.                                     ");
X     else
X	{
X	  printw("%sthe over all winner of that game.",
X		  win?"I am ":"You are ");
X	  move(10,0);
X	  if(win)
X	     printw("     Now isn't that a pity!!           ");
X	   else
X	      printw("Congratulations! But that was only ONE game.");
X	 }
X
X    refresh();
X
X    for(pause=0;pause<900000;pause++);
X
X}/* show_over_win */
X
X
X
X
Xvoid  i_do(what)
X      int  what;
X
X/* Computer declares its actions */
X
X{
X   int pause;
X
X   move(13,0);
X   printw("I will ");
X
X   switch (what) {
X      case 1 : printw("stay.           ");
X	       break;
X      case 2 : printw("drop my cards.  ");
X	       break;
X      case 3 : printw("call.           ");
X	       break;
X      case 4 : case 5 : case 6 : case 7 : case 8 :
X	       printw("bet %2d.        ",(5 * (what - 3)));
X	       break;
X      default : printw("raise %2d.      ",(5 * (what - 8)));
X	        break;
X   }
X
X   refresh();
X   if(what == 1)
X      for(pause=0;pause<900000;pause++);
X
X}/* i_do */
X
X
X
X
Xint  ano_yes_no(source)
X     int  source;
X
X/* ask if another game is requred, and get a y/n answer */
X
X{
X   char  reply;
X
X    move(11,0);
X    printw("Do you want another go ?               ");
X    move(11,25);
X    refresh();
X    do
X      get_input(source,&reply);
X    while(reply != 'y' && reply != 'n');
X    mvaddch(11,25,reply);
X    refresh();
X
X    return (reply == 'y');
X
X}/* yes_no */
X 
X
X
X
Xshow_inc(raising,source,amount)
X      int  raising;
X      int  source;
X      int  *amount;
X
X/*  get and display the user's bet increment	*/
X
X{
X   move (9,0);
X   printw("How much do you want to %s (1-5):               ",
X		       raising?"raise":"bet");
X   refresh();
X   get_increment(source,amount);
X   move(9,37);
X   printw("%2d",*amount);
X   refresh();
X
X}
X
X
X
Xint   choose_SDB(source,amount)
X      int  source;
X      int  *amount;
X
X/* ask the user if he wants to stay, drop or bet, and get the reply */
X
X{
X   char  choice;
X   int   response;
X   
X   move(13,0);
X   printw("                                              ");
X   refresh();
X   move(9,0);
X   printw("Do you wish to Stay,Drop or Bet :             ");
X   refresh();
X   get_SDB(source,&choice);
X   move(9,34);
X   printw("%c",choice);
X   refresh();
X   if(choice == 'b')
X      show_inc(0,source,amount);
X   switch (choice) {
X   case 's' : /* Staying */
X	    response = 1;
X	    break;
X   case 'd' : /* dropping */
X	    response = 2;
X	    break;
X   case 'b' : /* betting */
X	    response = (*amount/5) + 3;/* bet this */
X
X   }/*switch*/
X
X   return response;
X
X}/* choose SDB */
X
X
X
X
Xint   choose_RCD(source,amount,turn)
X      int  source;
X      int  *amount;
X      int  turn;
X
X/* ask user if he wants to raise, drop or call */
X
X{
X   char  choice;
X   int   response;
X
X   move(9,0);
X   printw("%sDo you wish to %sDrop or Call :                ",
X	   (turn ==6)?"      ":"",(turn ==6)?"":"Raise,");
X   refresh();
X   do
X     get_RCD(source,&choice);
X   while(turn == 6 && choice == 'r'); /* disallow raise on turn 6 */
X   move(9,36);
X   printw("%c",choice);
X   refresh();
X   if(choice == 'r')
X      show_inc(1,source,amount);
X   switch (choice) {
X   case 'c' : /* Staying */
X	    response = 3;
X	    break;
X   case 'd' : /* dropping */
X	    response = 2;
X	    break;
X   case 'r' : /* betting */
X	    response = (*amount/5) + 8;
X
X   }/*switch*/
X
X   return response;
X
X}/* choose RCD */
X
X
X
X
Xclear_mid()
X
X{
X   move(9,0);
X   printw("                                            ");
X   move(10,0);
X   printw("                                                   ");
X   move(11,0);
X   printw("                                            ");
X   move(12,0);
X   printw("                                            ");
X   move(13,0);
X   printw("                                            ");
X   refresh();
X}
X
X
X
Xvoid  inform_ante(pot)
X      int pot;
X
X{/* inform user that ante is required */
X
X    int  pause;
X
X    clear_mid();
X    move (11,0);
X    printw("We ante%s.                        ",(pot > 10)?" again":"");
X    refresh();
X    for(pause=0;pause < 900000;pause++);
X    clear_mid();
X
X}/* inform ante */
X
X
X
X/***********************************************/
X/* Following functions are for getting users   */
X/* rejected cards.                             */
X/***********************************************/
X
X
Xask_which()
X
X
X{
X
X    move(9,0);
X    printw("Which cards do you want to reject :                ");
X    refresh();
X    move(9,36);
X    refresh();
X
X}/* ask which */
X
X
X
Xdelete_line()
X
X/*  delete the line of rejected cards  */
X
X{
X    move(9,35);
X    printw("           ");
X    refresh();
X    move(9,35);
X    refresh();
X
X}/* delete line */
X
X
X
Xshow_choice(choice,count)
X    char  choice;
X    int   count;
X
X/* Does computer choose to stay, drop, bet, raise or call ? */
X
X{
X
X     int  across;
X
X     across = 35 + (count * 2);
X
X     mvaddch(9,across,choice);
X     refresh();
X
X}/* show choice */
X
X
X
Xi_take(num)
X    int  num;
X
X/* Computer declares how many cards it takes */
X
X{
X    int  pause;
X
X    move(11,0);
X    printw("I will take %d card%s                       ",num,
X						   (num != 1)?"s.":".");
X    refresh();
X    for(pause = 0;pause < 900000;pause++);
X    move(11,0);
X    printw("                                            ");
X    refresh();
X
X}/* i_take */
END_OF_FILE
if test 11110 -ne `wc -c <'p_scr.c'`; then
    echo shar: \"'p_scr.c'\" unpacked with wrong size!
fi
# end of 'p_scr.c'
fi
if test -f 'p_strat.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'p_strat.c'\"
else
echo shar: Extracting \"'p_strat.c'\" \(13748 characters\)
sed "s/^X//" >'p_strat.c' <<'END_OF_FILE'
X#include "poker.h"
X
X/****************************************/
X/*  p_strat.c  strategies               */
X/****************************************/
X/* 					*/
X/*  Hand value :-			*/
X/*  					*/
X/*  20    :     Royal Flush.		*/
X/*  19    :     Straight Flush 		*/
X/*  18	  :     4 of a Kind		*/
X/*  17	  :	Full House		*/
X/*  16    :	Flush			*/
X/*  15    :	Straight		*/
X/*  14	  :	3 of a Kind		*/
X/*  13	  : 	2 pair			*/
X/*  12    :     4 card straight flush	*/
X/* {11    :     high pair		*/
X/* {10	  : 	4 card flush		*/
X/*   9	  :	4 card straight		*/
X/*   8    :	low pair		*/
X/*  {7    :     3 card straight flush	*/
X/*  {6	  :	3 high card		*/
X/*   5    :     inside straight`	*/
X/*  {4	  :	2 high cards		*/
X/*  {3	  :	3 card flush		*/
X/*  					*/
X/*  {2	  :	3 card run		*/
X/*  {1	  :     1 high card		*/
X/*					*/
X/*  a high card is >= 10		*/
X/*					*/
X/****************************************/
X
X/* These are the procedures that categorise the hand */
X
Xflush  flusher();
Xprile  pairs();
Xrun    runs();
Xhigh   high_cards();
X
X
X
Xprile     priles;
Xrun       straight;
Xflush     flushes;
Xhigh      top_cards;
Xdescribe  res;
X
Xint  hi_straight;
X
X
X
Xint  strai_flush (stra,flus,length)
X      int  *stra,*flus,length;
X
X/* If there is a run present, and a flush present, this decides whether */
X/* or not the same cards are involved in both, i.e. a straight flush    */
X{
X    int count;
X    int truth;
X
X
X    truth=1;
X
X    for(count=0;count < length;count++)
X       if(stra[count] != flus[count])
X	   truth = 0;
X
X    return truth;
X
X}/* strai_flush */
X
X
X
X
X
Xvoid  improve(keep,throw,numkept)
X      int  *keep,*throw;
X      int  numkept;
X
X/* given the cards used in a hand, locate those that need to be changed */
X
X{
X   int card_count,keep_count,throw_count;
X   int keeping;
X
X   throw_count = 0;
X   for(card_count = 0;card_count < HAND_SIZE;card_count++)
X      {
X	keeping = 0;
X	for(keep_count = 0;keep_count < numkept;keep_count++)
X	   if(keep[keep_count] == card_count)
X	      keeping =1;
X
X	if(!keeping)
X	   throw[throw_count++] = card_count;
X      }
X
X
X}/* improve */
X
X
X
X
Xint   real_straight(hand)
X
X      playing_card  *hand;
X
X      /*  the straight algorithm is often wrong if there is a pair present  */
X      /*  This one makes certain */
X
X{
X     int  real;
X     int  counter,ptr;
X
X     real = 1;
X     counter =0;
X     ptr=straight.card[0] ; /*  first card of straight */
X
X
X     if(hand[ptr].face_value == 1 &&
X	hand[HAND_SIZE - 1].face_value == 13)  /* ace and king present */
X
X	ptr = straight.card[++counter]; /* look at next card */
X
X     do
X     {
X	if(hand[ptr].face_value >= hand[ptr+1].face_value)
X	   real = 0;
X	
X	ptr++;
X	counter++;
X     }
X     while(counter < straight.length - 1);
X
X     return real;
X
X
X}/* real_straight */
X
X
X	    
X
Xvoid handle_prile(hand,deal)
X
X     playing_card  *hand;
X     int   deal;
X
X/* This decides what to do with a hand, given that a pair is present */
X
X{
X     switch (priles.p_type) {
X
X     /* Four of a kind */
X     case 256 : res.hand_value = 18;
X		if(hand[priles.cards[0]].face_value < 10)
X		   {
X		     res.reject = 1;
X		     improve(priles.cards,res.exchange,4);
X		   }
X		 else
X		   res.reject = 0;
X		break;
X
X      /* Full house */
X      case 32 :	case 64 : res.hand_value = 17;
X			  res.reject = 0;
X			  break;
X
X      /* Three of a kind */
X      case 16 :	res.hand_value = 14;
X		res.reject = 2;
X		improve(priles.cards,res.exchange,3);
X		break;
X
X      /* Two pair */
X      case 8  : res.hand_value = 13;
X		res.reject = 1;
X		improve(priles.cards,res.exchange,4);
X		break;
X
X      /* One pair */
X      case 4  : if(flushes.flush_of == 4 &&
X
X		   deal && /* only continue if first deal */
X
X		   !straight.open_str    &&
X		   straight.length == 4  &&
X		   real_straight(hand) )
X
X		       /* is there also a 4 straight_flush ? */
X		       /* if so it is a better hand to improve */
X		       /* on first deal than any pair */
X		
X		     {
X		      res.hand_value=12;
X		      res.reject = 1;
X		      improve(flushes.cards,res.exchange,4);
X		     }
X		else /* no 4 sra_flush */
X		 {
X                   if(hand[priles.cards[0]].face_value < 10 &&
X                      hand[priles.cards[0]].face_value > 1 )
X
X		     {/* have a low pair but others are better if still */
X		      /* improving hand.*/
X
X              		if(flushes.flush_of == 4 && deal)
X			  {
X			    res.hand_value = 10;
X			    res.reject = 1;
X			    improve(flushes.cards,res.exchange,4);
X			  }
X			else
X			  {
X			    if(straight.length == 4 &&
X			       deal &&
X			       !straight.open_str   &&
X			       real_straight(hand))
X
X			       {
X				 res.hand_value = 9;
X				 res.reject = 1;
X				 improve(straight.card,res.exchange,4);
X			       }
X			     else /* only a low pair */
X			       {
X				 res.hand_value = 8;
X				 res.reject = 3;
X				 improve(priles.cards,res.exchange,2);
X			       }
X			  }
X
X			 
X		     }
X		  else /* hi pair */
X		     {
X		     if(flushes.flush_of == 4)
X		      {
X		        res.hand_value = decision_A(deal);
X		        if(res.hand_value == 11)
X			{
X			  res.reject = 3;
X			  improve(priles.cards,res.exchange,2);
X			}
X		       else /* is 10 */
X			{
X			  res.reject = 1;
X			  improve(flushes.cards,res.exchange,4);
X			}
X		      }
X		     else /* only a high pair */
X		      {
X			res.hand_value = 11;
X		        res.reject = 3;
X		        improve(priles.cards,res.exchange,2);
X		      }
X		  
X		    }
X		}
X     
X     }/*switch*/
X
X
X}/* prile */
X
X
X
Xvoid  handle_no_prile(hand,first_deal)
X     playing_card *hand;
X     int  first_deal;
X
X{
X    if(hi_straight)
X	if(flushes.flush_of == 5)
X         {
X	   if(hand[0].suit == 'H')  /* Royal flush */
X	     {
X	       res.hand_value = 20;
X	       res.reject = 0;
X	     }
X	   else /* just hi_straight */
X	     {
X	       res.hand_value = 19;
X	       res.reject = 0;
X	     }
X	 }
X	else /* just hi straight */
X	 {
X	   res.hand_value = 15;
X	   res.reject = 0;
X	 }
X     else
X	if(flushes.flush_of == 5)
X	  {
X	   res.hand_value = 16;
X	   res.reject = 0;
X	  }
X	 else
X	  
X	  /* all hands that could win with no pairs  	*/
X	  /* have been found at this point, the 	*/
X	  /* following is only needed if improvements	*/
X	  /* can be made, so only do on second deal.	*/
X
X	  if(first_deal)
X	   {
X
X	     if(flushes.flush_of == straight.length &&
X		strai_flush(flushes.cards,straight.card,straight.length))
X
X		switch (straight.length) 
X		{
X		  case 4 : res.hand_value = 12;
X			   res.reject = 1;
X			   improve(flushes.cards,res.exchange,4);
X			   break;
X		  case 3 : if(top_cards.number == 3) /* 3 hi cards */
X			     {
X			       res.hand_value = decision_B();
X			       res.reject = 2;
X			       if(res.hand_value == 7) /* 3 str flush */
X				   improve(flushes.cards,res.exchange,3);
X				else
X				   improve(top_cards.cards,res.exchange,3);
X			     }
X			     else /* just 3 str flush */
X			       {
X				 res.hand_value = 7;
X			         res.reject = 2;
X				 improve(flushes.cards,res.exchange,3);
X			       }/* end case 3 */
X
X		}/* end switch */
X
X                else   /* no straight flushes present */
X		 if(flushes.flush_of==4)
X		   {
X		      res.hand_value = 10;
X		      res.reject = 1;
X		      improve(flushes.cards,res.exchange,4);
X		   } 
X		   else
X		    if(straight.length == 4 && !straight.open_str)
X		     {
X		        res.hand_value = 9;
X		        res.reject = 1;
X		        improve(straight.card,res.exchange,4);
X		     }
X		     else
X		      if(top_cards.number == 3)
X		       {
X			res.hand_value = 6;
X			res.reject = 2;
X			improve(top_cards.cards,res.exchange,3);
X		       }
X		       else
X			if(straight.open_str)
X			 {
X			  res.hand_value = 5;
X			  res.reject = 1;
X			  improve(straight.card,res.exchange,4);
X			 }
X			 else
X			  if(top_cards.number == 2)
X			   {
X			    if(flushes.flush_of == 3)
X			      {
X				res.hand_value = decision_C();
X				res.reject = ((res.hand_value == 4)?3:2);
X				improve((res.hand_value == 4)?top_cards.cards:
X							      flushes.cards,
X					 res.exchange,
X					 (HAND_SIZE - res.reject));
X			      }
X			      else /* just 2 hi cards */
X			       {
X				res.hand_value = 4;
X				res.reject = 3;
X				improve(top_cards.cards,res.exchange,2);
X			       }
X			    }/* end 2 hi cards */
X			    else
X			    if(flushes.flush_of == 3)
X			     {
X			      res.hand_value = 3;
X			      res.reject = 2;
X			      improve(flushes.cards,res.exchange,3);
X			     }
X			     else
X			      if(straight.length == 3)
X			      {
X			       if(top_cards.number == 1)
X				{
X				 res.hand_value=decision_D();
X				 res.reject=((res.hand_value == 2)?2:3);
X				 improve((res.hand_value == 2)?straight.card:
X							       top_cards.cards,
X					 res.exchange,
X					 (HAND_SIZE - res.reject));
X				}
X				else
X				 {
X				  res.hand_value=2;
X				  res.reject=2;
X				  improve(straight.card,res.exchange,3);
X				 }
X			       }
X			       else
X				if(top_cards.number == 1)
X				  { /* only 1 high card */
X				    res.hand_value = 1;
X				    res.reject = 3;
X				    improve(top_cards.cards,res.exchange,2);
X                                   }
X				else
X				 { /* nothing */
X				   res.hand_value = 0;
X				   res.reject = 3;
X				   improve(top_cards.cards,res.exchange,2);
X				 }
X				 
X	    }/*  first_deal check */
X
X
X}/* no prile */
X
X
X
X
Xdescribe  evaluate(hand,first_deal)
X          playing_card  *hand;
X          int  first_deal;
X
X/* The hand evaluation routine */
X
X{
X
X  flushes = flusher(hand);
X
X  hi_straight = high_straight(hand);
X
X  priles = pairs(hand);
X
X  if(first_deal && !hi_straight) 
X		/* not needed second deal, as can not 	     */
X		/* improve any more or if hi straight found  */
X    if(priles.p_type <= 4)
X
X       straight = runs(hand,(priles.p_type == 4),priles.cards[0]);
X
X  top_cards = high_cards(hand);
X
X  res.hand_value = 0;
X  res.reject = 0;
X
X
X
X  if (priles.p_type > 2) 
X
X       handle_prile(hand,first_deal);
X
X    else 
X
X       handle_no_prile(hand,first_deal);
X
X  if(!first_deal)  /* on 2nd deal all other Hv's are irrelevant */
X      if(res.hand_value <13 && res.hand_value != 11 && res.hand_value !=8)
X	  res.hand_value = 0;
X
X
X  return res;
X
X}/* absolute */
X
X
X
X
Xint  det_winner(my_val,opp_val,my_hand,your_hand)
X      int           my_val,opp_val;
X      playing_card  *my_hand, *your_hand;
X
X/* determine the winner, particularly when the hand values are the same */
X
X{
X     int  winner;
X     int  my_hi,your_hi,my_lo,your_lo,count;
X
X     winner = -1;
X     
X     if(my_val != opp_val)
X	  winner = (my_val > opp_val);
X	
X	else
X	  switch (my_val) { /*  are equal  */
X
X	  case 19 : case 15 : /* straights */
X	       if(my_hand[HAND_SIZE - 1].face_value ==
X	          your_hand[HAND_SIZE - 1].face_value) /* hi cards equal */
X			{
X			  if(my_hand[HAND_SIZE - 1].face_value == 13)
X			     if(my_hand[0].face_value !=
X				your_hand[0].face_value)
X
X				/* are the runs 9TKQK or ATJQK */
X
X                              {
X				if(my_hand[0].face_value == 1)
X				   winner = 1; /* i have AKQJT */
X
X				if(your_hand[0].face_value == 1)
X				   winner = 0; /* you have AKQJT */
X			      }
X			 }
X		  else
X				
X		    winner = my_hand[HAND_SIZE - 1].face_value >
X			     your_hand[HAND_SIZE - 1].face_value;
X		break;
X	  case 18 : case 14 : case 17 :
X			 /*  compare third cards of hands */
X			 /* full houses determined by the 3ok present */
X
X		    if(my_hand[2].face_value == 1)
X			 winner = 1; /* me */
X		      else
X			  if(your_hand[2].face_value == 1)
X			      winner = 0; /* you */
X			else
X			   winner = (my_hand[2].face_value >
X				     your_hand[2].face_value);
X		     break;
X
X          case 13 : /* 2 pair */
X		    /* re-evaluate the pairs present */
X		    
X		    priles = pairs(my_hand);
X		    my_hi = my_hand[priles.cards[2]].face_value;
X		    my_lo = my_hand[priles.cards[0]].face_value;
X		    if(my_lo == 1) /* aces */
X			{
X			my_lo = my_hi;
X			my_hi = 14;/* ace == 14 */
X			}
X
X		    priles = pairs(your_hand);
X		    your_hi = your_hand[priles.cards[2]].face_value;
X		    your_lo = your_hand[priles.cards[0]].face_value;
X		    if(your_lo == 1) /* aces */
X			{
X			your_lo = your_hi;
X			your_hi = 14;
X			}
X
X                    if (my_hi != your_hi)
X			winner = (my_hi > your_hi);
X		      else
X			 if(my_lo != your_lo)
X			    winner = (my_lo > your_lo);
X
X		         else  /* 2 pairs the same */
X			       /*  compare hi cards */
X    
X			   for(count=HAND_SIZE -1;(count >= 0 && winner == -1);
X			       count ++)
X
X			     if(my_hand[count].face_value != 
X				your_hand[count].face_value)
X			        winner = (my_hand[count].face_value > 
X					  your_hand[count].face_value);
X
X		    break;
X
X            case 11 : case 8 : /* pairs */
X
X		    /* First get the value of the pair */
X
X		    priles = pairs(my_hand);
X		    my_hi = my_hand[priles.cards[0]].face_value;
X
X		    priles = pairs(your_hand);
X		    your_hi = your_hand[priles.cards[0]].face_value;
X
X		    my_hi += (13 * (my_hi == 1));
X		    your_hi += (13 * (your_hi == 1));
X		      /*  aces become 14 */
X
X		    if(my_hi != your_hi)
X		       winner = (my_hi > your_hi);
X
X		     else  /* pairs the same */
X			   /*  compare hi cards */
X
X			   for(count=HAND_SIZE -1;(count >= 0 && winner == -1);
X			       count ++)
X
X			     if(my_hand[count].face_value != 
X				your_hand[count].face_value)
X
X			        winner = (my_hand[count].face_value >
X					  your_hand[count].face_value);
X
X                    break;
X
X           default :
X		    if(my_hand[0].face_value != your_hand[0].face_value)
X		       /*  check for aces */
X		      if(my_hand[0].face_value == 1)
X			 winner = 1; /* i have ace */
X			else
X			   if(your_hand[0].face_value == 1)
X			      winner = 0; /* you have ace */
X
X		    if(winner == -1)
X
X		    for(count=HAND_SIZE -1 ; count >= 0;count--)
X		       if (my_hand[count].face_value != 
X			    your_hand[count].face_value)
X			     
X			     {
X			      winner = (my_hand[count].face_value >
X			                your_hand[count].face_value) ;
X			      break; /* from for loop */
X			     }
X					
X
X	  }/* switch */
X
X
X    return winner;
X
X}/* det_winner  */
END_OF_FILE
if test 13748 -ne `wc -c <'p_strat.c'`; then
    echo shar: \"'p_strat.c'\" unpacked with wrong size!
fi
# end of 'p_strat.c'
fi
if test -f 'poker.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'poker.c'\"
else
echo shar: Extracting \"'poker.c'\" \(8381 characters\)
sed "s/^X//" >'poker.c' <<'END_OF_FILE'
X	/************************************************/
X	/*						*/
X	/*      	Five card Draw Poker		*/
X	/*						*/
X	/*  Written by Nic Smith (csx43@uk.ac.kl.seq1)	*/
X	/*  As a final year project to illustrate	*/
X	/*  intelligent game play.			*/
X	/*						*/
X	/************************************************/
X	/*						*/
X	/*  The files that need to be compiled together */
X	/* and there main uses are :			*/
X	/* 						*/
X	/*  poker.h  : include file for structure 	*/
X	/*		definitons and configuration   	*/
X	/*		locating rules.			*/
X	/*  poker.c  : top level of code that pulls 	*/
X	/*		together all the main procedures*/
X	/*  p_deal.c : handles the shuffling, sorting   */
X	/*		and dealing of the cards.	*/
X	/*  p_hand.c : hand recognition routines.	*/
X	/*  p_strat.c: the strategy used to decide which*/
X	/*		hand type to play with, and how */
X	/*		to improve the given hand.	*/
X	/*  input.c  : accepts most input from the 	*/
X	/*		opponent.			*/
X	/* p_decide.c: makes decisions based on 	*/
X	/*  		imperfect information, such as	*/
X	/*		call/raise etc. decisions made	*/
X	/*		using probabilities in 'percent'*/
X	/*		array.				*/
X	/*  p_scr.c  : screen handling functions. This  */
X	/*  		uses the 'curses' library	*/
X	/* poker_rules : Text file that contains the	*/
X	/*		rules and instructions for the	*/
X	/*		game.				*/
X	/*						*/
X	/************************************************/
X
X#include "poker.h"
X#include <signal.h>
X#define source 0
X/* This is the file descriptor for input i.e. terminal 	*/
X/* Most procedures can be reused to convert the program	*/
X/* to machine-machine play. This can be used to improve	*/
X/* and test the strategy.				*/
X
X#define init_stake 250
X/* obviously the initial stake given to each player */
X
X#define VOID 0
X#define STAY 1
X#define DROP 2
X#define CALL 3
X
X#define flag int
X
X/********************************/
X/*				*/
X/* possible responses :		*/
X/*				*/
X/* 1 = stay			*/
X/* 2 = drop			*/
X/* 3 = call			*/
X/* 4-8 = bet 1-5  resp. 	*/
X/* 9-13 = raise 1-5  resp.	*/
X/*				*/
X/********************************/
X
Xplaying_card   my_hand[HAND_SIZE], your_hand[HAND_SIZE];
X
Xint   your_stake,my_stake,pot;
Xint   action,last_action;
Xint   amount,last_bet,total_bet;
Xint   turn;
Xflag  i_go_first,whos_go,winner,first_deal;
Xflag  ante_again;
X
X
Xdescribe  mine,yours;
X
X
Xlong rand();
Xdescribe  evaluate();
X
X
X
X
Xint   SDB(who) 
X      flag  who;
X
X{/* stay, drop or bet */
X /* used for returning both computer and opponent decisions */
X /* it will either call upon the user input routines are the*/
X /* decision making routines.				    */
X
X  int  response;
X
X  if(!who)  /* i.e opponent go */
X     response = choose_SDB(source,&amount);
X   else
X     {
X
X       if (stay(mine.hand_value,last_action,
X		first_deal,(my_stake - init_stake)))
X          response = STAY;
X         else
X	     {
X	     if(drop(first_deal,yours.reject,mine.hand_value,
X		     last_action,(my_stake - init_stake),turn))
X
X	        response = DROP; 
X     
X	      else /* bet */
X	          response = 3 + increase(mine.hand_value,first_deal,
X					  yours.reject);
X	      }
X       i_do(response);
X
X      }
X  
X   return response;
X
X
X}/* SDB */
X
X
X
X
Xint   RCD(who)
X      flag  who;
X
X{ /* raise call or drop */
X /* used for returning both computer and opponent decisions */
X /* it will either call upon the user input routines are the*/
X /* decision making routines.				    */
X
X  int  response;
X
X  if(!who)
X     response = choose_RCD(source,&amount,turn);
X   else
X
X    {
X     if(drop(first_deal,yours.reject,mine.hand_value,
X	     last_action,(my_stake - init_stake),turn))
X        response = DROP;
X   
X      else
X	  {
X	   if(calling(mine.hand_value,turn,first_deal,yours.reject))
X	      response = CALL;
X   	
X	    else /* raise */
X	       response = 8 + increase(mine.hand_value,first_deal,
X				       yours.reject);
X	  }
X     i_do(response);
X   
X    }
X   
X   return response;
X     
X}/*RCD*/
X
X
X
Xvoid  ante()
X
X{/* ante is 5 */
X /* used for intial ante and re-ante, so does not reset pot */
X
X     your_stake -= 5;
X     my_stake -= 5;
X     pot += 10;
X
X     inform_ante(pot);
X
X}/* ante */
X
X
X
X
Xmain()
X
X{
X  int  another_go;
X
X
X  srand(getpid());
X
X  i_go_first = rand()%01; /* a 1 means the computer goes first, a 0 means */
X			    /* opponent goes first */
X
X  another_go = 1; /*set to ensure that at least one game is played */
X
X  initialise_screen();
X  title_screen(); /* can be altered to show owners mail address */
X  instruct();     /* ask if instructions are required, and display if */
X		  /* necessary. The full pathname for poker_rules     */
X		  /* must be set in here (p_scr.c).		      */
X  initialise_cards();
X
X  
X  do
X  {
X    draw_screen();
X  
X    your_stake=my_stake=300;
X    pot =0;
X      
X    do
X    {
X      new_deal();
X  
X      deal_two_hands (your_hand,my_hand);
X  
X      clear_my_hand();  /* remove computer's old  hand from screen */
X
X      show_hand(your_hand,0); /* display hand at top of screen */
X  
X      action = VOID;
X      ante_again =0;
X      ante();
X    
X      money(your_stake,my_stake,pot);  /*  update money situation on screen */
X  
X      for(first_deal =1;first_deal >= 0 && !ante_again && action!=DROP;
X		        first_deal--)
X
X      {
X        last_bet=0;
X        total_bet=0;
X        last_action=VOID;
X        whos_go = i_go_first;
X  
X        mine = evaluate(my_hand,first_deal);
X
X
X        turn=1;  /* there is a limited number of betting turns allowed */
X
X        action = SDB(whos_go);
X
X        if(action == STAY)
X          {
X            turn ++;
X            whos_go = !whos_go;
X            last_action = STAY;
X            action = SDB(whos_go);
X            if(action == STAY)
X	       if(first_deal)
X	             ante_again = 1; 
X	         else
X	             action = CALL;
X          }
X         if(!ante_again)
X            {
X	      while(action!=DROP && action != CALL)
X	         {
X	           if (whos_go)  /* my_go */
X		       amount = (action > 8)?((action - 8) * 5):
X				             ((action - 3) * 5);
X	           total_bet = amount + last_bet;
X	           last_bet = amount;
X	           pot += total_bet;
X	           if(whos_go)
X		        my_stake -= total_bet;
X		      else
X		          your_stake -= total_bet;
X	           money(your_stake,my_stake,pot);
X	           turn++;
X	           whos_go = !whos_go;
X	           last_action = action;
X	           action = RCD(whos_go);
X	         } /* while */
X  
X	      if(action == DROP)
X	        {
X	          if(whos_go)
X		      your_stake += pot;
X	           else
X		      my_stake += pot;
X	          pot = 0;
X	          money(your_stake,my_stake,pot);
X	          winner = !whos_go;
X	        }
X	      if(action == CALL)
X	         {
X	            if(whos_go)
X		        my_stake -= last_bet;
X		      else
X		          your_stake -= last_bet;
X	            pot += last_bet;
X	            money(your_stake,my_stake,pot);
X	            if(first_deal)
X		       {
X                           re_deal(my_hand,mine);
X			   i_take(mine.reject);
X			   get_user_changes(source,&yours.reject,
X					    yours.exchange);
X
X			   re_deal(your_hand,yours);
X                           show_hand(your_hand,0);  
X		       }
X		      else
X	               {
X			  yours = evaluate(your_hand,first_deal);
X                          winner = det_winner(mine.hand_value,yours.hand_value,
X	                                      my_hand,your_hand);
X		       }
X
X	          }/* call */
X             }/* not ante again */
X      }/*for*/
X      if(!ante_again)
X         {
X  
X           if(action != DROP)
X             show_hand(my_hand,1); 
X
X             show_winner(winner);
X             if(winner == 1)
X	          my_stake += pot;
X	     if(winner == 0)
X	          your_stake += pot;
X	     if(winner != -1)
X                  pot = 0;
X
X             money(your_stake,my_stake,pot);
X
X             if((my_stake <= 0 || your_stake <= 0) && !ante_again)
X	      {
X		if(my_stake == your_stake)
X                	winner = -1;
X		else
X                	winner = my_stake > your_stake;
X                show_over_win(winner);
X	      }
X
X	     another_go = ano_yes_no(source);
X
X	     i_go_first = !i_go_first;
X    
X          }
X    }/* 2nd do */
X    while((my_stake > 0 && your_stake > 0) && (ante_again || another_go));
X  
X  
X  }/* first do */
X  while(another_go);
X
X  if(my_stake > 0 && your_stake > 0)
X    {
X      if(my_stake == your_stake)
X      	winner = -1;
X      else
X      	winner = my_stake > your_stake;
X      show_over_win(winner);
X    }
X
Xdie();
X}/* end of main */  
END_OF_FILE
if test 8381 -ne `wc -c <'poker.c'`; then
    echo shar: \"'poker.c'\" unpacked with wrong size!
fi
# end of 'poker.c'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0