poker.js

///////////////////////////////////////
//
//    JavaScript Video Poker Game
//    ===========================
//    (c) Copyright Paul Griffiths 2007
//    Email: mail@paulgriffiths.net
//


var newdeal    = 1;                                    //  1 if ready for new deal, 0 if ready to trade, 2 if out of money
var bet        = 5;                                    //  Stores the amount of next bet
var winnings   = 100;                                  //  Stores cumulative winnings
var back       = new Image(73,97);                     //  Image for back of card
var imgoffset     = 0;                                 //  First card should be (imgoffset + 1)th image on the HTML page

var picked     = new Array(52);                        //  To tell which cards already picked when dealing, 0 if unpicked
var flipped    = new Array(5);                         //  To tell which cards are flipped when trading, 0 if unflipped
var cards      = new Array(5);                         //  Stores images for dealt cards
var cardvals   = new Array(5);                         //  Stores values of dealt cards
var cardimg    = new Array(52);                        //  Stores images of entire deck


for ( var i = 0; i < 5; i++ ) {
  cards[i]   = new Image(73,97);                       //  Create array of five card images
  flipped[i] = 0;                                      //  Set flipped flags to unflipped
}

for ( var i = 0; i < 52; i++ ) {
  cardimg[i]     = new Image(73,97);                   //  Create image array for whole deck
  cardimg[i].src = "/images/web/cards/" + (i+1) + ".gif";   //  Precache all the card images
  picked[i]      = 0;                                  //  Set picked flags to unpicked
}

back.src = "/images/web/cards/b.gif";                       //  Store image for back of cards


//  function dealcards() - randomly deals five cards or trade selected cards, called by clicking button

function dealcards(form) {
  if ( !newdeal ) {                                                 //  Player has flipped his unwanted cards
    newdeal = 1;                                                    //  Switch newdeal flag
    form.deal.value = "Click to deal";                              //  Change description on button
    form.bet.disabled = false;                                      //  Make 'bet' text box read only
  }
  else {
    if ( ! isPosInteger(form.bet.value) ) {                         //  Check that 'bet' text box contains valid integer
      alert("You must enter an integer in the 'bet' field!");       //  Alert if it doesn't...
      form.bet.focus();                                             //  ...then return focus to text box...
      form.bet.select();                                            //  ...then highlight the invalid text...
      return;                                                       //  ...then go back for another try
    }
    if ( parseInt(form.bet.value) > parseInt(form.money.value) ) {  //  Check we aren't betting more than we have
      alert("You don't have that much money to bet!");              //  Alert if we are...
      form.bet.focus();                                             //  ...then return focus to text box...
      form.bet.select();                                            //  ...then highlight the invalid text...
      return;                                                       //  ...then go back for another try
    }
        
    newdeal = 0;                                                    //  This is a new hand, so do some stuff

    for ( var i = 0; i < 5; i++ ) {
      flipped[i] = 0;                                               //  Reset flipped flags for all five cards
    }
    for ( var i = 0; i < 52; i++ ) {
      picked[i] = 0;                                                //  Reset picked status of entire deck
    }

    form.info.value   = "Click the cards you want to trade";        //  Update info box
    bet               = form.bet.value;                             //  Get amount to bet...
    winnings         -= bet;                                        //  ...deduct it from winnings...
    form.money.value  = winnings;                                   //  ...and update winnings
    form.deal.value   = "Click to trade";                           //  Change description on button
    form.bet.disabled = true;                                       //  Make 'bet' text box editable again
  }

  for ( var i = 0; i < 5; i++ ) {                                   //  Deal five random cards
    if ( !newdeal || flipped[i] ) {                                 //  If not a new hand, replace only the flipped cards
      do {
        var n = Math.round(Math.random() * 51);                     //  Pick random card
      } while ( picked[n] );                                        //  Make sure not already picked
      picked[n] = 1;                                                //  Got it, so set picked flag
      cards[i].src = cardimg[n].src;                                //  Update card image array
      document.images[i+imgoffset].src = cardimg[n].src;               //  Update on screen
      cardvals[i] = n;                                              //  Store value of card
    }
  }

  if ( newdeal )                                                    //  We've replaced the flipped cards...
    checkwin(form);                                                 //  So check if we've won
}


//  function flipcard() - flips a clicked card, called by clicking a card

function flipcard(i) {
  if ( newdeal )                              //  If it's the end of a hand, we can't flip, so just return
    return;

  if ( !flipped[i] ) {                        //  Either flip card over...
    document.images[i+imgoffset].src = back.src;
    flipped[i] = 1;
  }
  else {                                      //  ...or flip it back
    document.images[i+imgoffset].src = cards[i].src;
    flipped[i] = 0;
  }
}


//  Compare function for sorting the cards

function compare(a, b) {
  return a-b;
}

    
//  Checks for winnings

function checkwin(form) {
  var suits = new Array(4);                   //  Used to check for a flush
  var matched = new Array(13);                //  Used to check for pairs, threes, fours
  var pairs = 0, threes = 0, fours = 0;       //  1 or 2 if we have any of these, 0 if not
  var flush = false, straight = false;        //  true if we have a flush or straight, false if not
  var won = 0;                                //  1 if there's a winning hand, 0 if not

  cardvals.sort(compare);                     //  Sort the cards using the compare() function

  for ( var i = 0; i < 4; i++ ) {
    suits[i] = 0;                             //  Initialise suits array to zero
  }

  for ( var i = 0; i < 13; i++ ) {
    matched[i] = 0;                           //  Initialise matched array to zero  
  }

  for ( var i = 0; i < 5; i++ ) {
    matched[cardvals[i] % 13]++;              //  Update matched for cards
    suits[Math.floor(cardvals[i]/13)]++;      //  Update suits for cards
  }

  for ( var i = 0; i < 13; i++ ) {
    if ( matched[i] == 2 ) {                  //  Check for pairs
      pairs++;
    }
    else if ( matched[i] == 3 ) {             //  Check for three of a kind
      threes++;
    }
    else if ( matched[i] == 4 ) {             //  Check for four of a kind
      fours++;
    }
  }

  for ( var i = 0; i < 4; i++ ) {                        //  Check for a flush
    if ( suits[i] == 5 ) {
      flush = true;
    }
  }

  if ( cardvals[4] - cardvals[1] == 3  &&                //  Consistent with 
       cardvals[4] - cardvals[0] == 12 &&                //  A, T, J, Q, K...
       flush ) {                                       
    form.info.value = "Royal flush!";
    won = bet * 2500;
  }
  else if ( cardvals[4] - cardvals[0] == 4 && flush ) {  //  If we also have a flush, then its a royal flush
    info.value = "Straight flush!";
    won = bet * 250;
  }


  //  Sort cards by face value (necessary to check for a straight)

  for ( var i = 0; i < 5; i++ )
    cardvals[i] = cardvals[i] % 13;
  cardvals.sort(compare);


  if ( won == 0 ) {                                      // Don't check further if we've already won
    if ( fours > 0 ) {
      form.info.value = "Four of a kind!";
      won = bet * 100;
    }
    else if ( threes && pairs ) {
      form.info.value = "Full house!";
      won = bet * 50;
    }
    else if ( flush ) {
      form.info.value = "A flush!";
      won = bet * 20;
    }
    else if ( cardvals[4] - cardvals[3] == 1 && cardvals[3] - cardvals[2] == 1 &&
              cardvals[2] - cardvals[1] == 1 && ( cardvals[1] - cardvals[0] == 1 ||
              cardvals[4] - cardvals[0] == 12 ) ) {
      form.info.value = "A straight!";
      won = bet * 15;
    }
    else if ( threes ) {
      form.info.value = "Three of a kind!";
      won = bet * 4;
    }
    else if ( pairs == 2 ) {
      form.info.value = "Two pair!";
      won = bet * 3;
    }
    else if ( matched[0]  == 2 ||
              matched[10] == 2 ||             
              matched[11] == 2 ||             
              matched[12] == 2 ) {
      form.info.value = "Jacks or better!";
      won = bet * 2;
    }
    else {
      form.info.value = "No win! Bad luck!";
    }
  }


  //  Update winnings if we've won

  if ( won ) {
    winnings += won;
    form.money.value = winnings;
    form.info.value += " You win $" + won + "!";
  }
    
    
  //  Check to see if we're out of money
    
  if ( !winnings ) {
    newdeal = 2;
    alert("You've run out of money! Click 'OK' to reset.");
    form.bet.value = bet = 5;
    form.money.value = winnings = 100;
    form.info.value = "It's time to play! Click button to deal!";
    for ( var i = 0; i < 5; ++i ) {
      flipped[i] = 0;
      flipcard(i);
    }
  }
}


//  Checks to see if 'v' represents a positive integer

function isPosInteger(v) {
  s = v.toString();
  for ( var n = 0; n < s.length; n++ ) {
    if ( s.charAt(n) < "0" || s.charAt(n) > "9" )
      return false;
  }
  return true;
}