📄 buraco.cpp
字号:
//$Id: Buraco.cpp,v 1.105 2006/08/03 23:25:30 markus Rel $//PROJECT : Cardgames//SUBSYSTEM : Buraco//REFERENCES ://TODO ://BUGS ://REVISION : $Revision: 1.105 $//AUTHOR : Markus Schwab//CREATED : 24.02.2003//COPYRIGHT : Copyright (C) 2003 - 2006// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.#include <cardgames-cfg.h>#include <cstdlib>#include <bitset>#include <sstream>#include <gtk/gtkdnd.h>#include <gtkmm/stock.h>#include <gtkmm/statusbar.h>#include <gtkmm/messagedialog.h>#include <gtkmm/scrolledwindow.h>#include <YGP/Check.h>#include <YGP/Trace.h>#include <YGP/ConnMgr.h>#include <YGP/ANumeric.h>#include <YGP/Tokenize.h>#include <YGP/AttrParse.h>#include <Human.h>#include <ScoreDlg.h>#include <ComputerPlayer.h>#include "Buraco.h"std::vector<Gtk::TargetEntry> Buraco::dndType;unsigned int Buraco::ENDPOINTS (2000);unsigned int Buraco::CARDS2DEAL (11);//-----------------------------------------------------------------------------/// Constructor/// \param parent: Parent widget to display the game in/// \param statusbar: Status bar widget to display information about the game/// \param cardset: Cardset to use/// \param player: Vector of player/// \param posPlayer: Position of player for the server/// \param mxSerialize: Mutex to serialize messages from the server//-----------------------------------------------------------------------------Buraco::Buraco (Gtk::Box& parent, Gtk::Statusbar& statusbar, CardSet& cardset, const std::vector<Player*>& player, unsigned int posPlayer, YGP::Mutex& mxSerialize) : Game (parent, statusbar, cardset, player, posPlayer, mxSerialize, 3, 10) , startPlayer (-1U) , newPile (_("New pile")) , staple (ICardPile::TOTALLY_COMPRESSED, ICardPile::SHOWBACK) , dumped (ICardPile::TOTALLY_COMPRESSED, ICardPile::SHOWFACE) , acceptCards (-1U), target (-1U) , pScoreDlg (NULL) { TRACE9 ("Buraco::Buraco (Box&, Statusbar&, CardSet&, const " "std::vector<Glib::ustring>&)"); for (unsigned int i (0); i < (NUM_PLAYERS >> 1); ++i) { scrlTable[i] = new Gtk::ScrolledWindow (); scrlTable[i]->add (boxTeam[i]); scrlTable[i]->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); scrlTable[i]->show (); } int width (cards.getCard (0).getImageWidth ()); int height (cards.getCard (0).getImageHeight ()); TRACE9 ("Buraco::Buraco (Box&, Statusbar&, CardSet&, const " "std::vector<Glib::ustring>&) - Init common staples"); staple.set_size_request (width, height); dumped.set_size_request (width, height); boxTeam[0].pack_end (newPile, Gtk::PACK_EXPAND_WIDGET, 5); boxTeam[0].set_size_request (-1, height + 5 * 15); boxTeam[1].set_size_request (-1, height + 5 * 15); for (unsigned int i (1); i < NUM_PLAYERS; ++i) { attach (hands[i], (i << 2) - 4, (i << 2) - 2, 4, 5, Gtk::EXPAND, Gtk::SHRINK, 5, 5); attach (names[i], (i << 2) - 4, (i << 2) - 2, 5, 6, Gtk::EXPAND, Gtk::SHRINK, 0); hands[i].show (); names[i].show (); } hands[0].setStyle (ICardPile::COMPRESSED); hands[0].setShowOption (ICardPile::SHOWFACE); hands[0].show (); names[0].show (); TRACE9 ("Buraco::Buraco (Box&, Statusbar&, CardSet&, const " "std::vector<Glib::ustring>&) - Attach widgets"); attach (hands[0], 3, 10, 0, 1, Gtk::EXPAND, Gtk::SHRINK, 1, 5); attach (names[0], 3, 10, 1, 2, Gtk::EXPAND, Gtk::SHRINK, 1, 5); attach (staple, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 5); attach (dumped, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 1, 5); attach (*scrlTable[0], 0, 10, 2, 3, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL, 0, 5); attach (*scrlTable[1], 0, 10, 3, 4, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL, 0, 5); TRACE9 ("Buraco::Buraco (Box&, Statusbar&, CardSet&, const " "std::vector<Glib::ustring>&) - Show widgets"); newPile.show (); staple.show (); dumped.show (); boxTeam[0].show (); boxTeam[1].show (); if (dndType.empty ()) dndType.push_back (Gtk::TargetEntry ("icon/card", Gtk::TARGET_SAME_APP, 0)); statusbar.pack_end (frameInfo, Gtk::PACK_SHRINK, 5); frameInfo.set_shadow_type (Gtk::SHADOW_IN); frameInfo.show (); info.show (); frameInfo.add (info); changeNames (player);}//-----------------------------------------------------------------------------/// Destructor//-----------------------------------------------------------------------------Buraco::~Buraco () { TRACE9 ("Buraco::~Buraco ()"); clean (); delete pScoreDlg; // Free team names for (std::vector<Player*>::iterator i (nameTeams.begin ()); i != nameTeams.end (); ++i) delete *i; for (unsigned int i (0); i < (NUM_PLAYERS >> 1); ++i) delete scrlTable[i];}//-----------------------------------------------------------------------------/// Removes a cerrado from the table/// \param team: Team to inspect/// \remarks As every move can only make one cerrado; only the first is/// removed.//-----------------------------------------------------------------------------void Buraco::cleanCerrado (unsigned int player) { Check1 (player < NUM_PLAYERS); for (std::vector<BuracoPile*>::iterator p (tablePiles[player & 1].begin ()); p != tablePiles[player & 1].end (); ++p) { Check3 (*p); Check3 ((*p)->size () <= 7); if (((*p)->size () == 7) && (*p)->is_visible ()) { removeCerrado (player, **p); return; } }}//-----------------------------------------------------------------------------/// Makes the move for the next player./// \param player: Actual player/// \returns \c int: Next player or -1 if end of game/// \remarks This method expects the target pile to play in the target-member/// and the positions to play in pos1Play and pos2Play//-----------------------------------------------------------------------------int Buraco::makeMove (unsigned int player) { TRACE5 ("Buraco::makeMove (unsigned int) - Turn of player " << player << "; Target: " << std::hex << (int)target << std::dec); Check1 (player); Check1 (player < NUM_PLAYERS); Check1 (gameStatus () == PLAYING); Check1 (!hands[player].empty ()); // First cleanup cerrado made in the last turn cleanCerrado (player); if (target == -1U) { target = showCardsToPlay (player); TRACE8 ("Buraco::makeMove (unsigned int) - Going to play cards to " << std::hex << (int)target << std::dec); Check3 (target != -1U); Check1 (pos1Play <= pos2Play); } else { Check1 (pos1Play <= pos2Play); // Calculate pile to play cards to: If target = 0xffff0000, append cards // to dumped staple; else target specifies offset of pile and card on // table Check3 (hands[player].getTopCard ().showsFace ()); unsigned int pos (target & 0xffff); ICardPile* dest; CardHPile& source (hands[player]); unsigned int oldPlayer (player); target >>= 16; if (target == 0xffff) { TRACE4 ("Buraco::makeMove (unsigned int) - Dumping card"); Check3 (pos1Play == pos2Play); pos = dumped.size (); dest = &dumped; gStatus.startTurn = 1; ++player &= 0x3; displayTurn (player); } else { TRACE4 ("Buraco::makeMove (unsigned int) - Moving cards to pile " << target); Check3 (target < tablePiles[player & 1].size ()); dest = tablePiles[player & 1][target];#if CHECK > 2 for (unsigned int pos (pos1Play); pos < pos2Play; ++pos) { int diff (cardDistance (*source[pos + 1], *source[pos])); TRACE1 ("Buraco::makeMove (unsigned int) - Card " << *source[pos]); Check3 (isJoker (*source[pos]) || isJoker (*source[pos + 1]) ? true : (diff == 0) || (diff == 1)); }#endif } // Move played cards to the pile to play Check3 (source.size () > pos2Play); for (; (int)pos1Play <= (int)pos2Play; --pos2Play) dest->insert (source.remove (pos1Play), pos++); target = -1U; if (gStatus.pickUpPlayed) { Check3 (dumped.size ()); gStatus.pickUpPlayed = 0; movePile (hands[player], dumped); hands[player].sort (compByNumberWithJokers); } if (containsOnlyJoker (source)) { if (reserve[oldPlayer & 1].size ()) addBuraco (oldPlayer); else if (source.empty ()) { cleanCerrado (oldPlayer); Check3 (points[oldPlayer & 1] > 100); points[oldPlayer & 1] += 100; endGame (); return -1; } } } return player;}//-----------------------------------------------------------------------------/// 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)//-----------------------------------------------------------------------------unsigned int Buraco::showCardsToPlay (unsigned int player) { TRACE2 ("Buraco::showCardsToPlay (unsigned int) - " << player << " (" << gStatus.startGame << '/' << gStatus.startTurn << ')'); if (gStatus.startTurn && (((player & 1) ? gStatus.team2Buraco : gStatus.team1Buraco) == (player >> 1))) ((player & 1) ? gStatus.team2Buraco : gStatus.team1Buraco) = 0x3; ICardPile& playerPile (hands[player]); if (gStatus.startTurn) { Check3 (dumped.size ()); gStatus.startTurn = 0; CardWidget& dumpedCard (dumped.getTopCard ()); if (gStatus.startGame ? (isJoker (dumpedCard) || playerPile.getFittingCard (dumpedCard, &cardDistance) != playerPile.end ()) : ((!isJoker (dumpedCard)) && pileHasFittingPair (playerPile, dumpedCard) && ((points[player & 1] > 100) || reserve[player & 1].size () || (dumped.size () + playerPile.size ()) > 4))) { if (getConnectionMgr ().getMode () != YGP::ConnectionMgr::NONE) { // Send played card to all clients (if any) std::ostringstream msg; msg << "Play=" << dumpedCard.id () << ";Target=3"; if (getConnectionMgr ().getMode () == YGP::ConnectionMgr::CLIENT) ignoreNextMsg = true; broadcastMessage (msg.str ()); } playerPile.insertSorted (dumped.removeTopCard (), compByNumberWithJokers); if (dumped.size ()) gStatus.pickUpPlayed = 1; if (!gStatus.startGame) { std::map<unsigned int, unsigned int> aPos; std::vector<unsigned int> aOrder; unsigned int nrs (playerPile.getSeries (dumpedCard, aPos, aOrder, &cardDistance)); TRACE8 ("Buraco::showCardsToPlay (unsigned int) - Sizes: " << nrs << "<->" << aPos.size ()); Check3 ((nrs >= 3) || (aPos.size () >= 3)); if (nrs > 7) nrs = 7; pos1Play = ((nrs < aPos.size ()) ? (nrs = aPos.size (), playerPile.sortColourSerie (aPos, aOrder)) : playerPile.find (dumpedCard, compByNumberWithJokers)); pos2Play = pos1Play + nrs - 1; Check3 ((pos2Play - pos1Play) >= 2); makeNewPile (player & 1); target = (tablePiles[player & 1].size () - 1) << 16; } } else { if (getConnectionMgr ().getMode () != YGP::ConnectionMgr::NONE) { // Send played card to all clients (if any) std::ostringstream msg; msg << "Play=" << staple.getTopCard ().id () << ";Target=2"; if (getConnectionMgr ().getMode () == YGP::ConnectionMgr::CLIENT)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -