📄 buraco.cpp
字号:
/// \param card: Number of card where something was dropped at/// \pre \c pContext not NULL; Expects \c info to be 0//-----------------------------------------------------------------------------void Buraco::cardDropped (const Glib::RefPtr<Gdk::DragContext>& context, gint, gint, const Gtk::SelectionData& data, guint info, guint32 time, unsigned int card) { Check3 (!context->get_is_source ()); Check3 (data.get_length () == sizeof (int)); Check3 (data.get_format () == 8); Check3 (card < hands[0].size ()); unsigned int* pValue (reinterpret_cast <unsigned int*> (const_cast<guint8*> (data.get_data ()))); Check3 (pValue); Check3 (*pValue < hands[0].size ()); TRACE1 ("Buraco::cardDropped (...) - Inserting card " << *pValue << " at pos " << card); if (acceptCards != -1U) { context->drag_finish (false, false, time); Gtk::MessageDialog dlg (_("Can't move cards before completing the pile!"), Gtk::MESSAGE_ERROR); dlg.set_title (_("Invalid move")); dlg.run (); return; } context->drag_finish (true, false, time); // End old DND CardWidget& cardMoved (hands[0].remove (*pValue)); hands[0].insert (cardMoved, card); // Insert moved card // Adapt dnd-settigns if (*pValue < card) { unsigned int temp (card); card = *pValue; *pValue = temp; } // DND within hand directly after picking up the buraco disables undoing if (undo.pickUp) menuUndo->set_sensitive (false); Glib::signal_idle ().connect (bind (mem_fun (*this, &Buraco::doRegisterHand), card, *pValue));}//-----------------------------------------------------------------------------/// Checks if the piles on the table are valid (have at least 3 cards)/// \param except: Pile which can be invalid/// \returns \c True, if the piles are OK//-----------------------------------------------------------------------------bool Buraco::doRegisterHand (unsigned int first, unsigned int last) { TRACE9 ("Buraco::doRegisterHand (unsigned int, unsigned int) - [" << first << '-' << last); Check1 (last < hands[0].size ()); Check1 (first <= last); registerHandDND (first, last); Check3 (aDNDHand.size () == hands[0].size ()); return false;}//-----------------------------------------------------------------------------/// Checks if the piles on the table are valid (have at least 3 cards)/// \param except: Pile which can be invalid/// \returns \c True, if the piles are OK//-----------------------------------------------------------------------------bool Buraco::humanPilesOK (unsigned int except) const { for (std::vector<BuracoPile*>::const_iterator p (tablePiles[0].begin ()); p != tablePiles[0].end (); ++p) { Check3 (*p); Check3 (((*p)->size () < 7) || !(*p)->is_visible ()); if ((p - tablePiles[0].begin ()) == static_cast<int> (except)) continue; if ((*p)->size () < 3) return false; } return true;}//-----------------------------------------------------------------------------/// Callback after dropping a card on the table/// \param pContext: Context of the drag (contains things like source,/// \param target, action, ...)/// \param data: Describes the thing which was dropped/// \param info: Describes the type of data (should be 0)/// \param time: Timestamp of the drag/// \param iCard: Combination of card and pile on which card was dropped/// \pre \c pContext not NULL;//-----------------------------------------------------------------------------void Buraco::cardDroppedOnTable (const Glib::RefPtr<Gdk::DragContext>& context, gint, gint, const Gtk::SelectionData& data, guint, guint32 time, unsigned int iCard) { TRACE1 ("Buraco::cardDroppedOnTable (...) - Card dropped on " << std::hex << (int)iCard << std::dec); Check3 (!context->get_is_source ()); Check3 (data.get_length () == sizeof (int)); Check3 (data.get_format () == 8); unsigned int* pValue (reinterpret_cast <unsigned int*> (const_cast<guint8*> (data.get_data ()))); Check3 (pValue); TRACE1 ("Buraco::cardDroppedOnTable (...) - Inserting card " << *pValue << " in pile"); Check3 (*pValue < hands[0].size ()); try { // Check if all piles (except those to which card is dropped) are valid if (!humanPilesOK (iCard >> 8)) throw Glib::ustring (_("You need to fill up other piles first!")); CardWidget& moved (*hands[0][*pValue]); TRACE4 ("Buraco::cardDroppedOnTable (...) - Card dropped: " << moved); if ((acceptCards != -1U) && isJoker (moved) || (*pValue >= acceptCards)) throw Glib::ustring (_("You must play your cards (without \"monos\"), when you picked up the pile!")); // Move dropped card to a (new) pile on the table unsigned int iPile; BuracoPile* pile (NULL); if (iCard == -1U) { // If card was dropped on the new pile: Create pile // Check validity of drop if (!(isJoker (moved) ? pileHasFittingPair (hands[0], &moved) : pileHasFittingPair (hands[0], moved, acceptCards == -1U))) throw Glib::ustring (_("There are no cards to make a valid new pile!")); // Only allow dropping on new pile while having < 5 cards, if the game // can be ended, or there is still the reserve if (!canDumpCards (0, 3)) throw Glib::ustring (_(*unfinishedMonoPiles ? N_("You can't end the game (a pile of monos is not finished)!") : ((hands[0].size () <= 5) ? N_("You can't end the game (there's no \"cerrado\")!") : N_("Not enough cards to make new pile!")))); iPile = tablePiles[0].size (); pile = &makeNewPile (0); Check3 (tablePiles[0].size ()); iCard = 0; } else { // Else check pile to use Check1 ((iCard >> 8) < tablePiles[0].size ()); pile = tablePiles[0][iPile = (iCard >> 8)]; if ((iCard = cardFitsOnPile (iPile, moved)) == -1U) throw Glib::ustring (_("This card does not fit on that pile!")); // Only allow dropping of last card, if the game can be ended, or there // is still the reserve if (!canDumpCards (0, 1, iPile)) throw Glib::ustring (_("You can't end the game (there's no \"cerrado\")!")); if ((pile->size () == 1) && isJoker (pile->getTopCard ()) && isJoker (moved)) ++unfinishedMonoPiles[0]; } // End old drag context->drag_finish (true, false, time); activeCards[*pValue].disconnect (); activeCards.erase (activeCards.begin () + *pValue); // Unregister old card hands[0].remove (*pValue); unregisterHandDND (moved); // Insert card into pile and register it for DND unsigned int move (-1U); pile->getPosition4Card (moved, iCard, move); Check3 (iCard <= pile->size ()); TRACE4 ("Buraco::cardDroppedOnTable (...) - Undo: " << iPile << "; " << iCard << "; " << *pValue << ": " << acceptCards << '/' << pile->getPosJoker ()); undo.assign (iPile, iCard, *pValue, acceptCards); menuUndo->set_sensitive (); if (move != -1U) { Check3 (move <= pile->size ()); Check3 (move != pile->getPosJoker ()); Check3 (pile->getPosJoker () != 7); undo.monoPos = pile->getPosJoker (); sendMoveCard (iPile, pile->getPosJoker (), move); pile->move (move, pile->getPosJoker ()); } // Send move if (getConnectionMgr ().getMode () != YGP::ConnectionMgr::NONE) { std::ostringstream msg; msg << "Play=" << moved.id () << ";Target=" << (iPile << 16) + iCard + 100; if (getConnectionMgr ().getMode () == YGP::ConnectionMgr::CLIENT) ignoreNextMsg = true; broadcastMessage (msg.str ()); } pile->insert (moved, iCard); registerTableDND (moved, (iPile << 8) + iCard); if (iCard < (pile->size () - 1)) registerTableDND (iPile, iCard + 1, pile->size () - 1); // Remove pile, if it contains 7 cards if (pile->size () == 7) removeCerrado (0, *pile); // Accept again the jokers, if the pile has has now three cards (jokers are // disabled, if the human picked up the dumped pile. if (pile->size () == 3) { acceptCards = -1U; menuSort->set_sensitive (); menuSort2->set_sensitive (); } else if (acceptCards != -1U) --acceptCards; // If the player has no more cards left (except of joker): Give him the reserve if (containsOnlyJoker (hands[0]) && humanPilesOK ()) if (!reserve[0].empty ()) { addBuraco (0); return; } else if (hands[0].empty ()) { points[0] += 100; endGame (); return; } // Re-register the cards in the hand of the human for DND if (*pValue < hands[0].size ()) registerHandDND (*pValue, hands[0].size () - 1); Check3 (aDNDHand.size () == hands[0].size ()); } catch (Glib::ustring& error) { context->drag_finish (false, false, time); Gtk::MessageDialog dlg (error, Gtk::MESSAGE_ERROR); dlg.set_title (_("Invalid move")); dlg.run (); return; }}//-----------------------------------------------------------------------------/// Callback to query the data to drop/// \param pContext: Context of the drag (contains things like source,/// \param target, action, ...)/// \param data: Describes the thing which was dropped/// \param time: Timestamp of the drag/// \param cardPos: Position of card (either in hand or pile on table)/// \pre \c pContext not NULL; Expects \c info to be 0//-----------------------------------------------------------------------------void Buraco::getDropData (const Glib::RefPtr<Gdk::DragContext>& pContext, Gtk::SelectionData& data, guint info, guint32 time, unsigned int cardPos) { Check1 (!info); Check1 (pContext->get_is_source ()); data.set (data.get_target (), 8, reinterpret_cast <guchar*> (&cardPos), sizeof (cardPos));}//-----------------------------------------------------------------------------/// Prepares the passed region of cards for drag磏磀rop/// \param start: Number of first card to prepare for DND/// \param end: Number of last card to prepare for DND/// \pre \c start < \c end; \c end <= Nr. ofcards//-----------------------------------------------------------------------------void Buraco::registerHandDND (unsigned int start, unsigned int end) { TRACE5 ("Buraco::registerHandDND (unsigned int, unsigned int) - [" << start << '-' << end << ']'); Check1 (start <= end); Check1 (end < hands[0].size ()); Check1 (end < activeCards.size ()); for (; start <= end; ++start) { TRACE9 ("Buraco::registerHandDND (unsigned int, unsigned int) - Handling card " << start); activeCards[start].disconnect (); activeCards[start] = hands[0][start]->signal_clicked ().connect (bind (mem_fun (*this, (&Buraco::cardSelected)), start)); unregisterHandDND (*hands[0][start]); registerHandDND (start); } TRACE9 ("Buraco::registerHandDND (unsigned int, unsigned int) - End ");}//-----------------------------------------------------------------------------/// Checks, if the passed pile contains no cards except jokers or 2s. This is/// also true for empty piles./// \param pile: Pile to inspect/// \returns \c True, if there are only jokers (or pile is empty)//-----------------------------------------------------------------------------bool Buraco::containsOnlyJoker (const std::vector<CardWidget*>& pile) { TRACE8 ("Buraco::containsOnlyJoker (const std::vector<CardWidget*>&"); for (std::vector<CardWidget*>::const_iterator i (pile.begin ()); i != pile.end (); ++i) { Check3 (*i); if (!isJoker (**i)) return false; } return true;}//-----------------------------------------------------------------------------/// Checks, if the passed pile does not contain neither jokers nor 2s./// \param pile: Pile to inspect/// \returns \c True, if there are no jokers//-----------------------------------------------------------------------------bool Buraco::containsNoJoker (const std::vector<CardWidget*>& pile) { for (std::vector<CardWidget*>::const_iterator i (pile.begin ()); i != pile.end (); ++i) { Check3 (*i); if (isJoker (**i)) return false; } return true;}//-----------------------------------------------------------------------------/// Adds the buraco to the passed player./// \param player: Player getting the reserve//-----------------------------------------------------------------------------void Buraco::addBuraco (unsigned int player) { TRACE3 ("Buraco::addBuraco (unsigned int) - " << player); Check1 (player < NUM_PLAYERS); undo.pickUp = 1; unsigned int cJokers (hands[player].size ()); // Storing player picking up the buraco ((player & 1) ? gStatus.team2Buraco : gStatus.team1Buraco) = (player >> 1); // Disable the cards in the hand (if the human gets the cards) if (!player) { Game::disableHuman (); for (unsigned int i (0); i < hands[0].size (); ++i) unregisterHandDND (*hands[0][i]); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -