📄 game.cpp
字号:
//$Id: Game.cpp,v 1.55 2006/06/05 21:38:14 markus Rel $//PROJECT : Cardgames//SUBSYSTEM : Common/Game//REFERENCES ://TODO ://BUGS ://REVISION : $Revision: 1.55 $//AUTHOR : Markus Schwab//CREATED : 10.9.2002//COPYRIGHT : Copyright (C) 2002 - 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 <cerrno>#include <cstdlib>#include <sstream>#include <glibmm/main.h>#include <gtkmm/box.h>#include <gtkmm/menu.h>#include <gtkmm/statusbar.h>#include <gtkmm/messagedialog.h>#include <YGP/Check.h>#include <YGP/Trace.h>#include <YGP/Socket.h>#include <YGP/ConnMgr.h>#include <YGP/AttrParse.h>#include "Player.h"#include "CardSet.h"#include "CardPile.h"#include "ComputerPlayer.h"#include "Game.h"//-----------------------------------------------------------------------------/// Constructor/// \param parent: Parent of widget/// \param statusbar: For messages/// \param cardset: Cardset/// \param player: Vector of player/// \param posPlayer: Position of the player for the server/// \param rows: Number of rows needed by game/// \param columns: Number of columns needed by game//-----------------------------------------------------------------------------Game::Game (Gtk::Box& parent, Gtk::Statusbar& statusbar, CardSet& cardset, const std::vector<Player*>& player, unsigned int posPlayer, YGP::Mutex& mxSerialize, unsigned int rows, unsigned int columns) : Gtk::Table (rows, columns), status (statusbar) , cards (cardset) , actPlayers (player), mxSerializeMsgs (mxSerialize), posServer (posPlayer) , pos2Play (-1U) , pos1Play (-1U), ignoreNextMsg (false), data (NULL) , statGame (NONE) , actPlayer (0), pWonPile (NULL), pMenuPopSort (NULL) { TRACE3 ("Game::Game (Gtk::Box&, Gtk::Statusbar&, Cardset&, std::vector<Player*>," "unsinged int, unsigned int)"); Check3 (cardset.size ()); show (); set_col_spacings (2); set_row_spacings (2); parent.pack_start (*this, true, true, 5); stati.pendingTurn = stati.restart = 0;}//-----------------------------------------------------------------------------/// Destructor//-----------------------------------------------------------------------------Game::~Game () { TRACE9 ("Game::~Game ()"); clean (); delete pMenuPopSort;}//-----------------------------------------------------------------------------/// Starts the game//-----------------------------------------------------------------------------void Game::start () { TRACE8 ("Game::start () - Act. status: " << statGame); Check3 ((statGame <= INITIALIZING) || (statGame == STOPPED)); clean (); setGameStatus (PLAYING); if (getConnectionMgr ().getMode () == YGP::ConnectionMgr::SERVER) { std::string msg ("Game="); msg += name (); TRACE8 ("Game::start () - Sending: " << msg); broadcastMessage (msg); }}//-----------------------------------------------------------------------------/// Terminates the game and cleans the table//-----------------------------------------------------------------------------void Game::stop () { TRACE8 ("Game::stop ()"); if (getConnectionMgr ().getMode () == YGP::ConnectionMgr::SERVER) broadcastMessage ("End"); clean (); setGameStatus (STOPPED);}//-----------------------------------------------------------------------------/// End the current game as soon as possible/// \param startNew: Flag, if game should be restarted//-----------------------------------------------------------------------------void Game::end (bool startNew) { TRACE8 ("Game::end () - Restart: " << (startNew ? "Yes" : "No")); stati.restart = startNew; if (canBeStopped ()) { stop (); actPlayer = 0; disableHuman (); } else setGameStatus (TOSTOP);}//-----------------------------------------------------------------------------/// Disables the cards the human player can select//-----------------------------------------------------------------------------void Game::disableHuman () { TRACE2 ("Game::disableHuman () - " << activeCards.size () << " cards"); for (int i (activeCards.size ()); i > 0;) activeCards[--i].disconnect (); activeCards.clear ();}//-----------------------------------------------------------------------------/// Shuffles (Randomizes) the cards onto the staple/// \param pile: Pile to which the cards should be shuffeled to/// \returns bool: Flag, if method completed successfully//-----------------------------------------------------------------------------bool Game::randomizeCardsToPile (ICardPile& pile) const { // Randomize and put cards onto staple YGP::ConnectionMgr& cmgr (getConnectionMgr ()); if (cmgr.getMode () == YGP::ConnectionMgr::CLIENT) { Check3 (data && *data); std::string input (data); YGP::AttributeParse ap; ATTRIBUTE (ap, std::string, input, "Cards"); try { ap.assignValues (input); YGP::Tokenize positions (input); TRACE8 ("Game::randomizeCardsToPile (ICardPile&) - Cards: " << cards.size ()); for (unsigned int i (0); i < (cards.size () - 1); ++i) { unsigned long pos (0); std::string token; char* pTail (NULL); errno = 0; // Read next token; the value must be a number if ((token = positions.getNextNode (' ')).empty () || stringToNumber (pos, token.c_str ()) || (pos >= cards.size ()) || (errno || (pTail && *pTail))) { std::string error (N_("Invalid card specification!")); throw YGP::CommError (error); } TRACE9 ("Game::randomizeCardsToPile (ICardPile&) const - [" << i << "] = " << pos); cards.set (i, pos); } writeOK (*cmgr.getSocket ()); } catch (YGP::CommError& error) { writeError (*cmgr.getSocket (), 99, error.what ()); Glib::ustring err (_("Received invalid input from the server!\n\nReason: %1")); err.replace (err.find ("%1"), 2, _(error.what ())); Gtk::MessageDialog dlg (err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK); dlg.set_title (PACKAGE); dlg.run (); return false; } } else { cards.shuffle (); std::ostringstream msg; msg << "Cards="; for (unsigned int i (0); i < cards.size (); ++i) msg << cards.getCard (i).id () << ' '; const_cast<Game*> (this)->cardOrder = msg.str (); if (cmgr.getMode () == YGP::ConnectionMgr::SERVER) broadcastMessage (cardOrder); } pile.setTopCards (cards.getCards ()); return true;}//-----------------------------------------------------------------------------/// Moves cards from one pile to another/// \param dest: Destination pile/// \param source: Source pile//-----------------------------------------------------------------------------void Game::movePile (ICardPile& dest, ICardPile& source, unsigned int start, int end) { TRACE3 ("Game::movePile (ICardPile&, ICardPile&, unsigned int, int) - " "moving from pos " << start << " to " << end); Check3 (source.size ()); Check3 (start < source.size ()); if (end == -1) end = source.size () - 1; Check1 (end < static_cast<int> (source.size ())); Check1 (static_cast<int> (start) <= end); do { dest.append (source.remove (start)); } while ((unsigned int)end-- > start);}//-----------------------------------------------------------------------------/// Cleans the table//-----------------------------------------------------------------------------void Game::clean () { TRACE8 ("Game::clean ()"); disableWonCards ();}//-----------------------------------------------------------------------------/// Activates the next player//-----------------------------------------------------------------------------void Game::makeNextMoves () { if (actPlayer >= 0) { TRACE8 ("Game::makeNextMoves () - " << actPlayer); Check3 (actPlayer < static_cast<int> (actPlayers.size ())); Check3 (!stati.pendingTurn); unsigned int timeout (actPlayers[actPlayer]->timeout ()); if (timeout) { Glib::signal_timeout ().connect (bind (mem_fun (*actPlayers[actPlayer], &Player::makeTurn), this), timeout); stati.pendingTurn = 1; } else Glib::signal_idle ().connect (bind (mem_fun (*actPlayers[actPlayer], &Player::makeTurn), this)); disableHuman (); }}//-----------------------------------------------------------------------------/// Ends the move of the passed remote player. This contains of executing the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -