📄 sgtmayor.cpp
字号:
//$Id: SgtMayor.cpp,v 1.22 2006/08/06 23:59:34 markus Rel $//PROJECT : Cardgames//SUBSYSTEM : Sgt. Mayor//REFERENCES ://TODO ://BUGS ://REVISION : $Revision: 1.22 $//AUTHOR : Markus Schwab//CREATED : 11.4.2004//COPYRIGHT : Copyright (C) 2004 - 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 <iomanip>#include <sstream>#include <cardgames-cfg.h>#include <gtkmm/menu.h>#include <gtkmm/stock.h>#include <gtkmm/statusbar.h>#include <gtkmm/messagedialog.h>#include <YGP/Check.h>#include <YGP/Trace.h>#include <YGP/ConnMgr.h>#include <YGP/ANumeric.h>#include <YGP/Tokenize.h>#include <ScoreDlg.h>#include <RemotePlayer.h>#include <ComputerPlayer.h>#include "SgtMayor.h"const unsigned int SgtMayor::COLS_PLAYER[NUM_PLAYERS] = { 1, 0, 4 };const unsigned int SgtMayor::ROWS_PLAYER[NUM_PLAYERS] = { 1, 6, 6 };unsigned int SgtMayor::ENDTRICKS (10);//-----------------------------------------------------------------------------/// 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//-----------------------------------------------------------------------------SgtMayor::SgtMayor (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, 10, 8), played (ICardPile::COMPRESSED, ICardPile::SHOWFACE), pTrump (NULL), startPlayer (rand () % NUM_PLAYERS), pScoreDlg (NULL) { TRACE9 ("SgtMayor::SgtMayor (Box&, Statusbar&, CardSet&, ...)"); int width (cards.getCard (0).getImageWidth ()); int height (cards.getCard (0).getImageHeight ()); // Show and attach card-piles changeNames (player); for (unsigned int i (0); i < NUM_PLAYERS; ++i) { players[i].name.show (); attach (players[i].name, COLS_PLAYER[i], COLS_PLAYER[i] + (i ? 3 : 5), ROWS_PLAYER[i] + 1, ROWS_PLAYER[i] + 2, Gtk::EXPAND, Gtk::SHRINK, 1, 2); players[i].neededTicks.show (); attach (players[i].neededTicks, COLS_PLAYER[i], COLS_PLAYER[i] + (i ? 3 : 5), ROWS_PLAYER[i] + 2, ROWS_PLAYER[i] + 3, Gtk::EXPAND, Gtk::SHRINK, 1, 5); players[i].won.show (); attach (players[i].won, COLS_PLAYER[i], COLS_PLAYER[i] + (i ? 3 : 5), ROWS_PLAYER[i] - 1, ROWS_PLAYER[i], Gtk::EXPAND, Gtk::SHRINK, 1, 5); players[i].hand.show (); attach (players[i].hand, COLS_PLAYER[i], COLS_PLAYER[i] + (i ? 3 : 5), ROWS_PLAYER[i], ROWS_PLAYER[i] + 1, Gtk::EXPAND, Gtk::EXPAND, 5); TRACE9 ("SgtMayor::SgtMayor () - Attach at: " << COLS_PLAYER[i] << '/' << COLS_PLAYER[i] + (i ? 3 : 5) << " - " << ROWS_PLAYER[i] << '/' << ROWS_PLAYER[i] + 1); players[i].hand.setStyle (i ? ICardPile::QUITE_COMPRESSED : ICardPile::COMPRESSED); players[i].hand.setShowOption (i ? ICardPile::SHOWBACK : ICardPile::SHOWFACE); players[i].hand.set_size_request (width + 17 * (i ? 7 : 18), height + 5); players[i].won.set_size_request (width + 17 * 7, height + 5); players[i].won.setStyle (ICardPile::QUITE_COMPRESSED); players[i].won.setShowOption (ICardPile::SHOWBACK); } // Show played area played.setStyle (ICardPile::COMPRESSED); played.show (); attach (played, 2, 5, 4, 5, Gtk::SHRINK, Gtk::SHRINK, 5); played.set_size_request (width + 150, height); memset (diffTicks, '\0', sizeof (diffTicks));}//-----------------------------------------------------------------------------/// Destructor//-----------------------------------------------------------------------------SgtMayor::~SgtMayor () { TRACE9 ("SgtMayor::~SgtMayor ()"); delete pScoreDlg; clean ();}//-----------------------------------------------------------------------------/// Makes the move for the next player./// \param player: Actual player/// \returns \c int: Next player or -1 if end of game//-----------------------------------------------------------------------------int SgtMayor::makeMove (unsigned int player) { if ((player + posServer) >= NUM_PLAYERS) player -= posServer; TRACE5 ("SgtMayor::makeMove () - Turn of player - " << player); Check1 (gameStatus () == PLAYING); Check3 (pos2Play == pos1Play); if (pos2Play == -1U) { pos2Play = pos1Play = findPos2Play (player); TRACE8 ("SgtMayor::makeMove (unsigned int) - Going to play card at pos " << pos2Play); flipCards2Play (players[player].hand, pos1Play, pos2Play); } else { TRACE9 ("SgtMayor::makeMove (unsigned int) - Playing card at pos " << pos2Play); player = playCard (player, pos1Play); pos1Play = pos2Play = -1U; } return convertPlayer (player);}//-----------------------------------------------------------------------------/// Starts the game by dealing the cards//-----------------------------------------------------------------------------void SgtMayor::start () { TRACE9 ("SgtMayor::start ()"); Game::start (); Check2 (!played.size ()); ICardPile pile; if (randomizeCardsToPile (pile)) { // Delete the score-dialog if the game has ended if (pScoreDlg) { unsigned int player; int points; pScoreDlg->getMaxPoints (points, player); Check3 (points >= 0); if ((unsigned int)points >= ENDTRICKS) { delete pScoreDlg; pScoreDlg = NULL; memset (diffTicks, '\0', sizeof (diffTicks)); } } if (getConnectionMgr ().getMode () != YGP::ConnectionMgr::CLIENT) { setNextPlayer (startPlayer = calcNextPlayer (startPlayer)); broadcastStartPlayer (startPlayer); } Check3 (cards.size () == 52); for (unsigned int i (0); i < NUM_PLAYERS; ++i) for (unsigned int j (0); j < (cards.size () / NUM_PLAYERS);) if ((pile.getTopCard ().number () != CardWidget::TWO) || (pile.getTopCard ().colour () != CardWidget::SPADES)) { players[(NUM_PLAYERS + i - posServer) % NUM_PLAYERS].hand.insertColourSorted (pile.removeTopCard ()); ++j; } else pile.removeTopCard (); Check3 (pile.empty ()); for (unsigned int i (0); i < (sizeof (playedCards) / sizeof (playedCards[0])); ++i) playedCards[i].reset (); bfColours = 0; if (getConnectionMgr ().getMode () != YGP::ConnectionMgr::CLIENT) { showNeededTicks (); makeExchange (); } }}//-----------------------------------------------------------------------------/// Shows the ticks each player needs//-----------------------------------------------------------------------------void SgtMayor::showNeededTicks () { TRACE9 ("SgtMayor::showNeededTicks () - Startplayer " << startPlayer); // Separate this from dealing the cards, to give the client a chance to // receive and perform the ActPlayer-message (to set the start-player) for (unsigned int i (0); i < NUM_PLAYERS; ++i) { char neededTicks[NUM_PLAYERS] = { '6', '3', '8' }; Glib::ustring needed (_("(needs %1 ticks)")); needed.replace (needed.find ("%1"), 2, 1, neededTicks[i]); players[(i + startPlayer) % NUM_PLAYERS].neededTicks.set_text (needed); }}//-----------------------------------------------------------------------------/// Remove cards from everything which can hold them//-----------------------------------------------------------------------------void SgtMayor::clean () { TRACE9 ("SgtMayor::clean ()"); for (unsigned int i (0); i < NUM_PLAYERS; ++i) { players[i].hand.clear (); for (ICardPile::iterator c (players[i].won.begin ()); c != players[i].won.end (); ++c) (*c)->show (); players[i].won.clear (); } if (pTrump) { remove (*pTrump); delete pTrump; pTrump = NULL; } played.clear (); disableHuman (); Game::clean ();}//-----------------------------------------------------------------------------/// Shows or hides the cards of the computer player/// \param open: Flag if cards should be shown or hidden//-----------------------------------------------------------------------------void SgtMayor::playOpen (bool open) { for (unsigned int i (1); i < NUM_PLAYERS; ++i) { players[i].hand.setShowOption (open ? ICardPile::SHOWFACE : ICardPile::SHOWBACK); players[i].hand.setStyle (open ? ICardPile::COMPRESSED : ICardPile::QUITE_COMPRESSED); } for (unsigned int i (0); i < NUM_PLAYERS; ++i) { players[i].won.setShowOption (open ? ICardPile::SHOWFACE : ICardPile::SHOWBACK); players[i].won.setStyle (open ? ICardPile::COMPRESSED : ICardPile::QUITE_COMPRESSED); for (CardVPile::iterator c (players[i].won.begin ()); c != players[i].won.end (); ++c) if (((c - players[i].won.begin ()) % 3) != 2) open ? (*c)->show () : (*c)->hide (); }}//-----------------------------------------------------------------------------/// Enables the cards of the human player/// \returns \c Flag, if time should be continued/// \remarks Depending of the status of the game (PLAYING2) also the top card/// of the played pile is enabled//-----------------------------------------------------------------------------bool SgtMayor::enableHuman () { Check3 (activeCards.empty ()); TRACE2 ("SgtMayor::enableHuman () - Human has " << players[0].hand.size () << " cards"); for (int i (players[0].hand.size () - 1); i >= 0; --i) activeCards.push_back (players[0].hand[i]->signal_clicked ().connect (bind (mem_fun (*this, (&SgtMayor::cardSelected)), i))); return Game::enableHuman ();}//-----------------------------------------------------------------------------/// Callback after clicking on a card in hand/// \param iCard: Offset of card in hand//-----------------------------------------------------------------------------void SgtMayor::cardSelected (unsigned int iCard) { TRACE5 ("SgtMayor::cardSelected (unsigned int) - Position " << iCard); Check1 (iCard < players[0].hand.size ()); Check2 (gameStatus () == PLAYING); Check2 (pos1Play == -1U); Check2 (pos2Play == -1U); CardWidget& selCard (*players[0].hand[iCard]); CardWidget::COLOURS playColour (selCard.colour ()); if (played.size ()) { // The same colour must be played again (if available) CardWidget::COLOURS colour (played[0]->colour ()); if (playColour != colour) { if (players[0].hand.exists (colour)) { Gtk::MessageDialog dlg (_("Play a card with an equal colour as " "the first played one!"), Gtk::MESSAGE_ERROR); dlg.set_title (PACKAGE " - SgtMayor"); dlg.run (); return; } bfColours |= (1 << played[0]->colour ()); Check2 (pTrump);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -