📄 machiavelli.cpp
字号:
//-----------------------------------------------------------------------------void Machiavelli::getDropData (const Glib::RefPtr<Gdk::DragContext>& pContext, Gtk::SelectionData& data, guint, guint32 time, unsigned int cardPos) { Check1 (pContext->get_is_source ()); data.set (data.get_target (), 8, reinterpret_cast <guchar*> (&cardPos), sizeof (cardPos));}//-----------------------------------------------------------------------------/// 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 Machiavelli::cardDroppedOnTable (const Glib::RefPtr<Gdk::DragContext>& context, gint, gint, const Gtk::SelectionData& data, guint info, guint32 time, unsigned int iCard) { TRACE1 ("Machiavelli::cardDroppedOnTable (...) - Card dropped on " << std::hex << (int)iCard << std::dec << "; " << info); Check1 (!context->get_is_source ()); Check1 (data.get_length () == sizeof (int)); Check1 (data.get_format () == 8); Check1 ((info == HAND) || (info == TABLE)); unsigned int* pValue (reinterpret_cast <unsigned int*> (const_cast<guint8*> (data.get_data ()))); TRACE1 ("Machiavelli::cardDroppedOnTable (...) - Inserting card " << std::hex << *pValue << std::hex << " in pile"); Check2 (pValue); unsigned int nrpile (*pValue >> 8); unsigned int off (*pValue & 0xff); Check2 ((info == HAND) ? (off < hands[0].size ()) : (nrpile < tablePiles.size () && (off < tablePiles[nrpile]->size ()))); // Move dropped card to a (new) pile on the table unsigned int iPile (0); MachiPile* pile (NULL); ICardPile& src ((info == HAND) ? hands[0] : *tablePiles[nrpile]); CardWidget* moved (src[off]); unsigned int nr (((info == HAND) || (tablePiles[nrpile]->getType () == MachiPile::NUMBER)) ? 1 : (src.size () - off)); TRACE4 ("Machiavelli::cardDroppedOnTable (...) - Card dropped: " << *moved); if (iCard == -1U) { // If card was dropped on the new label: Create pile iPile = tablePiles.size (); pile = &makeNewPile (); iCard = 0; } else { // Else check pile to use iPile = iCard >> 8; // Ignore dnd from a pile to itself if ((info == TABLE) && (iPile == nrpile)) { context->drag_finish (true, false, time); return; } Check1 (iPile < tablePiles.size ()); pile = tablePiles[iPile]; iCard = pile->getPosition4Card (*moved); if (iCard == -1U) { context->drag_finish (true, false, time); Gtk::MessageDialog dlg (_("This card does not fit on that pile!"), Gtk::MESSAGE_ERROR); dlg.set_title (_("Invalid move")); dlg.run (); return; } if (info == TABLE) { // Move only one card from/to a numbered pile if ((pile->getType () == MachiPile::NUMBER) || ((pile->getType () == MachiPile::UNDEFINED) ? ((pile->size () == 1) && ((*pile)[0]->number () == moved->number ())) : !iCard) || (tablePiles[nrpile]->getType () == MachiPile::NUMBER)) nr = 1; // Check if only cards from an edge are moved to the beginning of // a coloured pile or a numbered pile if ((tablePiles[nrpile]->getType () == MachiPile::COLOUR) && (((off + 1) != src.size ()) && off) && ((iCard != pile->size ()) || (pile->getType () == MachiPile::NUMBER))) { context->drag_finish (true, false, time); Gtk::MessageDialog dlg (_("Card is not on the edge of the origen - try splitting the origin first!"), Gtk::MESSAGE_ERROR); dlg.set_title (_("Invalid move")); dlg.run (); return; } } } Check3 (pile); // End old drag context->drag_finish (true, false, time); // Store undo-info 4 Bytes: Target-pile, target-card, source-pile, // source-card; if played from hand, set source-pile to 0xff undoValue val (iPile, iCard, (info == HAND) ? 0xff : nrpile, off, nr); // Send move if (getConnectionMgr ().getMode () != YGP::ConnectionMgr::NONE) { std::ostringstream msg; if (info == HAND) msg << "Play=" << src[off]->id (); else msg << "Reorder=" << ((nr << 16) + (nrpile << 8) + off); msg << ";Target=" << (iPile << 16) + iCard; if (info ==TABLE) msg << ";Now=1"; if (getConnectionMgr ().getMode () == YGP::ConnectionMgr::CLIENT) ++ignoreNextMsg; broadcastMessage (msg.str ()); } while (nr--) { TRACE9 ("Machiavelli::cardDroppedOnTable (...) - Insert to: " << iPile << "; Pos: " << iCard); Check3 (iCard != -1U); // Unregister old card src.remove (off); (info == HAND) ? unregisterHandDND (*moved) : unregisterTableDND (*moved); // Insert card into pile and register it for DND Check3 (iCard <= pile->size ()); pile->insert (*moved, iCard); registerTableDND (*moved, (iPile << 8) + iCard); if (iCard < (pile->size () - 1)) registerTableDND (iPile, iCard + 1, pile->size () - 1); moved = src[off]; iCard++; } if (hands[0].empty ()) { YGP::StatusObject obj; checkPiles (obj); if (obj.getType () == YGP::StatusObject::UNDEFINED) { unsigned int nextPlayer (findNextPlayer (0)); if (nextPlayer == findNextPlayer (nextPlayer)) { endGame (nextPlayer); disableHuman (); return; } } } if (info == TABLE) { if (src.empty ()) { // Pile moved completely? std::vector<MachiPile*>::iterator i (tablePiles.begin () + nrpile); Check3 (*i == &src); tablePiles.erase (i); delete &src; val.create = true; if (nrpile > iPile) nrpile = iPile; // Re-register the following piles while (nrpile < tablePiles.size ()) { registerTableDND (nrpile, 0, tablePiles[nrpile]->size () - 1); ++nrpile; } } else { for (MachiPile::iterator i (tablePiles[nrpile]->begin ()); i != tablePiles[nrpile]->end (); ++i) { unregisterTableDND (**i); registerTableDND (**i, (nrpile << 8) + i - tablePiles[nrpile]->begin ()); } } } // Re-register the cards in the hand of the human for DND if ((info ==HAND) && *pValue < hands[0].size ()) registerHandDND (*pValue, hands[0].size () - 1); Check3 (aDNDHand.size () == hands[0].size ()); undo.push (val); undo1->set_sensitive (true); undoAll->set_sensitive (true);}//----------------------------------------------------------------------------/// Finds the next player still having cards/// \param player: Player to find next player to/// \return unsigned int: Next player having cards/// \remarks We assume (without really checking), that there's a next player.//----------------------------------------------------------------------------unsigned int Machiavelli::findNextPlayer (unsigned int player) const { for (unsigned int i (0); i < NUM_PLAYERS; ++i) { player = (player + 1) & 0x3; if (hands[player].size ()) { TRACE8 ("Machiavelli::findNextPlayer (unsigned int) const - Player: " << player); break; } } Check3 (player < NUM_PLAYERS); return player;}//-----------------------------------------------------------------------------/// Makes a new pile./// \returns MachiPile&: New created pile//-----------------------------------------------------------------------------MachiPile& Machiavelli::makeNewPile () { TRACE9 ("Machiavelli::makeNewPile ()"); MachiPile* pile (new MachiPile ()); pile->show (); piles.add (*pile); tablePiles.push_back (pile); TRACE9 ("Machiavelli::makeNewPile () - Pile " << tablePiles.size ()); return *pile;}//-----------------------------------------------------------------------------/// Makes a new pile in a certain position/// \param pos: Position of pile on the table/// \returns MachiPile&: New created pile//-----------------------------------------------------------------------------MachiPile& Machiavelli::makeNewPile (unsigned int pos) { TRACE9 ("Machiavelli::makeNewPile ()"); MachiPile* pile (new MachiPile ()); pile->show (); Check3 (pos <= tablePiles.size ()); piles.insert (*pile, pos); tablePiles.insert (tablePiles.begin () + pos, pile); return *pile;}//-----------------------------------------------------------------------------/// Searches the passed pile, if it has a serie of 3 or more. This method also/// \param playerPile: Pile to inspect/// \returns \c bool:/// \requires The pile must have at least 3 cards/// \remarks: Sets pos1Play and pos2Play, if a serie is found//-----------------------------------------------------------------------------bool Machiavelli::hasSerie (ICardPile& playerPile) { Check3 (playerPile.size () >= 3); // Check for 3 cards belonging to a serie for (unsigned int i (0); i < (playerPile.size () - 2); ++i) { TRACE8 ("Machiavelli::hasSerie (ICardPile&) - Analyzing card " << *playerPile[i]); std::map<unsigned int, unsigned int> aPos; // diff, pos std::vector<unsigned int> aOrder; unsigned int nrs (playerPile.getSeries (*playerPile[i], aPos, aOrder, &MachiPile::cardDistance, false)); // Play the bigger of the found matching cards, if there are >= 3 if ((nrs > aPos.size ()) ? (nrs > 2) : (aPos.size () > 2)) { if (nrs <= aPos.size ()) { i = playerPile.sortColourSerie (aPos, aOrder); nrs = aPos.size (); } pos1Play = i; pos2Play = i + nrs - 1; return true; } } return false;}//-----------------------------------------------------------------------------/// Searches for cards to play and shows them in the hand of the actual player/// \param player: Player to inspect/// \returns \c ID of the target (32 Bit: Pile << 16 + Position) or -1U;/// \remarks: - Sets pos1Play and pos2Play approbiatly/// - Creates a new pile if needed//-----------------------------------------------------------------------------unsigned int Machiavelli::cardFitsToPile (const CardWidget& card, unsigned int offset) { TRACE8 ("Machiavelli::cardFitsToPile (const CardWidget&, unsigned int) - Adding card " << card << '?'); unsigned int dest (-1U); for (std::vector<MachiPile*>::const_iterator m (tablePiles.begin ()); m != tablePiles.end (); ++m) { Check2 ((*m)->getType () != MachiPile::UNDEFINED); // Check if the card can be added to an existing pile dest = (*m)->getPosition4Card (card); if (dest != -1U) { pos1Play = pos2Play = offset; return ((m - tablePiles.begin ()) << 16) + dest; } // Or can the card be added by splitting the pile? int diff (MachiPile::cardDistance (card, *(**m)[0])); if (((*m)->getType () == MachiPile::COLOUR) ? ((diff < 0) || (card.colour () != (**m)[0]->colour ())) : diff) continue; int pos ((*m)->size () - static_cast<unsigned int> (diff)); TRACE8 ("Machiavelli::cardFitsToPile (const CardWidget&unsigned int) - Splitting " << (m - tablePiles.begin ()) << " at " << diff << " (" << pos << ")?"); // A new pile can be made directly (enough cards on both sides) if ((pos > 2) && (diff > 1)) { // Move cards to remove to hand (to be shown); The card from the // hand will be added in the next move ++diff; pos1Play = pos2Play = offset; posPiles.push_back ((((*m)->size () - diff) << 16) + ((m - tablePiles.begin ()) << 8) + diff); TRACE9 ("Machiavelli::cardFitsToPile (const CardWidget&unsigned int) - Marked pile: " << std::hex << pos2Play << std::dec); do { Check3 ((unsigned int)diff < (*m)->size ()); (**m)[diff]->mark (); } while (static_cast<unsigned int> (++diff) < (*m)->size ()); makeNewPile (); return (tablePiles.size () - 1) << 16; } } return -1U;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -