Version 10 of Whitejack

Updated 2015-06-25 21:13:12 by MiHa

if 0 {


Introduction

MiHa 2015-06-24: One of the example-programs on my HelloWorld-page creates a deck of cards,
so I had the idea to expand that into a simple cardgame, for the tcl-console.

Blackjack is quite simple, and with (debug-)options still in place to show the cards "in the open",
this would nicely double as a tcl-tutorial and a blackjack-trainer.

With ideas and code from the following pages:

  • HelloWorld (MiHa) - the examples using foreach, while, gets, unicode and list
  • ...

}


Program

 # Whitejack.tcl - MiHa - 2015-06-25
 # http://wiki.tcl.tk/41565
 # http://ideone.com/jVxnHV

  puts "Whitejack:\n"
  
  proc help {}  {     ;# Todo: needs rewording
    puts "\nWhitejack - a cardgame much like simplified, self-service blackjack."
    puts {It is played with one or more decks of 52 cards. 
The object of the game is to beat the dealer:
* Get 21 points on the player's first two cards (called a blackjack), without a dealer blackjack;
* Reach a final score higher than the dealer without exceeding 21; 
* orLet the dealer draw additional cards until his or her hand exceeds 21.
The player is dealt an initial two-card hand and add together the value of their cards. 
Face cards (kings, queens, and jacks) count as ten points. 
An ace is worth 1 point or 11 points, owners choice. 
All other cards count as the numeric value shown on the card. 
After their initial two cards, players can get a "hit", i.e. take an additional card. 
In a given round, the player or the dealer wins by having a score of 21 or
by having the highest score that is less than 21. 
Scoring higher than 21 (called "busting" or "going bust") results in a loss.Commands:
---------
h   : help
q   : quit

n   : new cards: add a fresh pack of 52 cards to the deck.
f   = fill: move cards from discard-pile to the end of the deck.
t   = trash: empty both hands and the discard-pile.
f   : fill: move cards from discard-pile to the end of the deck.
t   : trash: empty both hands and the discard-pile.
0-9 : move the card from position 0..9 of the deck to the end of the deck.
0   : move the card from the front of the deck to the discard-pile
1   : move the card from the front of the deck to the end of the deck.
2-9 : move the card from position 2..9 of the deck to the end of the deck.
%   : swap the two cards at the front of the deck (positions 1 and 2).
s   : shuffle the deck (do a number of "1-9"-actions).
d,- : dealer-draw: move first card from deck to dealer's hand

b,l : bust: player loses the round
w   : win : player wins the round

x   = discard: move cards from player's hand to the discard-pile
y   = discard: move cards from dealer's hand to the discard-pile
x   : discard: move cards from player's hand to the discard-pile
y   : discard: move cards from dealer's hand to the discard-pile

  }


  proc showStatus {}  {
      global deck discard playerHand dealerHand cWin cLoss

      puts "\nStatus:"
      puts -nonewline "Number of cards in "
      puts -nonewline       "deck: [llength $deck]  "
      puts -nonewline    "discard: [llength $discard]  "
      puts -nonewline "playerHand: [llength $playerHand]  "
      puts            "dealerHand: [llength $dealerHand]  "
      puts "Wins: $cWin  Losses: $cLoss"

     #puts "card #3 [lindex $::deck 2]"        ;# index is zero-based
     #showList "Deck" $deck 0 19
      showFirst "Deck" $deck 18
      showLast  "Deck" $deck 18
      
      puts "Player: $playerHand  Value: [cardValue $playerHand]" 
      puts "Dealer: $dealerHand  Value: [cardValue $dealerHand]"  
      puts "Player: $playerHand" 
      puts "Dealer: $dealerHand" 
  proc win {x}  {
    if { $x>0 } { 

    puts -nonewline "Making cards..."
    set i 0
    # For unicode, see also: http://wiki.tcl.tk/26403 : [HTML character entity references]

                     # Spades    Hearts    Diamonds  Clubs
    foreach {suit sym} { S \u2660  H \u2665  D \u2666  C \u2663 } {   
      foreach rank { A 2 3 4 5 6 7 8 9 10 J Q K } { ;# Ace 2 .. 10 Jack Queen King
        incr i
        set card "$rank$sym"
       #puts -nonewline " $rank$suit=$card "
        lappend deck $card                     ;# add card to list
      }
   #puts ""
    }
    set maxCard $i
    puts "done.\nPack of $maxCard cards added to the deck."
   #puts "\ndeck : $deck"                ;##
    puts "done.\nPack of cards with $maxCard cards added to deck."

  proc c1 {s} { set c [string range $s 0 0] }  ;# return first char of string
 
    puts "$tx $p1-$p2: [lrange $L $p1 $p2]"
  }
  proc showFirst {tx L n}  {   ;# show the first n elements in list L
    puts "$tx 0-$n: [lrange $L 0 $n] ..."
  }
  proc showLast {tx L n}  {   ;# show the last n elements in list L
    set p2 [llength $L]
    set p1 $p2; incr p1 -$n
    puts "$tx $p1-$p2: ... [lrange $L $p1 $p2]"
  }
  
  proc deal_p {}  {
  # deal card from deck to player's hand:
     global deck discard playerHand dealerHand 
  
     set card [lindex $deck 0]               ;# get first card from deck
     lappend playerHand $card                ;# put it in his hand
                                             ;# delete it from the deck:
     set deck [lreplace $deck[set deck {}] 0 0 ]
     # see also: [lreplace] - "Modifying a List In-Place"

   ##puts "deck : $deck"
   ##showList "Deck" $deck 0 18
  }

  proc moveCard {p}  {
  # move card from position p at front of deck to end of deck:
     global deck discard playerHand dealerHand 
  
     set card [lindex $deck 0]               ;# get first card from deck
     lappend dealerHand $card                ;# put it in his hand
                                             ;# delete it from the deck:
     set deck [lreplace $deck[set deck {}] 0 0 ]
  }
  
  proc deal {to}  {
  # deal card from deck to player- or dealer's hand:
    #global deck discard playerHand dealerHand 
  
     set card [lindex $::deck 0]             ;# get first card from deck
     lappend $to $card                       ;# put it in his hand
                                             ;# delete it from the deck:
     set ::deck [lreplace $::deck[set ::deck {}] 0 0 ]
     # see also: [lreplace] - "Modifying a List In-Place"

   ##puts "deck : $::deck"
   ##showList "Deck" $::deck 0 18
  }
  
  set deck {}                                  ;# create empty list
  set discard {}
  set playerHand {}
  set dealerHand {}
  
  set cWin  0
  set cLoss 0
  set dealerCash 1000
  set playerCash  100

  puts "Start with 'n' to get a fresh pack of cards."

  set cmd "."                ;# try: n 1  + - + -  + - -  w * q
  while { $cmd ne "q" } {
  set cmd "."
    set cmd [gets stdin]
    puts $cmd

    if {$cmd=="h"} { help }
    if {$cmd=="q"} { puts "Bye!"; exit }
    
    if {$cmd=="n"} { makeCards }
    if {$cmd=="0"} { moveCard 0 }
    if {$cmd=="1"} { moveCard 1 }
   #if {$cmd=="d"} { deal $dealerHand }
   #if {$cmd=="p"} { deal $playerHand }
   
   if {$cmd=="w"} { win  1 }
  }

#.

----
**Output**

Whitejack:

Start with 'n' to get a fresh pack of cards.


Comments

MiHa 2015-06-26: The most basic functionality is done,

Remarks

This is not-yet the Alpha-version, there will be bugs, so use with caution
... with regard to changing values outside the proc.