home *** CD-ROM | disk | FTP | other *** search
- /* **************************************************************************************
- File: Cards.cpp
- By Mauro Mindoli
-
- January 2003 ver. 1.0
-
- February 2003 : ver 2.0
- Corrected some bug and added new features to the code:
-
- @@ DONE
- @ Management of hidden card , the first one of the human player. Now Pc does not see it!
- @ New method CPlayerNapoletano::GetEstimatedPoints() that makes some pseudo A.I.
- @ Corrected GameNapoletano::Play() to insert an estimation of the points.
- @ Changed the bet edit box, now it is a combo box.
- @ Bet is now only allowed after the first (hidden) card, like in the real rules.
- @ Implemented a simple error checking when there are not bmp to load (before it simply crashed!)
- @ Introduced two txt files to read for Info and for Rules in the help dialog and its menu.
- @ Solved a memory leak for a bug in the distructor ~CDeckNapoletano: it deleted the wrong deck
- @ Added sound effects!
- @ Management of the "jolly" i.e. the 10 of gold that can change its value
- (0.5, 1, 2, ..., 7, but NOT 1.5, 4.5, ...), dinamically.
-
- ***************************************************************************************** */
- #include "stdafx.h"
- #include "cards.h"
-
- int CGameCard::GetIdCard()
- {
- return (mFam << 8) | mVal;
- }
-
- CDeck::CDeck(int numCards, int numFams) : mNumCards(numCards), mNumFams(numFams)
- {
- mCurPos = 0;
- }
-
- void CDeck::ShuffleDeck()
- {
- // the suffle is implemented by random swapping
- srand(time( NULL ) );
- int randcard;
- for (int ncard = 0; ncard < mNumCards; ncard++)
- {
- randcard = rand()%mNumCards;
- std::swap(shuffledDeck[ncard], shuffledDeck[randcard]);
- }
-
- }
-
- // The current card is taken from the Deck already shuffled by the mCurPos that is incremented
- bool CDeck::GiveMeACard(const CGameCard* &card)
- {
- if (mCurPos >= mNumCards)
- return false;
- else
- card = shuffledDeck[mCurPos++];
- return true;
- }
-
- CDeckNapoletano::CDeckNapoletano() : CDeck(NCARDS, NFAMS)
- {
- // init the Deck ordering it by values and familys
- int vCard;
- int vFam;
- mDeck.reserve(NCARDS);
- shuffledDeck.reserve(NCARDS);
- // we have to use mDeck to store the allocated pointers
- // to delete them in the distructor, and shuffledDeck
- // to play
- for (vFam = game::COPPE; vFam < game::END; vFam++)
- for (vCard = 1; vCard <= (mNumCards/mNumFams); vCard++)
- {
- CGameCardNapoletano *p = new CGameCardNapoletano(vFam, vCard);
- mDeck.push_back(p);
- shuffledDeck.push_back(p);
- }
- }
-
- CDeckNapoletano::~CDeckNapoletano()
- {
- VecPCards::iterator itCurCard = mDeck.begin();
- for (; itCurCard != mDeck.end(); itCurCard++)
- delete (*itCurCard);
- }
-
- // we reshuffle the deck when cards are ended
- // we cannot use the same original deck, because some card
- // are still in play, so we have to use outCards: the vector
- // with all cards played
- void CDeckNapoletano::Reshuffle(VecPCards &outCards)
- {
- mNumCards = outCards.size(); // mNumCard is <= 40 now
- shuffledDeck.erase(shuffledDeck.begin(), shuffledDeck.end());
- // we copy outCards in the shuffled Vector to restart the game
- for (VecPCards::iterator it = outCards.begin(); it != outCards.end(); it++)
- shuffledDeck.push_back(*it);
- // mCurPos has to be reset!
- mCurPos = 0;
- }
-
- CPlayer::CPlayer(std::string name) : mPoints(0.0), mName(name){}
-
- #include <math.h>
- int CPlayerNapoletano::AddCard(CGameCard *pCard)
- {
- int val, fam;
- pCard->GetFamVal(fam, val);
-
- // the card is the Jolly! Possible Jolly values are: 0.5, 1, 2, 3, 4, 5, 6, 7
- if ((fam == game::DENARI) && (val == 10))
- {
- // I want to check if I had a point with a decimal part or not:
- // if I have 3.5 points my jolly will be 4, if I have 4 points my jolly will be 3
- mJollyValue = (mPoints - floor(mPoints)) > 0 ? 7.5 - mPoints : 7.0 - mPoints;
- mPoints += mJollyValue;
- if (mJollyValue == 0.0)
- mJollyValue = mPoints; // Jolly was the first card
- }
- else // Jolly was already in hand
- if (mJollyValue)
- {
- mPoints = mPoints - mJollyValue + ((val > 7) ? 0.5 : val); // points without jolly
- if (mPoints < 7.5) // minimum Jolly value is 0.5
- mJollyValue = (mPoints - floor(mPoints)) > 0 ? 7.5 - mPoints : 7.0 - mPoints;
- mPoints += mJollyValue;
- }
- else // normal case
- mPoints += (val > 7) ? 0.5 : val;
-
- if (mPoints > 7.5)
- return game::GAME_LOST;
- else
- return game::GAME_OK;
- }
-
- void CPlayerNapoletano::AddHand(CGameCard *pCard)
- {
- mHand.push_back(pCard);
- }
-
- // ****************************************
- // * Artificial Intelligence Method!!!(?) *
- // ****************************************
- double CPlayerNapoletano::GetEstimatedPoints() const
- {
- double valEstimated = 0.0;
- // there is only the hidden card
- // so the Pc estimate the hidden card
- // basing (psychology!) on the average of the old hidden cards
- if (mHand.size() <= 1)
- valEstimated = mEstimatedCard;
- else
- // Pc must know (it's a rule) when we have 7.5 points
- if (mPoints == 7.5)
- valEstimated = 7.5;
- else
- {
- int fam, valHidden;
- // this is the hidden card, and pc must not know about it!
- mHand[0]->GetFamVal(fam, valHidden);
- // this is the value of the points on the table (without hidden card)
- double valTable = mPoints - ((valHidden > 7) ? 0.5 : valHidden);
- // this is the value that Pc estimates
-
- // there are 12 cards on the total of 40 with 0.5 points, so mEstimatedCard must know it!
- srand(time( NULL ) );
- int randEstim;
- randEstim = rand()%40;
- if (randEstim < 12)
- valEstimated = 0.5 + valTable;
- else
- valEstimated = mEstimatedCard + valTable;
- // if on the table there are 6.5 points
- // the Pc knows exactly the real points!
- // (if we had 7.5 points we had to declare it for the rule!)
- if (valTable == 6.5)
- valEstimated = mPoints;
- else
- // if points are 7.5 the rule says that we have to declare it
- // so the Pc will know exactly the points.
- // And if Pc estimated more than 7.5 points, we have to correct it!
- if (valEstimated > 7.0)
- valEstimated = 7.0;
- }
- return valEstimated;
- }
-
- void CPlayerNapoletano::ResetHand()
- {
- if (!mHand.empty())
- {
- static unsigned int count = 1;
- int fam, valHidden;
- mHand[0]->GetFamVal(fam, valHidden);
- count++;
- // average estimation of hidden card
- mEstimatedCard = ((count-1)*mEstimatedCard + valHidden) / count;
- mJollyValue = 0.0;
- mPoints = 0.0;
- mHand.erase(mHand.begin(), mHand.end());
- }
- }
-
- int GameNapoletano::Try(CPlayer *pp)
- {
- int gameResult = game::GAME_OK;
- if (!dn.GiveMeACard((const CGameCard* &)pCard))
- {
- Reshuffle();
- dn.GiveMeACard((const CGameCard* &)pCard);
- }
- gameResult = pp->AddCard((CGameCard *)pCard);
- pp->AddHand((CGameCard *)pCard);
- return gameResult;
- }
-
- GameNapoletano::GameNapoletano()
- {
- pMe = new CPlayerNapoletano("Maurus");
- pPc = new CPlayerNapoletano("Pc");
- Init();
- }
-
- void GameNapoletano::Init()
- {
- dn.ShuffleDeck();
- gameResult = game::GAME_OK;
- pCard = NULL;
- }
-
- void GameNapoletano::Reshuffle()
- {
- dn.Reshuffle(mOutCards);
- mOutCards.erase(mOutCards.begin(), mOutCards.end());
- Init();
- }
-
- void GameNapoletano::ResetPoints()
- {
- pPc->SetPoints(0.0);
- pMe->SetPoints(0.0);
- }
-
- int GameNapoletano::Play(int who)
- {
- if (who == game::ME)
- gameResult = Try(pMe);
- else
- {
- gameResult = Try(pPc);
- if (gameResult != game::GAME_LOST)
- {
- // Pc has 7.5, so it wins!
- if (pPc->GetPoints() > 7.0)
- gameResult = game::GAME_WON;
- else
- // Pc estimates to have more than Me
- if (pPc->GetPoints() >= pMe->GetEstimatedPoints())
- {
- // this is the real result!
- if (pPc->GetPoints() >= pMe->GetPoints())
- gameResult = game::GAME_WON;
- else
- gameResult = game::GAME_LOST;
- }
- }
- }
- if ((gameResult == game::GAME_LOST) || (gameResult == game::GAME_WON))
- {
- // we save all the cards in hand, to the mOutCards vector
- // because we need to know them, when we have to reshuffle the deck
- for(VecPCards::iterator it1 = pMe->mHand.begin(); it1 != pMe->mHand.end(); it1++)
- mOutCards.push_back(*it1);
- for(VecPCards::iterator it2 = pPc->mHand.begin(); it2 != pPc->mHand.end(); it2++)
- mOutCards.push_back(*it2);
- pMe->ResetHand();
- pPc->ResetHand();
- }
- return gameResult;
- }
-
-
-