📄 buraco.cpp
字号:
// Add reserve sort (reserve[player & 1].begin (), reserve[player & 1].end (), compByNumberWithJokers); for (std::vector<CardWidget*>::reverse_iterator i (reserve[player & 1].rbegin ()); i != reserve[player & 1].rend (); ++i) hands[player].insert (**i, 0); reserve[player & 1].clear (); if (!player) for (unsigned int i (0); i < hands[player].size (); ++i) { enableCard (i); registerHandDND (i); } Check3 (actPlayers.size () > player); Check3 (actPlayers[player]); // If the computer-player had jokers left, show them if (player && cJokers) { TRACE3 ("Buraco::addBuraco (unsigned int) - Jokers: " << cJokers); for (ICardPile::iterator i (hands[player].begin () + 11); i != hands[player].end (); ++i) { (*i)->showFace (); hands[player].resize (**i, ICardPile::COMPRESSED); } hands[player].resize (10 + cJokers, ICardPile::NORMAL); Glib::signal_timeout ().connect (bind (sigc::ptr_fun (&Buraco::hideJoker), &hands[player], cJokers), ComputerPlayer::TIMEOUT - 30); } status.pop (); Glib::ustring stat (_("%1 picked up the burraco")); stat.replace (stat.find ("%1"), 2, actPlayers[player]->getName ()); status.push (stat); updateInfo ();}//-----------------------------------------------------------------------------/// Hides the joker, which are displayed when picking up the buraco/// \param pile: Pile holding the jokers shown/// \param cJokers: Numer of jokers shown/// \returns bool: false//-----------------------------------------------------------------------------bool Buraco::hideJoker (ICardPile* pile, unsigned int cJokers) { TRACE9 ("Buraco::hideJoker (ICardPile&, unsigned int) - " << cJokers); Check1 (pile); Check1 (cJokers); Check1 (cJokers < pile->size ()); for (ICardPile::iterator i (pile->begin () + 11); i != pile->end (); ++i) { (*i)->showBack (); pile->resize (**i, ICardPile::VERY_COMPRESSED); } pile->resize (10 + cJokers, ICardPile::NORMAL); return false;}//-----------------------------------------------------------------------------/// Makes a new pile for the passed team./// \param team: Which team to make the pile for/// \returns BuracoPile&: New created pile//-----------------------------------------------------------------------------BuracoPile& Buraco::makeNewPile (unsigned int team) { TRACE9 ("Buraco::makeNewPile (unsigned int) - New pile for team " << team + 1); Check1 (team < (sizeof (boxTeam) / sizeof (boxTeam[0]))); Check1 (team < (sizeof (tablePiles) / sizeof (tablePiles[0]))); BuracoPile* pile (new BuracoPile ()); tablePiles[team].push_back (pile); boxTeam[team].pack_start (*pile, Gtk::PACK_SHRINK, 5); pile->show (); return *pile;}//-----------------------------------------------------------------------------/// Checks if the passed card can be put on one of the existing piles/// \param player: Player to inspect/// \param iCard: Card to inspect/// \returns Value describing the pile (and the offset of the card) to play/// to; -1 if none/// \remarks This method moves the card//-----------------------------------------------------------------------------unsigned int Buraco::cardFitsOnPlayedPile (unsigned int player, unsigned int iCard) { TRACE8 ("Buraco::cardFitsOnPlayedPile (unsigned int, unsigned int) - " "Card " << iCard << " of player " << player); Check1 (player); Check1 (player < NUM_PLAYERS); Check1 (iCard < hands[player].size ()); CardWidget& card (*hands[player][iCard]); TRACE3 ("Buraco::cardFitsOnPlayedPile (unsigned int, unsigned int) - Card " << card); unsigned int bestPile (-1U); unsigned int maxPoints (0); unsigned int size (0); for (std::vector<BuracoPile*>::iterator p (tablePiles[player & 1].begin ()); p != tablePiles[player & 1].end (); ++p) { TRACE5 ("Buraco::cardFitsOnPlayedPile (unsigned int, unsigned int) - " "Checking pile " << (int)(p - tablePiles[player & 1].begin ())); Check3 (*p); if ((*p)->size () == 7) { // Skip finished piles Check3 (!(*p)->is_visible ()); continue; } Check3 ((*p)->size () >= 3); Check3 ((*p)->size () < 7); // Play joker, if you can make a cerrado (7 in a row) - but only if the // one having picked up the reserve already played (the missing card // might be in there) and the oponent can't finish. And of course not, // if you have 7 monos in your hand! int posPile ((*p)->size ()); if (isJoker (card) ? (((((*p)->size () == 6) && ((*p)->getPosJoker () > 6)) && ((hands[player].size () - iCard) < 7) && (((reserve[player & 1].empty () && (((player & 1) ? gStatus.team2Buraco : gStatus.team1Buraco == 0x3))) || (points[player & 1] > 100)) || reserve[!(player & 1)].empty () || (points[!(player & 1)] > 100))) || (((*p)->size () > 2) && ((*p)->getPosFirst () > 6))) : ((posPile = cardFitsOnPile (p - tablePiles[player & 1].begin (), card)) != -1)) { // Always play on a joker pile (don't bother checking for a second one) if ((*p)->getPotentialPoints () >= 1000) { bestPile = p - tablePiles[player & 1].begin (); break; } if ((size < (*p)->size ()) || ((size == (*p)->size ()) && (maxPoints < (*p)->getPotentialPoints ()))) { size = (*p)->size (); maxPoints = (*p)->getPotentialPoints (); bestPile = p - tablePiles[player & 1].begin (); } } } if (bestPile != -1U) { unsigned int pos (0), move (-1U); BuracoPile& pile (*tablePiles[player & 1][bestPile]); Check3 (pile.getPosition4Card (card, pos, move)); pile.getPosition4Card (card, pos, move); Check3 (pos <= pile.size ()); if ((move != -1U) && canDumpCards (player, 1, ((int)target) >> 16)) { Check3 (move <= pile.size ()); Check3 (move != pile.getPosJoker ()); Check3 (pile.getPosJoker () != 7); sendMoveCard (bestPile, pile.getPosJoker (), move); pile.move (move, pile.getPosJoker ()); } pos1Play = pos2Play = iCard; return (bestPile << 16) + pos; } return -1U;}//-----------------------------------------------------------------------------/// Checks if the passed card is a joker/// \param card: Card to inspect/// \returns \c True if card is a joker//-----------------------------------------------------------------------------bool Buraco::isJoker (const CardWidget& card) { return ((card.number () == CardWidget::TWO) || (card.number () > CardWidget::ACE));}//-----------------------------------------------------------------------------/// Removes a cerrado (a pile with 7 cards) from the table/// \param player: Player causing the remove of the pile/// \param pile: Pile holding the cerrado//-----------------------------------------------------------------------------void Buraco::removeCerrado (unsigned int player, BuracoPile& pile) { unsigned int team (player & 1); Check1 (player < NUM_PLAYERS); Check1 ((std::find (tablePiles[team].begin (), tablePiles[team].end (), &pile)) != tablePiles[team].end ()); TRACE9 ("Buraco::removeCerrado (unsigned int, BuracoPile&) - Pile " << (std::find (tablePiles[team].begin (), tablePiles[team].end (), &pile) - tablePiles[team].begin ()) << " of team " << team); Check2 (pile.size () == 7); pile.hide (); Check3 (static_cast<int> (pile.getPotentialPoints ()) == pile.getPoints ()); points[team] += pile.getPoints (); if (pile.getPoints () > 999) --unfinishedMonoPiles[team]; updateInfo ();}//-----------------------------------------------------------------------------/// Actualizes the info-part of the statusbar//-----------------------------------------------------------------------------void Buraco::updateInfo () { Glib::ustring strInfo (_("Points [Buraco]: %1 [%2] / %3 [%4]")); strInfo.replace (strInfo.find ("%1"), 2, YGP::ANumeric::toString (points[0])); strInfo.replace (strInfo.find ("%2"), 2, (reserve[0].empty () ? _("N") : _("Y"))); strInfo.replace (strInfo.find ("%3"), 2, YGP::ANumeric::toString (points[1])); strInfo.replace (strInfo.find ("%4"), 2, (reserve[1].empty () ? _("N") : _("Y"))); info.set_text (strInfo);}//-----------------------------------------------------------------------------/// Checks if the passed card fits on the passed staple/// \param iPile: Pile to inspect/// \param card: Card to check/// \returns Position where card can be played to, or -1 if card does not fit//-----------------------------------------------------------------------------int Buraco::cardFitsOnPile (unsigned int iPile, const CardWidget& card) const { Check1 (iPile < tablePiles[currentPlayer () & 1].size ()); BuracoPile& pile (*tablePiles[currentPlayer () & 1][iPile]); Check2 (pile.size ()); Check2 (pile.size () < 7); // Card played on a joker: Valid is: // - A joker; if there are at least 3 jokers (on table + in hand) // - Any card, which has a pair (if there's only one joker on the table) if (pile.getPosFirst () > 6) if (pile.getPosJoker ()) return isJoker (card) ? 0 : -1; else { ICardPile::const_iterator pCard (hands[currentPlayer ()].getFittingCard (card, &cardDistance)); if (*pCard == &card) pCard = hands[currentPlayer ()].getFittingCard (card, ++pCard, &cardDistance); return pCard == hands[currentPlayer ()].end () ? -1 : 0; } unsigned int pos, move; if (pile.getPosition4Card (card, pos, move)) { Check3 (pos <= pile.size ()); if ((pile.size () > 1) || isJoker (card)) return pos; else { const CardHPile& hand (hands[currentPlayer ()]); if (!containsNoJoker (hand)) return pos; CardWidget& pileCard (*pile[pile.getPosFirst ()]); int dist (cardDistance (pileCard, card)); Check3 ((dist > -2) && (dist < 2)); int cmp (0); ICardPile::const_iterator pCard (hand.begin ()); do { pCard = hand.getFittingCard (pileCard, pCard, &cardDistance); if (*pCard == &card) pCard = hand.getFittingCard (pileCard, ++pCard, &cardDistance); if (pCard == hand.end ()) return -1; TRACE8 ("Buraco::cardFitsOnPile (unsigned int, const CardWidget&) const - " "Dist: " << dist << "<->" << cardDistance (**pCard, card)); cmp = dist - cardDistance (**pCard, card); ++pCard; } while ((cmp != -dist) & (cmp != (dist << 1))); return pos; } } return -1;}//----------------------------------------------------------------------------/// Sends a move-message to the connected machines/// \param pile: Number of pile involved/// \param from: Card to move/// \param to: Position card to move to//----------------------------------------------------------------------------void Buraco::sendMoveCard (unsigned int pile, unsigned int from, unsigned int to) const { TRACE8 ("Buraco::sendMoveCard (3x unsigned int) - Pile " << pile << ' ' << from << "->" << to); if (getConnectionMgr ().getMode () != YGP::ConnectionMgr::NONE) { // Send played card to all clients (if any) std::ostringstream msg; msg << "Move=" << from << ";To=" << to << ";Pile=" << pile; if (getConnectionMgr ().getMode () == YGP::ConnectionMgr::CLIENT) const_cast<Buraco*> (this)->ignoreNextMsg = true; broadcastMessage (msg.str ()); }}//-----------------------------------------------------------------------------/// Shows or hides the cards of the computer player/// \param open: Flag if cards should be shown or hidden//-----------------------------------------------------------------------------void Buraco::playOpen (bool open) { for (unsigned int i (1); i < NUM_PLAYERS; ++i) { hands[i].setShowOption (open ? ICardPile::SHOWFACE : ICardPile::SHOWBACK); hands[i].setStyle (open ? ICardPile::COMPRESSED : ICardPile::QUITE_COMPRESSED); }}//-----------------------------------------------------------------------------/// Creates the combined team names from the players/// \param names: Array to receive groups//-----------------------------------------------------------------------------void Buraco::makeTeamNames (std::vector<Player*>& names) const { Check1 (actPlayers.size () >= NUM_PLAYERS); // First delete old names for (unsigned int i (0); i < names.size (); ++i) delete names[i]; names.clear (); // ... then create it new with pair 0/2; 1/3 for (unsigned int i (0); i < (NUM_PLAYERS >> 1); ++i) { Glib::ustring name (_("Team %1\n%2/%3")); name.replace (name.find ("%1"), 2, 1, char ('1' + i)); name.replace (name.find ("%2"), 2, actPlayers[i]->getName ()); name.replace (name.find ("%3"), 2, actPlayers[i + 2]->getName ()); TRACE8 ("Buraco::makeTeamNames (std::vector<Player*>) - Add: " << name); names.push_back (new Human (name)); }}//-----------------------------------------------------------------------------/// Performs the steps to end the game//-----------------------------------------------------------------------------void Buraco::endGame () { TRACE8 ("Buraco::endGame ()"); if (!currentPlayer ()) disableHuman (); if (!pScoreDlg) { pScoreDlg = ScoreDlg::create (nameTeams); pScoreDlg->get_w
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -