📄 rovhult.cpp
字号:
Check3 (start != -1U); Check3 (players[player].hand[start]->number () == cardNuke); } TRACE7 ("Rovhult::findCard2Play (unsigned int) - Using special card " << players[player].hand[start] << " at pos " << start); } else { Check3 ((cardMin == cardReverse) ? (players[player].hand[start]->number () <= cardReverse) : (players[player].hand[start]->number () >= cardMin)); // If player would continue with a card coming directly // before cardReverse (6), but has also a cardReverse (7), // play that card instead if (players[player].hand[start]->number () == (cardReverse - 1)) { if ((end = players[player].hand.find (cardReverse, start)) != -1U) { TRACE8 ("Rovhult::findCard2Play (unsigned int) - Exchanging " << *players[player].hand[start] << " with " << *players[player].hand[end]); start = end; } } else // The search of CardWidget does not know (and shall not know anything) // about the special meaning of tens, so skip them by yourself, // but use a TWO (if available) in case a TEN is/are the last card(s) if ((end = skip (cardNuke, players[player].hand, start)) == -1U) { if (players[player].hand[0]->number () == CardWidget::TWO) start = 0; } else start = end; TRACE5 ("Rovhult::findCard2Play (unsigned int) - Playing " << *players[player].hand[start] << " at pos " << start); } // Now find the last of equal cards; get rid of all of them if: // - they would complete 4 // - there are are only special cards left // - it's not a special card which is // * not the highest card // * it's the first card // * it's a not that high card (up to 9) unsigned int last (players[player].hand.findLastEqual (start)); TRACE8 ("Rovhult::findCard2Play (unsigned int) - Last equal at pos " << last << " (of " << players[player].hand.size () << " cards)"); Check3 (last < players[player].hand.size ()); end = (((numberOfEqualTopCards () + last - start) == 3) || ((start ? existOnlySpecialCards (players[player].hand, 0, start - 1) : 1) && ((last < (players[player].hand.size () - 1)) ? existOnlySpecialCards (players[player].hand, last + 1, players[player].hand.size () - 1) : 1)) || ((!isSpecialCard (players[player].hand[start]->number ())) && ((last != (players[player].hand.size () - 1)) || !start || (players[player].hand[start]->number () < cardNuke)))) ? last : start; return; } else { TRACE5 ("Rovhult::findCard2Play (unsigned int) - Analyzing reserve"); // Bitfield for lower cards: Bit 0: Cards visible; Bit 1: Normal cards int bfLowerCardsInfo (0); // Play first visible cards for (start = 0; start < 3; ++start) { const ICardPile* pPile (&players[player].reserve[start]); if (pPile->size ()) { CardWidget& card (pPile->getTopCard ()); if (card.showsFace ()) { bfLowerCardsInfo |= 0x1; // If card can be played: Search for last equal card if (cardValid (card.number (), true)) { end = start; // Don't play all cards, if it is a special card and "normal" // cards remain if (!(isSpecialCard (card.number ()) && (bfLowerCardsInfo & 0x2))) while ((end < 2) && (pPile = &players[player].reserve[end + 1]) && pPile->size () && pPile->topCardShowsFace () && (pPile->getTopCard ().number () == card.number ())) ++end; if (!isSpecialCard (card.number ())) bfLowerCardsInfo |= 0x2; TRACE7 ("Rovhult::findCard2Play (unsigned int) - Playing " "visible card " << card << " at pos " << end); return; } } } } // No card visible: Play the first if (!bfLowerCardsInfo) { start = 0; while (!players[player].reserve[start].size ()) { ++start; Check3 (start < 3); } end = start; TRACE7 ("Rovhult::findCard2Play (unsigned int) - Playing invisible card " << players[player].reserve[end].getTopCard () << " at pos " << end); } }}//-----------------------------------------------------------------------------/// Retrieves the minimal and maximal card of the player/// \param player: Player whose card to analyze/// \param min: Returns the minimal card/// \param max: Returns the maximal card/// \returns \c bool: true, if cardinfo is available//-----------------------------------------------------------------------------bool Rovhult::getPileLimits (unsigned int player, CardWidget::NUMBERS& min, CardWidget::NUMBERS& max) const { if (players[player].hand.size ()) return false; TRACE3 ("Rovhult::getPileInfo (unsigned int, unsigned int&, unsigned int&)" " - Analyzing cards of player " << player); bool cardFound (false); for (unsigned int i (0); i < 3; ++i) { const ICardPile* pPile (&players[player].reserve[i]); if (pPile->size ()) { CardWidget& card (pPile->getTopCard ()); if (card.showsFace ()) { if (isSpecialCard (card.number ())) break; if (cardFound) max = card.number (); else { min = max = card.number (); cardFound = true; } } } } TRACE5 ("Rovhult::getPileInfo (unsigned int, unsigned int&, unsigned int&)" " - Limits found: " << int (cardFound ? min : -1) << '/' << int (cardFound ? max : -1)); return cardFound;}//-----------------------------------------------------------------------------/// Shows or hides the cards of the computer player/// \param open: Flag if cards should be shown or hidden//-----------------------------------------------------------------------------void Rovhult::playOpen (bool open) { ICardPile::ShowOpt show (open ? ICardPile::SHOWFACE : ICardPile::SHOWBACK); for (unsigned int i (1); i < NUM_PLAYERS; ++i) { players[i].hand.setShowOption (show); players[i].hand.setStyle ((show == ICardPile::SHOWFACE) ? ICardPile::COMPRESSED : ICardPile::QUITE_COMPRESSED); }}//-----------------------------------------------------------------------------/// End the current game as soon as possible//-----------------------------------------------------------------------------void Rovhult::end (bool restart) { if (gameStatus () == EXCHANGE) unregisterDND (); Game::end (restart);}//-----------------------------------------------------------------------------/// Changes the names of the playing people/// \param newPlayer: Array holding the new player//-----------------------------------------------------------------------------void Rovhult::changeNames (const std::vector<Player*>& newPlayer) { Game::changeNames (newPlayer); for (unsigned int i (0); i < NUM_PLAYERS; ++i) players[i].name.set_text (actPlayers[i]->getName ());}//----------------------------------------------------------------------------/// Converts a pile-number to the actual pile/// \param player: Actual player/// \param pile: ID of the pile to return/// - 0: Play from hand/// - 1 - 3: Play from pile 0 - 2/// - 4: Pick up played pile/// - 5 - 7: Tried to play from pile 0 - 2, but failed/// \returns ICardPile*: Pile corresponding to the passed number or NULL//----------------------------------------------------------------------------ICardPile* Rovhult::getPileOfPlayer (unsigned int player, unsigned int pile) { if ((player >= NUM_PLAYERS) || (pile > 7)) return NULL; TRACE8 ("Rovhult::getPileOfPlayer (unsigned int, unsigned int) - Player " << player << "; Pile " << pile); if (pile > 4) { ICardPile& playerPile (players[player].reserve[pile - 5]); Check3 (playerPile.size ()); if (cardValid (playerPile.getTopCard ().number (), true)) return &playerPile; else { played.append (playerPile.removeTopCard ()); return &played; } } return &(pile ? ((pile == 4) ? static_cast<ICardPile&> (played) : static_cast<ICardPile&> (players[player].reserve[pile - 1])) : static_cast<ICardPile&> (players[player].hand));}//----------------------------------------------------------------------------/// Handles the messages the server might send for the Rovhult cardgame/// \param player: ID of player sending the message/// \param message: Message received from the server/// \returns bool: True, if message has been completey processed/// \throw YGP::ParseError, YGP::CommError: In case of an error an describing text//----------------------------------------------------------------------------bool Rovhult::handleMessage (unsigned int player, const std::string& message) throw (YGP::ParseError, YGP::CommError) { if (gameStatus () >= EXCHANGE) { TRACE1 ("Rovhult::handleMessage (unsigned int player, const std::string&) - " << message << " (" << player << ')'); YGP::Tokenize command (message); std::string cmd (command.getNextNode ('=')); if (cmd == "Exchange") { std::string cards (command.getNextNode (';')); cmd = command.getNextNode ('='); unsigned long lPlayer (player); if ((cmd == "Player") && !stringToNumber (lPlayer, command.getNextNode (';').c_str ()) && (lPlayer < NUM_PLAYERS)) { register unsigned int save (lPlayer); lPlayer = (lPlayer - posServer) & 0x3; // Don't exchange already exchanged cards if (save != posServer) { // Remove the cards in the hand and the top of the table piles ICardPile pile; for (unsigned int i (0); i < 3; ++i) { pile.push_back (&players[lPlayer].hand.removeTopCard ()); pile.push_back (&players[lPlayer].reserve[i].removeTopCard ()); } command = cards; unsigned long card (0); unsigned int target (0); // Target piles ICardPile* piles[] = { &players[lPlayer].hand, &players[lPlayer].hand, &players[lPlayer].hand, &players[lPlayer].reserve[0], &players[lPlayer].reserve[1], &players[lPlayer].reserve[2] }; while (command.getNextNode (' ').size ()) { if (stringToNumber (card, command.getActNode ().c_str ())) break; TRACE8 ("Rovhult::handleMessage (unsigned int, const std::string&) - " << lPlayer << ": " << card); card = pile.find (static_cast<unsigned int> (card)); Check3 (card < pile.size ()); if (card != -1U) { CardWidget& movedCard (*pile[card]); if (target > 2) movedCard.showFace (); piles[target++]->setTopCard (movedCard); pile.erase (pile.begin () + card); } } if (pile.empty ()) { aExchanged |= (1 << lPlayer); TRACE2 ("Rovhult::handleMessage (unsigned int player, const std::string&) - " "Exchanged: " << std::hex << aExchanged << std::dec); YGP::ConnectionMgr& cmgr (getConnectionMgr ()); // Inform other clients if (cmgr.getMode () == YGP::ConnectionMgr::SERVER) broadcastMessage (message); if (aExchanged == 0xf) { status.pop (); setGameStatus (PLAYING); makeNextMoves (); } } } else ignoreNextMsg = false; return true; } } } return Game::handleMessage (player, message);}//----------------------------------------------------------------------------/// Executes the remote move locally/// \param pile: Pile to move to/from/// \param target: ID of target as send by the partner/// \throw YGP::Par
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -