//*****************************************************************************
// 
// Blackjack - an X windows program of the casino game.
// Copyright (C) 1997  Tom Daley 
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// 
// The license is in the file COPYING.
// 
// Tom Daley
// 1309 W. Lorraine Ave.
// Woodland Park, CO  80863-2329
// 
// daley@codenet.net (Tom Daley)
// http://users.codenet.net/daley
// 
//*****************************************************************************

#include <stdlib.h>
#include <iostream.h>
#include <time.h>

#include "shoe.h"

extern "C" double drand48();

//*****************************************************************************

Shoe::
Shoe (int num_decks) {
   int deck, suit, rank;
   time_t time1;
   Card **card_pp;

   Card::init();
   _num_cards = num_decks * 52;

   _cards = new (Card (*[_num_cards])); 

   if (_cards == NULL) {
      cerr << "Shoe::Shoe(): Can't allocate memory for cards\n";
      exit (1);
   }
  
   _next_card = 0;
   card_pp = _cards;
   for (deck = 0; deck < num_decks; deck++)
      for (suit = Card::SPADE; suit <= Card::CLUB; suit++)
         for (rank = Card::ACE; rank <= Card::KING; rank++)
            *card_pp++ = new Card((Card::RankType)rank, (Card::SuitType)suit); 

   time(&time1);	// seed random number generator with time in seconds
   srand48(time1);
   shuffle();
}

//*****************************************************************************

Shoe::
~Shoe() { 
   int i;

   for (i = 0; i < _num_cards; i++)
      delete (_cards[i]);

   delete[]_cards; 
}


//*****************************************************************************

void Shoe::
shuffle(void) {
   int offset, i, index;
   Card **card_p, **prev_card_p, **temp_shoe;

   _next_card = 0;
   temp_shoe = new (Card (*[_num_cards])); 

   for (i = _num_cards; i > 0; i--) {
      offset = (int)(drand48() * i); 		// take a random card
      temp_shoe[i - 1] = _cards[offset];   	// put in the temp shoe
      prev_card_p = &_cards[offset];		// move cards to fill space
      card_p = prev_card_p + 1;			// of card taken
      for (index = offset; index < i - 1; index++)
         *prev_card_p++ = *card_p++;
   }
   memcpy(_cards, temp_shoe, sizeof(Card *) * _num_cards);
   delete[]temp_shoe;
}

//*****************************************************************************

Card *Shoe::
getCard(Card::Direction dir) {
   Card *cp = NULL;

   if (_next_card < _num_cards) {
      cp = _cards[_next_card++];
      cp->setDirection(dir);
   }

   return (cp); 
}

//*****************************************************************************
// This is for debug only, you can stack the deck to test a scenerio
//*****************************************************************************

void Shoe::
putCard(int rank, int suit, int pos) {
   int i;
   if (pos < _num_cards) {
      for (i = _num_cards - 1; i >= 0; i--) {
         if (_cards[i]->getRank() == rank && _cards[i]->getSuit() == suit) {
            Card *cp;
            cp = _cards[i];		// save card pointer
            _cards[i] = _cards[pos];	// move card 2 to card 1
            _cards[pos] = cp;		// move card 1 to card 2
            break;
         }
      }
   }
}

//*****************************************************************************
