home *** CD-ROM | disk | FTP | other *** search
/ Over 1,000 Games for Windows / Over1000GamesForWindows.iso / CARDS / 7andHalf / cards.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2003-02-09  |  8.7 KB  |  283 lines

  1. /* **************************************************************************************
  2.    File: Cards.cpp
  3.    By Mauro Mindoli 
  4.    
  5.    January 2003 ver. 1.0
  6.    
  7.    February 2003 : ver 2.0
  8.    Corrected some bug and added new features to the code:
  9.   
  10.   @@ DONE 
  11.    @ Management of hidden card , the first one of the human player. Now Pc does not see it!
  12.    @ New method CPlayerNapoletano::GetEstimatedPoints() that makes some pseudo A.I.
  13.    @ Corrected GameNapoletano::Play() to insert an estimation of the points.
  14.    @ Changed the bet edit box, now it is a combo box.
  15.    @ Bet is now only allowed after the first (hidden) card, like in the real rules.
  16.    @ Implemented a simple error checking when there are not bmp to load (before it simply crashed!)
  17.    @ Introduced two txt files to read for Info and for Rules in the help dialog and its menu.
  18.    @ Solved a memory leak for a bug in the distructor ~CDeckNapoletano: it deleted the wrong deck
  19.    @ Added sound effects!
  20.    @ Management of the "jolly" i.e. the 10 of gold that can change its value 
  21.      (0.5, 1, 2, ..., 7, but NOT 1.5, 4.5, ...), dinamically.
  22.  
  23. ***************************************************************************************** */
  24. #include "stdafx.h"
  25. #include "cards.h"
  26.  
  27. int CGameCard::GetIdCard()
  28. {
  29.    return (mFam << 8) | mVal; 
  30. }
  31.  
  32. CDeck::CDeck(int numCards, int numFams)  : mNumCards(numCards), mNumFams(numFams)
  33. {
  34.    mCurPos = 0;
  35. }
  36.  
  37. void CDeck::ShuffleDeck()
  38. {
  39.    // the suffle is implemented by random swapping   
  40.    srand(time( NULL ) );
  41.    int randcard;
  42.    for (int ncard = 0; ncard < mNumCards; ncard++)
  43.    {
  44.       randcard = rand()%mNumCards;         
  45.       std::swap(shuffledDeck[ncard], shuffledDeck[randcard]);
  46.    }
  47.  
  48. }
  49.  
  50. // The current card is taken from the Deck already shuffled by the mCurPos that is incremented
  51. bool CDeck::GiveMeACard(const CGameCard* &card) 
  52. {
  53.    if (mCurPos >= mNumCards)
  54.       return false;
  55.    else
  56.       card = shuffledDeck[mCurPos++];
  57.    return true;
  58. }
  59.  
  60. CDeckNapoletano::CDeckNapoletano() : CDeck(NCARDS, NFAMS)
  61. {
  62.    // init the Deck ordering it by values and familys
  63.    int vCard;
  64.    int vFam;
  65.    mDeck.reserve(NCARDS);
  66.    shuffledDeck.reserve(NCARDS);
  67.    // we have to use mDeck to store the allocated pointers
  68.    // to delete them in the distructor, and shuffledDeck
  69.    // to play
  70.    for (vFam = game::COPPE; vFam < game::END; vFam++)
  71.       for (vCard = 1; vCard <= (mNumCards/mNumFams); vCard++)
  72.       {
  73.          CGameCardNapoletano *p = new CGameCardNapoletano(vFam, vCard);
  74.          mDeck.push_back(p);
  75.          shuffledDeck.push_back(p);
  76.       }
  77. }
  78.  
  79. CDeckNapoletano::~CDeckNapoletano()
  80. {
  81.    VecPCards::iterator itCurCard = mDeck.begin();
  82.    for (; itCurCard != mDeck.end(); itCurCard++)
  83.       delete (*itCurCard);
  84. }
  85.  
  86. // we reshuffle the deck when cards are ended
  87. // we cannot use the same original deck, because some card
  88. // are still in play, so we have to use outCards: the vector 
  89. // with all cards played
  90. void CDeckNapoletano::Reshuffle(VecPCards &outCards)
  91. {
  92.    mNumCards = outCards.size(); // mNumCard is <= 40 now
  93.    shuffledDeck.erase(shuffledDeck.begin(), shuffledDeck.end());
  94.    // we copy outCards in the shuffled Vector to restart the game
  95.    for (VecPCards::iterator it = outCards.begin(); it != outCards.end(); it++)
  96.       shuffledDeck.push_back(*it);
  97.    // mCurPos has to be reset!
  98.    mCurPos = 0;
  99. }
  100.  
  101. CPlayer::CPlayer(std::string name) : mPoints(0.0), mName(name){}
  102.  
  103. #include <math.h>
  104. int CPlayerNapoletano::AddCard(CGameCard *pCard)
  105. {
  106.    int val, fam;
  107.    pCard->GetFamVal(fam, val);
  108.    
  109.    // the card is the Jolly! Possible Jolly values are: 0.5, 1, 2, 3, 4, 5, 6, 7
  110.    if ((fam == game::DENARI) && (val == 10))
  111.    {
  112.       // I want to check if I had a point with a decimal part or not:
  113.       // if I have 3.5 points my jolly will be 4, if I have 4 points my jolly will be 3
  114.       mJollyValue = (mPoints - floor(mPoints)) > 0 ? 7.5 - mPoints : 7.0 - mPoints;
  115.       mPoints += mJollyValue;
  116.       if (mJollyValue == 0.0)
  117.          mJollyValue = mPoints; // Jolly was the first card
  118.    }
  119.    else // Jolly was already in hand
  120.    if (mJollyValue)
  121.    {
  122.       mPoints = mPoints - mJollyValue + ((val > 7) ? 0.5 : val); // points without jolly
  123.       if (mPoints < 7.5) // minimum Jolly value is 0.5
  124.          mJollyValue = (mPoints - floor(mPoints)) > 0 ? 7.5 - mPoints : 7.0 - mPoints;
  125.       mPoints += mJollyValue;
  126.    }
  127.    else // normal case
  128.       mPoints += (val > 7) ? 0.5 : val;
  129.    
  130.    if (mPoints > 7.5)
  131.       return game::GAME_LOST;
  132.    else
  133.       return game::GAME_OK;
  134. }
  135.  
  136. void CPlayerNapoletano::AddHand(CGameCard *pCard)
  137. {
  138.    mHand.push_back(pCard);
  139. }
  140.  
  141. // ****************************************
  142. // * Artificial Intelligence Method!!!(?) *
  143. // ****************************************
  144. double CPlayerNapoletano::GetEstimatedPoints() const
  145. {
  146.    double valEstimated = 0.0;
  147.    // there is only the hidden card
  148.    // so the Pc estimate the hidden card
  149.    // basing (psychology!) on the average of the old hidden cards
  150.    if (mHand.size() <= 1)
  151.       valEstimated = mEstimatedCard;
  152.    else
  153.    // Pc must know (it's a rule) when we have 7.5 points
  154.    if (mPoints == 7.5)
  155.       valEstimated = 7.5;
  156.    else
  157.    {
  158.       int fam, valHidden;
  159.       // this is the hidden card, and pc must not know about it!
  160.       mHand[0]->GetFamVal(fam, valHidden);
  161.       // this is the value of the points on the table (without hidden card)
  162.       double valTable = mPoints - ((valHidden > 7) ? 0.5 : valHidden);
  163.       // this is the value that Pc estimates
  164.  
  165.       // there are 12 cards on the total of 40 with 0.5 points, so mEstimatedCard must know it!
  166.       srand(time( NULL ) );
  167.       int randEstim;
  168.       randEstim = rand()%40;         
  169.       if (randEstim < 12)
  170.          valEstimated = 0.5 + valTable;
  171.       else
  172.          valEstimated = mEstimatedCard + valTable;
  173.       // if on the table there are 6.5 points
  174.       // the Pc knows exactly the real points!
  175.       // (if we had 7.5 points we had to declare it for the rule!)
  176.       if (valTable == 6.5)
  177.          valEstimated = mPoints;
  178.       else
  179.       // if points are 7.5 the rule says that we have to declare it
  180.       // so the Pc will know exactly the points.
  181.       // And if Pc estimated more than 7.5 points, we have to correct it!
  182.       if (valEstimated > 7.0)
  183.          valEstimated = 7.0;
  184.    }
  185.    return valEstimated;
  186. }
  187.  
  188. void CPlayerNapoletano::ResetHand()
  189. {
  190.    if (!mHand.empty())
  191.    {
  192.       static unsigned int count = 1;   
  193.       int fam, valHidden;
  194.       mHand[0]->GetFamVal(fam, valHidden);
  195.       count++;
  196.       // average estimation of hidden card
  197.       mEstimatedCard = ((count-1)*mEstimatedCard + valHidden) / count;
  198.       mJollyValue = 0.0;
  199.       mPoints = 0.0;
  200.       mHand.erase(mHand.begin(), mHand.end());
  201.    }
  202. }
  203.  
  204. int GameNapoletano::Try(CPlayer *pp)
  205. {
  206.    int gameResult = game::GAME_OK;
  207.    if (!dn.GiveMeACard((const CGameCard* &)pCard))
  208.    {
  209.       Reshuffle();
  210.       dn.GiveMeACard((const CGameCard* &)pCard);
  211.    }
  212.    gameResult = pp->AddCard((CGameCard *)pCard);
  213.    pp->AddHand((CGameCard *)pCard);
  214.    return gameResult;
  215. }
  216.  
  217. GameNapoletano::GameNapoletano()
  218. {
  219.    pMe = new CPlayerNapoletano("Maurus");
  220.    pPc = new CPlayerNapoletano("Pc");
  221.    Init();
  222. }
  223.  
  224. void GameNapoletano::Init()
  225. {
  226.    dn.ShuffleDeck();
  227.    gameResult = game::GAME_OK;
  228.    pCard = NULL;
  229. }
  230.  
  231. void GameNapoletano::Reshuffle()
  232. {
  233.    dn.Reshuffle(mOutCards);
  234.    mOutCards.erase(mOutCards.begin(), mOutCards.end());
  235.    Init();
  236. }
  237.  
  238. void GameNapoletano::ResetPoints()
  239. {
  240.    pPc->SetPoints(0.0);
  241.    pMe->SetPoints(0.0);
  242. }
  243.  
  244. int GameNapoletano::Play(int who)
  245. {
  246.    if (who == game::ME)
  247.       gameResult = Try(pMe);
  248.    else
  249.    {
  250.       gameResult = Try(pPc);
  251.       if (gameResult != game::GAME_LOST)
  252.       {
  253.          // Pc has 7.5, so it wins!
  254.          if (pPc->GetPoints() > 7.0) 
  255.                gameResult = game::GAME_WON;
  256.          else
  257.          // Pc estimates to have more than Me
  258.          if (pPc->GetPoints() >= pMe->GetEstimatedPoints())
  259.          {
  260.             // this is the real result!
  261.             if (pPc->GetPoints() >= pMe->GetPoints())
  262.                gameResult = game::GAME_WON;
  263.             else
  264.                gameResult = game::GAME_LOST;
  265.          }
  266.       }
  267.    }
  268.    if ((gameResult == game::GAME_LOST) || (gameResult == game::GAME_WON))
  269.    {
  270.       // we save all the cards in hand, to the mOutCards vector
  271.       // because we need to know them, when we have to reshuffle the deck
  272.       for(VecPCards::iterator it1 = pMe->mHand.begin(); it1 != pMe->mHand.end(); it1++)
  273.          mOutCards.push_back(*it1);     
  274.       for(VecPCards::iterator it2 = pPc->mHand.begin(); it2 != pPc->mHand.end(); it2++)
  275.          mOutCards.push_back(*it2);     
  276.       pMe->ResetHand();
  277.       pPc->ResetHand();
  278.    }
  279.    return gameResult;
  280. }
  281.  
  282.  
  283.