#!/bin/bash # aceyduecey: dealer flips over two cards and you guess whether # the next card from the deck will or will not rank between # the two. For example, with a 6 and 8, a 7 is between the two, # but a 9 is not. proc initializeDeck { # Start by creating the deck of cards setglobal card = '1' while [ $card != 53 ] # 52 cards in a deck. You knew that, right? { deck[$card]=$card setglobal card = $shExpr(' $card + 1 ') } } proc shuffleDeck { # It's not really a shuffle. It's a random extraction of card values # from the 'deck' array, creating newdeck[] as the "shuffled" deck setglobal count = '1' while [ $count != 53 ] { pickCard newdeck[$count]=$picked setglobal count = $shExpr(' $count + 1 ') } } proc pickCard { # This is the most interesting function: pick a random card from the deck # Uses the deck[] array to find an available card slot. var errcount = '', randomcard = '' setglobal threshold = '10' # max guesses for a card before we fall through set errcount = '0' # Randomly pick a card that hasn't already been pulled from the deck # a max of $threshold times, fall through on fail (to avoid a possible # infinite loop where it keeps guessing the same already dealt card) while [ $errcount -lt $threshold ] { set randomcard = $shExpr(' ( $RANDOM % 52 ) + 1 ') set errcount = $shExpr(' $errcount + 1 ') if test $(deck[$randomcard]) != "0" { setglobal picked = $(deck[$randomcard]) deck[$picked]=0 # picked, remove it return $picked } } # If we get here, we've been unable to randomly pick a card, so we'll # just step through the array until we find an available card set randomcard = '1' while [ ${newdeck[$randomcard]} -eq 0 ] { set randomcard = $shExpr(' $randomcard + 1 ') } setglobal picked = $randomcard deck[$picked]=0 # picked, remove it return $picked } proc showCard { # This uses a div and a mod to figure out suit and rank, though # in this game only rank matters. Still, presentation is # important, so this helps make things pretty. setglobal card = $1 if test $card -lt 1 -o $card -gt 52 { echo "Bad card value: $card" exit 1 } # div and mod. See, all that math in school wasn't wasted! setglobal suit = "$shExpr(' ( ( $card - 1) / 13 ) + 1')" setglobal rank = "$shExpr(' $card % 13')" match $suit { with 1 setglobal suit = '"Hearts'" with 2 setglobal suit = '"Clubs'" with 3 setglobal suit = '"Spades'" with 4 setglobal suit = '"Diamonds'" with * echo "Bad suit value: $suit"; exit 1 } match $rank { with 0 setglobal rank = '"King'" with 1 setglobal rank = '"Ace'" with 11 setglobal rank = '"Jack'" with 12 setglobal rank = '"Queen'" } setglobal cardname = ""$rank of $suit"" } proc dealCards { # Acey Deucey has two cards flipped up... setglobal card1 = $(newdeck[1]) # since deck is shuffled, we take setglobal card2 = $(newdeck[2]) # the top two cards from the deck setglobal card3 = $(newdeck[3]) # and pick card #3 secretly setglobal rank1 = $shExpr(' ${newdeck[1]} % 13 ') # and let's get the rank values setglobal rank2 = $shExpr(' ${newdeck[2]} % 13 ') # to make subsequent calculations easy setglobal rank3 = $shExpr(' ${newdeck[3]} % 13 ') # to make subsequent calculations easy # Fix to make the king, default rank = 0, have rank = 13 if test $rank1 -eq 0 { setglobal rank1 = '13'; } if test $rank2 -eq 0 { setglobal rank2 = '13'; } if test $rank3 -eq 0 { setglobal rank3 = '13'; } # Now let's organize them so that card1 is always lower than card2 if test $rank1 -gt $rank2 { setglobal temp = $card1; setglobal card1 = $card2; setglobal card2 = $temp setglobal temp = $rank1; setglobal rank1 = $rank2; setglobal rank2 = $temp } showCard $card1 ; setglobal cardname1 = $cardname showCard $card2 ; setglobal cardname2 = $cardname showCard $card3 ; setglobal cardname3 = $cardname # shhh, it's a secret for now echo "I've dealt:" ; echo " $cardname1" ; echo " $cardname2" } proc introblurb { cat << """ Welcome to Acey Deucey. The goal of this game is for you to correctly guess whether the third card is going to be between the two cards I'll pull from the deck. For example, if I flip up a 5 of hearts and a jack of diamonds, you'd bet on whether the next card will have a higher rank than a 5 AND a lower rank than a jack (e.g., a 6, 7, 8, 9, or 10 of any suit). Ready? Let's go! """ } ################################################################# #### The main code block .... setglobal games = '0' setglobal won = '0' if test $Argc -gt 0 { # helpful info if a parameter is specified introblurb } while test /bin/true { # The main block starts here initializeDeck shuffleDeck dealCards setglobal splitValue = $shExpr(' $rank2 - $rank1 ') if test $splitValue -eq 0 { echo "No point in betting when they're the same rank!" continue } /bin/echo -n "The spread is $splitValue. Do you think the next card will " /bin/echo -n "be between them? (y/n/q) " read answer if test $answer = "q" { echo "" echo "You played $games games and won $won times." exit 0 } echo "I picked: $cardname3" # Is it between the values? Let's test. Remember, equal rank = lose if test $rank3 -gt $rank1 -a $rank3 -lt $rank2 { # winner! setglobal winner = '1' } else { setglobal winner = '0' } if test $winner -eq 1 -a $answer = "y" { echo "You bet that it would be between the two, and it is. WIN!" setglobal won = $shExpr(' $won + 1 ') } elif test $winner -eq 0 -a $answer = "n" { echo "You bet that it would not be between the two, and it isn't. WIN!" setglobal won = $shExpr(' $won + 1 ') } else { echo "Bad betting strategy. You lose." } setglobal games = $shExpr(' $games + 1 ') # how many times do you play? } exit 0