/*****************************************************************************
 *                                                                           *
 *  Copyright (c) 1993, 1994, 1995, Elan Feingold (feingold@zko.dec.com)     *
 *                                                                           *
 *     PERMISSION TO USE, COPY, MODIFY, AND TO DISTRIBUTE THIS SOFTWARE      *
 *     AND ITS DOCUMENTATION FOR ANY PURPOSE IS HEREBY GRANTED WITHOUT       *
 *     FEE, PROVIDED THAT THE ABOVE COPYRIGHT NOTICE APPEAR IN ALL           *
 *     COPIES AND MODIFIED COPIES AND THAT BOTH THAT COPYRIGHT NOTICE AND    *
 *     THIS PERMISSION NOTICE APPEAR IN SUPPORTING DOCUMENTATION.  THERE     *
 *     IS NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR      *
 *     ANY PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS       *
 *     OR IMPLIED WARRANTY.                                                  *
 *                                                                           *
 *****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>

#include "deck.h"
#include "debug.h"

extern void UTIL_ExitProgram(Int32 i);

/************************************************************************ 
 *  FUNCTION: DECK_Create
 *  HISTORY: 
 *     02.04.94  ESF  Created.
 *     03.16.94  ESF  Added code for returned card handling.
 *  PURPOSE: 
 *  NOTES: 
 ************************************************************************/
Deck *DECK_Create(Int32 iNumCards)
{
  Deck   *pDeck = (Deck *)MEM_Alloc(sizeof(Deck));
  Int32   i;

  /* Seed the random number generator */
  srand((Int32)clock());

  /* Init the structure */
  pDeck->iCardsLeft = pDeck->iTotalCards = iNumCards;
  pDeck->iCardsReturned = 0;
  pDeck->piCards         = (Int32 *)MEM_Alloc(sizeof(Int32)*iNumCards);
  pDeck->piCardsReturned = (Int32 *)MEM_Alloc(sizeof(Int32)*iNumCards);

  /* Init all of the cards */
  for(i=0; i!=iNumCards; i++)
    pDeck->piCards[i] = i;

  return(pDeck);
}


/************************************************************************ 
 *  FUNCTION: DECK_GetCard
 *  HISTORY: 
 *     02.04.94  ESF  Created.
 *     03.16.94  ESF  Added code for returned card handling.
 *     05.15.94  ESF  Changed to return -1 when deck is empty.
 *  PURPOSE: 
 *  NOTES: 
 ************************************************************************/
Int32 DECK_GetCard(Deck *pDeck)
{
  Int32 iCardIndex, iCard;
  Int32 i;
  
  /* If there are no cards left, take all of the cards from the 
   * returned pile and put them into the deck.
   */

  if (!pDeck->iCardsLeft)
    {
      /* Are there cards to return to the deck? */
      if (!pDeck->iCardsReturned)
	return(-1);

      /* Copy all of the returned cards to the deck */
      memcpy((char *)pDeck->piCards, (char *)pDeck->piCardsReturned, 
	     sizeof(Int32)*pDeck->iCardsReturned);
      pDeck->iCardsLeft = pDeck->iCardsReturned;
      pDeck->iCardsReturned = 0;

#ifdef MEM_DEBUG
      printf("New deck:\n");
      for (i=0; i!=pDeck->iCardsLeft; i++)
	printf("%d.", pDeck->piCards[i]);
      printf("\n");
#endif
    }

  /* Pick a card out of the remaining ones */
  iCardIndex = rand() % pDeck->iCardsLeft;

  /* Switch the last card with this one. */
  iCard = pDeck->piCards[iCardIndex];
  pDeck->piCards[iCardIndex] = pDeck->piCards[--pDeck->iCardsLeft];

  return(iCard);
}



/************************************************************************ 
 *  FUNCTION: DECK_PutCard
 *  HISTORY: 
 *     02.04.94  ESF  Created.
 *     03.16.94  ESF  Fixed so that it would act like a real deck.
 *     03.29.94  ESF  Fixed a dumb bug in full deck detection.
 *  PURPOSE: 
 *  NOTES: 
 ************************************************************************/
void DECK_PutCard(Deck *pDeck, Int32 iCard)
{
  /* If returned card pile fills up, this is bad */
  if (pDeck->iCardsLeft == pDeck->iTotalCards)
    {
      printf("Fatal Error! DECK: Can't add to full deck!\n");
      UTIL_ExitProgram(-1);
    }
  
  /* Add the card to the retured cards pile */
  pDeck->piCardsReturned[pDeck->iCardsReturned++] = iCard;
}


/************************************************************************ 
 *  FUNCTION: DECK_Destroy
 *  HISTORY: 
 *     02.04.94  ESF  Created.
 *     03.16.94  ESF  Added code for returned card handling.
 *  PURPOSE: 
 *  NOTES: 
 ************************************************************************/
void DECK_Destroy(Deck *pDeck)
{
  MEM_Free(pDeck->piCards);
  MEM_Free(pDeck->piCardsReturned);
  MEM_Free(pDeck);
}
