Dave Taylor's Final Cribbage Script


#!/bin/sh

# Cribbage - program to evaluate a cribbage hand and 
# suggest an optimal subset

# In cribbage, you seek cards that add up to 15, sets of 3-4 cards w/ same 
# rank, runs of 3 or more cards and sets of 4 cards of the same suit.

# We'll represent our hand in an array of six cards: hand[0-5] where 
# each card has a value of 1-52, which breaks down into 
# cardnum / 13 = rank and cardnum % 13 = suit

suits[0]="H"; suits[1]="C"; suits[2]="D"; suits[3]="S";
hand[0]=0; hand[1]=0; hand[2]=0; hand[3]=0; hand[4]=0; hand[5]=0;

# combinations of four choose two and four choose three

fourtwo[0]="0 1"; fourtwo[1]="0 2"; fourtwo[2]="0 3"; fourtwo[3]="1 2"
fourtwo[4]="1 3"; fourtwo[5]="2 3"; fourthree[0]="0 1 2"; 
fourthree[1]="0 1 3"; fourthree[2]="0 2 3"; fourthree[3]="1 2 3"

debug=0

showcard()
{
  # given a card value of 0..51 show the suit and rank

  suit=$(( $1 / 13 ))
  rank=$(( ( $1 % 13 ) + 1 ))
  case $rank in
    1)  orank="A" ;;
    11) orank="J" ;;
    12) orank="Q" ;;
    13) orank="K" ;;
     *) orank=$rank ;;
  esac
  showcardvalue=$orank${suits[$suit]}
}

dealhand()
{
   # we need to establish a deck from which to deal 
   # the individual cards (to avoid duplication)

   for i in {0..51}
   do 
     deck[$i]=$i
   done

   # we're not going to "shuffle" the deck because we can 
   # just pick from it randomly instead

   # start with an undealt hand: 
   for card in {0..5} ; do
     hand[$card]=-1
   done

   # now let's deal some cards!
   for card in {0..5} ; do
     until [ ${hand[$card]} -ne -1 ]
     do
       pick=$(( $RANDOM % 52 ))
       hand[$card]=${deck[$pick]}
     done
     deck[$pick]=-1	# we've now dealt it so it's no longer available
   done
}

showhand()
{
   # show our hand neatly

   /bin/echo -n "Hand: "
   for card in {0..4}
   do
     showcard ${hand[$card]}
     /bin/echo -n "$showcardvalue, "
   done
   showcard ${hand[5]}
   echo "$showcardvalue."
}

sorthand()
{
   # hand is dealt, now sort it by card rank...

   index=0
   tempfile=".deleteme"

   for card in {0..5}
   do
     showcard ${hand[$card]} 
     echo "$rank ${hand[$card]}"
   done | sort -n > $tempfile

   while read rank value
   do
     hand[$index]=$value
     index=$(( $index + 1 ))
   done < $tempfile

   rm -f $tempfile
}

Calc4cardValue()
{
  # given four ranks, see if there are any combinations 
  # that add up to 15, pairs, runs or flushes.
  # return total point value of the four card subhand

  points=0 ; runof3=0

  cs0=$9; cs1=${10}; cs2=${11}; cs3=${12}       # suits

  cardrank[0]=$1; cardrank[1]=$2; cardrank[2]=$3; \
  cardrank[3]=$4 # normalized ranks 
  cardrankfull[0]=$5; cardrankfull[1]=$6; cardrankfull[2]=$7; 
  cardrankfull[3]=$8                      # original ranks

  # echo "Calc4cardValue() given original ranks: \
  #      ${cardrankfull[0]} ${cardrankfull[1]} ${cardrankfull[2]} \
  #      ${cardrankfull[3]}"

  # two card combos

  for mysubhand in {0..5}
  do
    sum=0

    for thecard in ${fourtwo[$mysubhand]} 
    do 
      sum=$(( $sum + ${cardrank[$thecard]} ))
    done
    if [ $sum -eq 15 ] ; then
      points=$(( $points + 2 ))
      if [ $debug -eq 1 ] ; then 
        echo "fifteen for two" 
      fi
    fi

    # now let's look at pairs
    #  remember:  ${string:position:length}

    twocards=${fourtwo[$mysubhand]}
    card1=${twocards:0:1}
    card2=${twocards:2}

    if [ ${cardrankfull[$card1]} = ${cardrankfull[$card2]} ] ; then
      if [ $debug -eq 1 ] ; then
        echo "a pair ${cardrankfull[$card1]} and \
                 ${cardrankfull[$card2]} for two"
      fi
      points=$(( $points + 2 ))
    fi
      
  done

  # three card combos

  for mysubhand in {0..3}
  do
    sum=0

    for thecard in ${fourthree[$mysubhand]} 
    do 
      sum=$(( $sum + ${cardrank[$thecard]} ))
    done
    if [ $sum -eq 15 ] ; then
      points=$(( $points + 2 ))
      if [ $debug -eq 1 ] ; then
        echo "three card fifteen for two"
      fi
    fi

    # now let's check for three-card runs
    combo=${fourthree[$mysubhand]}

    if [ $(( ${cardrankfull[${combo:0:1}]} + 1 )) -eq \
              ${cardrankfull[${combo:2:1}]} -a \
         $(( ${cardrankfull[${combo:2:1}]} + 1 )) -eq \
              ${cardrankfull[${combo:4:1}]} ] ; then
      if [ $debug -eq 1 ] ; then
        /bin/echo -n "${cardrankfull[${combo:0:1}]} + \
                ${cardrankfull[${combo:2:1}]} + "
        echo "${cardrankfull[${combo:4:1}]} run for three" 
      fi
      points=$(( $points + 3 ))
      runof3=$(( $runof3 + 1 ))
    fi

  done

  # four cards combos 

  if [ $(( ${cardrank[0]} + ${cardrank[1]} + ${cardrank[2]} + \
            ${cardrank[3]} )) -eq 15 ] ; then
    points=$(( $points + 2 ))
    if [ $debug -eq 1 ] ; then
      echo "four card fifteen for two"
    fi
  fi

  if [ $cs0 -eq $cs1 -a $cs1 -eq $cs2 -a $cs2 -eq $cs3 ] ; then
    if [ $debug -eq 1 ] ; then
      echo "four card flush for four."
    fi
    points=$(( $points + 4 ))
  fi

  if [ $runof3 -eq 2 ] ; then
    if [ $debug -eq 1 ] ; then
      echo "two runs of three = a run of four. minus two"
    fi
    points=$(( $points - 2 ))
  fi

  if [ $debug -eq 1 ] ; then
    echo "Total point value of that hand: $points"
  fi
}


handvalue4()
{
   # given four cards, how much are they worth unto themselves?

   c1=$1; c2=$2; c3=$3; c4=$4
   s1=$(( $c1 / 13 )); s2=$(( $c2 / 13 ))
   s3=$(( $c3 / 13 )); s4=$(( $c4 / 13 ))

   r1=$(( ( $c1 % 13 ) + 1 )); r2=$(( ( $c2 % 13 ) + 1 ))
   r3=$(( ( $c3 % 13 ) + 1 )); r4=$(( ( $c4 % 13 ) + 1 ))

   # now fix rank to normalize for value=10
   case $r1 in 
     11|12|13) nr1=10 ;;
     *) nr1=$r1 ;;
   esac
   case $r2 in
     11|12|13) nr2=10 ;;
     *) nr2=$r2 ;;
   esac
   case $r3 in
     11|12|13) nr3=10 ;;
     *) nr3=$r3 ;;
   esac
   case $r4 in
     11|12|13) nr4=10 ;;
     *) nr4=$r4 ;;
   esac

   ## Ready to start calculating!

   if [ $debug -eq 1 ] ; then
     echo ""
   fi 
   Calc4cardValue $nr1 $nr2 $nr3 $nr4 $r1 $r2 $r3 $r4 $s1 $s2 $s3 $s4
}

if [ $# -gt 0 ] ; then 
  debug=1
fi

dealhand;
sorthand;
showhand;

# six choose four

sixfour[0]="0 1 2 3";  sixfour[1]="0 1 2 4";  sixfour[2]="0 1 2 5";  \
sixfour[3]="0 1 3 4"
sixfour[4]="0 1 3 5";  sixfour[5]="0 1 4 5";  sixfour[6]="0 2 3 4";  \
sixfour[7]="0 2 3 5"
sixfour[8]="0 2 4 5";  sixfour[9]="0 3 4 5";  sixfour[10]="1 2 3 4"; \
sixfour[11]="1 2 3 5"
sixfour[12]="1 2 4 5"; sixfour[13]="1 3 4 5"; sixfour[14]="2 3 4 5"

handvalue=0
besthand=-1

for subhand in {0..14}
do
  if [ $debug -eq 1 ] ; then
    /bin/echo -n "Subhand ${subhand}:" 
  fi
  cardnum=0  # start over
  for thecard in ${sixfour[$subhand]}
  do
    if [ $debug -eq 1 ] ; then
      showcard ${hand[$thecard]}
      /bin/echo -n "  $showcardvalue"
    fi
    oursubhand[$cardnum]=${hand[$thecard]}
    cardnum=$(( $cardnum + 1 ))
  done
  handvalue4 ${oursubhand[0]} ${oursubhand[1]} ${oursubhand[2]} \
                     ${oursubhand[3]}

  if [ $debug -eq 1 ] ; then
    echo ""
  fi

  if [ $points -gt $handvalue ] ; then
    if [ $debug -eq 1 ] ; then
      echo "** hand $subhand is the best yet, adding up to $points points"
    fi
    besthand=$subhand
    handvalue=$points
  fi

done

/bin/echo -n "Your best subhand is worth $handvalue points: "

  for thecard in ${sixfour[$besthand]}
  do
    showcard ${hand[$thecard]}
    /bin/echo -n "  $showcardvalue"
  done

echo ""

exit 0
Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix