[monopd] 02/04: Imported Upstream version 0.10.1

Markus Koschany apo-guest at moszumanska.debian.org
Sun Jul 19 14:13:17 UTC 2015


This is an automated email from the git hooks/post-receive script.

apo-guest pushed a commit to branch master
in repository monopd.

commit 348b715d1af01a17254c8b79074ce365c28290b1
Author: Markus Koschany <apo at gambaru.de>
Date:   Sun Jul 19 16:06:26 2015 +0200

    Imported Upstream version 0.10.1
---
 API            |   2 +-
 COPYING        |  43 +++---
 ChangeLog      |   6 +
 NEWS           |   6 +
 configure      |   2 +-
 configure.ac   |   6 +-
 src/game.cpp   | 423 ++++++++++++++++++++++++++++-----------------------------
 src/game.h     |   9 +-
 src/player.cpp |  77 ++++++-----
 src/server.cpp |   4 +-
 10 files changed, 294 insertions(+), 284 deletions(-)

diff --git a/API b/API
index 37d3252..8986572 100644
--- a/API
+++ b/API
@@ -1,7 +1,7 @@
 ===============================================================================
 monopd API
 
-Revision: 0.10.0
+Revision: 0.10.1
 
 Erik Bourget <ebourg at po-box.mcgill.ca>
 Rob Kaper <cap at capsi.com>
diff --git a/COPYING b/COPYING
index 60549be..d159169 100644
--- a/COPYING
+++ b/COPYING
@@ -1,12 +1,12 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
 
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-			    Preamble
+                            Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users.  This
 General Public License applies to most of the Free Software
 Foundation's software and to any other program whose authors commit to
 using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
+the GNU Lesser General Public License instead.)  You can apply it to
 your programs, too.
 
   When we speak of free software, we are referring to freedom, not
@@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
 
   The precise terms and conditions for copying, distribution and
 modification follow.
-

-		    GNU GENERAL PUBLIC LICENSE
+
+                    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
   0. This License applies to any program or other work which contains
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
     License.  (Exception: if the Program itself is interactive but
     does not normally print such an announcement, your work based on
     the Program is not required to print an announcement.)
-

+
 These requirements apply to the modified work as a whole.  If
 identifiable sections of that work are not derived from the Program,
 and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
 access to copy the source code from the same place counts as
 distribution of the source code, even though third parties are not
 compelled to copy the source along with the object code.
-

+
   4. You may not copy, modify, sublicense, or distribute the Program
 except as expressly provided under this License.  Any attempt
 otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
 
 This section is intended to make thoroughly clear what is believed to
 be a consequence of the rest of this License.
-

+
   8. If the distribution and/or use of the Program is restricted in
 certain countries either by patents or by copyrighted interfaces, the
 original copyright holder who places the Program under this License
@@ -255,7 +255,7 @@ make exceptions for this.  Our decision will be guided by the two goals
 of preserving the free status of all derivatives of our free software and
 of promoting the sharing and reuse of software generally.
 
-			    NO WARRANTY
+                            NO WARRANTY
 
   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGES.
 
-		     END OF TERMS AND CONDITIONS
-

-	    How to Apply These Terms to Your New Programs
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
 possible use to the public, the best way to achieve this is to make it
@@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
 the "copyright" line and a pointer to where the full notice is found.
 
     <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) 19yy  <name of author>
+    Copyright (C) <year>  <name of author>
 
     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
@@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
     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
-
+    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.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 Also add information on how to contact you by electronic and paper mail.
 
 If the program is interactive, make it output a short notice like this
 when it starts in an interactive mode:
 
-    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision version 69, Copyright (C) year name of author
     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     This is free software, and you are welcome to redistribute it
     under certain conditions; type `show c' for details.
@@ -336,5 +335,5 @@ necessary.  Here is a sample; alter the names:
 This General Public License does not permit incorporating your program into
 proprietary programs.  If your program is a subroutine library, you may
 consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
+library.  If this is what you want to do, use the GNU Lesser General
 Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
index b9cd69d..86426c6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+0.10.1
+------
+
+- reworked a little bit game logic to cleanup some bugs on player
+  disconnection event
+
 0.10.0
 ------
 
diff --git a/NEWS b/NEWS
index b9cd69d..86426c6 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+0.10.1
+------
+
+- reworked a little bit game logic to cleanup some bugs on player
+  disconnection event
+
 0.10.0
 ------
 
diff --git a/configure b/configure
index f64968d..759ac72 100755
--- a/configure
+++ b/configure
@@ -2443,7 +2443,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=monopd
- VERSION=0.10.0
+ VERSION=0.10.1
 
 
 cat >>confdefs.h <<_ACEOF
diff --git a/configure.ac b/configure.ac
index d2c315f..0a61904 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
 # Process this file with autoconf to produce a configure script.
 AC_INIT(configure.ac)
-AM_INIT_AUTOMAKE(monopd, 0.10.0)
+AM_INIT_AUTOMAKE(monopd, 0.10.1)
 AM_CONFIG_HEADER(config.h)
 AC_LANG(C++)
 
@@ -42,8 +42,8 @@ AS_IF([test "x$USE_SYSTEMD_DAEMON" != "xno"], [
 ])
 
 if test "x$GCC" = "xyes"; then  \
-     CFLAGS+=" -Wall -Wextra";  \ 
-     CXXFLAGS+=" -Wall -Wextra";  \ 
+     CFLAGS+=" -Wall -Wextra";  \
+     CXXFLAGS+=" -Wall -Wextra";  \
 fi
 
 AC_OUTPUT([
diff --git a/src/game.cpp b/src/game.cpp
index 81b9219..f5d1211 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -43,8 +43,7 @@
 #include "display.h"
 
 Game::Game(int id)
- :	GameObject(id, GGame),
- 	m_pWinner( 0 )
+ :	GameObject(id, GGame)
 {
 	m_status = Config;
 
@@ -553,7 +552,7 @@ void Game::start(Player *pInput)
 
 void Game::setTokenLocation(Player *pInput, unsigned int estateId)
 {
-	if (!clientsMoving() || !pInput || !m_pTurn)
+	if (!clientsMoving())
 		return;
 
 	Estate *estateLoc = findEstate(estateId);
@@ -561,54 +560,48 @@ void Game::setTokenLocation(Player *pInput, unsigned int estateId)
 	if ( !estateLoc || !pInput->tokenLocation() || !m_pTurn->destination() || (pInput->tokenLocation() == estateLoc) )
 		return;
 
-	bool useNext = false;
-	unsigned int money = 0;
-
 //	printf("Game::setTokenLocation, P:%d PTL:%d EID:%d\n", pInput->id(), pInput->tokenLocation()->id(), estateId);
 
-	Estate *estate = 0;
-	for (std::vector<Estate *>::iterator it = m_estates.begin() ;;)
-	{
-		if (it == m_estates.end())
-		{
+	std::vector<Estate *>::iterator it;
+	// find current player estate
+	for (it = m_estates.begin(); it != m_estates.end(); it++) {
+		if (*it == pInput->tokenLocation()) {
+//			printf("Game::setTokenLocation, %d==PTL\n", (*it)->id());
+			it++;
+			break;
+		}
+	}
+
+	unsigned int money = 0;
+	while (1) {
+		if (it == m_estates.end()) {
 //			printf("Game::setTokenLocation, reloop\n");
 			it = m_estates.begin();
-			continue;
 		}
-		if (!(estate = *it))
-			break;
+		Estate *estate = *it;
 
-		if (useNext)
-		{
-			if (estate->getIntProperty("passmoney"))
-			{
-//				printf("Game::setTokenLocation, pass:%d\n", estate->id());
-				Display display;
-				display.setText("%s passes %s and gets %d.", m_pTurn->getStringProperty("name").c_str(), estate->getStringProperty("name").c_str(), estate->getIntProperty("passmoney"));
-				pInput->sendDisplayMsg(&display);
-				money += estate->getIntProperty("passmoney");
-				pInput->ioWrite("<monopd><playerupdate playerid=\"%d\" money=\"%d\"/></monopd>\n", m_pTurn->id(), m_pTurn->getIntProperty("money") + money);
-			}
-			if (estate == m_pTurn->destination())
-			{
-//				printf("Game::setTokenLocation, setPTL:0\n");
-				pInput->setTokenLocation(0); // Player is done moving
-				break;
-			}
-			if (estate == estateLoc)
-			{
-//				printf("Game::setTokenLocation, setPTL:%d\n", estateId);
-				pInput->setTokenLocation(estate); // Player is not done moving
-				break;
-			}
+		if (estate->getIntProperty("passmoney")) {
+//			printf("Game::setTokenLocation, pass:%d\n", estate->id());
+			Display display;
+			display.setText("%s passes %s and gets %d.", m_pTurn->getStringProperty("name").c_str(), estate->getStringProperty("name").c_str(), estate->getIntProperty("passmoney"));
+			pInput->sendDisplayMsg(&display);
+			money += estate->getIntProperty("passmoney");
+			pInput->ioWrite("<monopd><playerupdate playerid=\"%d\" money=\"%d\"/></monopd>\n", m_pTurn->id(), m_pTurn->getIntProperty("money") + money);
 		}
-		else if (estate == pInput->tokenLocation())
-		{
-//			printf("Game::setTokenLocation, useNext:%d==PTL\n", estate->id());
-			useNext = true;
+
+		if (estate == m_pTurn->destination()) {
+//			printf("Game::setTokenLocation, setPTL:0\n");
+			pInput->setTokenLocation(0); // Player is done moving
+			break;
 		}
 
-		++it;
+		if (estate == estateLoc) {
+//			printf("Game::setTokenLocation, setPTL:%d\n", estateId);
+			pInput->setTokenLocation(estate); // Player is not done moving
+			break;
+		}
+
+		it++;
 	}
 
 	// Find out if there are still clients busy with movement.
@@ -616,38 +609,33 @@ void Game::setTokenLocation(Player *pInput, unsigned int estateId)
 		return;
 
 	// Land player!
-	bool endTurn = landPlayer(m_pTurn, false);
-
-	if (clientsMoving())
-	{
-		// Don't do a thing.. just wait until they are done.
-	}
-	else if (m_pTurn->getBoolProperty("can_buyestate"))
-	{
-		// Don't do a thing..
-	}
-	else if (endTurn)
-		m_pTurn->endTurn();
+	landPlayer(m_pTurn, false);
+	// game might be ended if a player is bankrupt after landing (eg. could not pay rent), thus m_pTurn can be NULL here
+	if (m_pTurn) m_pTurn->endTurn();
 }
 
 void Game::tokenMovementTimeout()
 {
+	// game might be ended if a player left while moving, thus m_pTurn can be NULL here
+	if (!m_pTurn) {
+		return;
+	}
+
+	if (!m_pTurn->destination()) {
+		return;
+	}
+
 	// Mark all clients as non moving.
-	Player *pTmp = 0;
-	for(std::vector<Player *>::iterator it = m_players.begin(); it != m_players.end() && (pTmp = *it) ; ++it)
-		if (pTmp->tokenLocation())
-		{
-			if (m_pTurn && m_pTurn->destination())
-			{
-				m_pTurn->setProperty("location", m_pTurn->destination()->id(), this);
-				m_pTurn->setBoolProperty("directmove", true, this);
-				setTokenLocation(pTmp, m_pTurn->destination()->id());
-			}
+	for(std::vector<Player *>::iterator it = m_players.begin(); it != m_players.end(); ++it) {
+		if ((*it)->tokenLocation()) {
+			setTokenLocation(*it, m_pTurn->destination()->id());
 		}
+	}
 }
 
 unsigned int Game::auctionTimeout()
 {
+	// game might be ended while an auction was in progress (eg. a player left), thus m_auction can be NULL here
 	if (!m_auction)
 		return 0;
 
@@ -672,6 +660,7 @@ unsigned int Game::auctionTimeout()
 		}
 
 		completeAuction();
+		m_pTurn->endTurn();
 		return 0;
 	}
 
@@ -747,6 +736,11 @@ void Game::delDebt(Debt *debt)
 			m_debts.erase(it);
 			break;
 		}
+
+	if (debt == m_auctionDebt) {
+		m_auctionDebt = 0;
+	}
+
 	Player *pFrom = debt->from();
 	if ( !findDebt(pFrom) )
 		pFrom->setBoolProperty("hasdebt", false);
@@ -761,8 +755,6 @@ void Game::solveDebts(Player *pInput, const bool &verbose)
 	{
 		if (verbose)
 			ioError("You don't have any debts to pay off!");
-		if (!clientsMoving() && !m_auction && !m_pausedForDialog)
-			pInput->endTurn();
 		return;
 	}
 
@@ -784,11 +776,8 @@ void Game::solveDebts(Player *pInput, const bool &verbose)
 		display.resetButtons(); /* Remove declare bankruptcy button */
 		pInput->sendDisplayMsg(&display);
 
-		completeAuction();
+		m_pTurn->endTurn();
 	}
-
-	if (!clientsMoving() && !m_auction && !m_pausedForDialog)
-		pInput->endTurn();
 }
 
 bool Game::solveDebt( Debt *debt )
@@ -808,10 +797,8 @@ bool Game::solveDebt( Debt *debt )
 	Display display;
 	display.setText("%s pays off a %d debt to %s.", pFrom->getStringProperty("name").c_str(), debt->amount(), (pCreditor ? pCreditor->getStringProperty("name").c_str() : "Bank"));
 	sendDisplayMsg(&display);
-	if (debt == m_auctionDebt) {
-		m_auctionDebt = 0;
-	}
 	delDebt(debt);
+	completeAuction();
 	return true;
 }
 
@@ -1039,13 +1026,8 @@ void Game::acceptTrade(Player *pInput, char *data)
 
 	trade->setPlayerAccept(pInput, true);
 
-	if (trade->allAccept())
-	{
-		// Complete trade
+	if (trade->allAccept()) {
 		completeTrade(trade);
-		delTrade(trade);
-		if (!clientsMoving() && !m_auction && !m_pausedForDialog)
-			m_pTurn->endTurn();
 	}
 }
 
@@ -1091,7 +1073,7 @@ void Game::completeTrade(Trade *trade)
 			delete object; // was temporarily created to serve as trade object
 			if (!pFrom->payMoney(money))
 			{
-				display2.setText("%s owes %d to %s. Game paused, %s is not solvent. Player needs to raise %d in cash first.", pFrom->getStringProperty("name").c_str(), money, pTo->getStringProperty("name").c_str(), pFrom->getStringProperty("name").c_str(), (money - pFrom->getIntProperty("money")));
+				display2.setText("Game paused, %s owes %d to %s but is not solvent. Player needs to raise %d in cash first.", pFrom->getStringProperty("name").c_str(), money, pTo->getStringProperty("name").c_str(), (money - pFrom->getIntProperty("money")));
 				sendDisplayMsg(&display2);
 
 				newDebt(pFrom, pTo, 0, money);
@@ -1115,6 +1097,8 @@ void Game::completeTrade(Trade *trade)
 	for(std::vector<Player *>::iterator it = m_players.begin(); it != m_players.end() && (player = *it) ; ++it)
 		if (trade->hasPlayer(player))
 			solveDebts(player);
+
+	delTrade(trade);
 }
 
 void Game::abortAuction()
@@ -1124,12 +1108,12 @@ void Game::abortAuction()
 
 	printf("Game::abortAuction()\n");
 
-	ioWrite("<monopd><auctionupdate auctionid=\"%d\" status=\"%d\"/></monopd>\n", m_auction->id(), Auction::Sold);
+	if (m_auction->status() != Auction::Sold) {
+		ioWrite("<monopd><auctionupdate auctionid=\"%d\" status=\"%d\"/></monopd>\n", m_auction->id(), Auction::Sold);
+	}
 
 	delete m_auction;
 	m_auction = NULL;
-
-	m_pTurn->endTurn();
 }
 
 void Game::completeAuction()
@@ -1149,8 +1133,6 @@ void Game::completeAuction()
 
 	delete m_auction;
 	m_auction = NULL;
-
-	m_pTurn->endTurn();
 }
 
 void Game::sendDisplayMsg(Display *display, Player *except) {
@@ -1226,46 +1208,54 @@ Estate *Game::findEstate(int id)
 
 Estate *Game::findNextEstate(EstateGroup *group, Estate *startEstate)
 {
-	bool useNext = true;
-	if (startEstate)
-		useNext = false;
-
-	Estate *eTmp = 0, *eFirst = 0;
-	for (std::vector<Estate *>::iterator eIt = m_estates.begin() ; eIt != m_estates.end() && (eTmp = *eIt) ; eIt++)
-	{
-		if (startEstate && startEstate == eTmp)
-			useNext = true;
-		if (eTmp->group() == group)
-		{
-			if (useNext==true)
-				return eTmp;
-			else if (!eFirst)
-				eFirst = eTmp;
+	std::vector<Estate *>::iterator it = m_estates.begin();
+	if (startEstate) {
+		for (; it != m_estates.end(); it++) {
+			if (startEstate == *it) {
+				break;
+			}
 		}
 	}
-	return eFirst;
+	for (; it != m_estates.end(); it++) {
+		if ((*it)->group() == group) {
+			return *it;
+		}
+	}
+	// reloop
+	if (startEstate) {
+		for (it = m_estates.begin(); it != m_estates.end(); it++) {
+			if ((*it)->group() == group) {
+				return *it;
+			}
+		}
+	}
+	return NULL;
 }
 
 Estate *Game::findNextJailEstate(Estate *startEstate)
 {
-	bool useNext = true;
-	if (startEstate)
-		useNext = false;
-
-	Estate *eTmp = 0, *eFirst = 0;
-	for (std::vector<Estate *>::iterator eIt = m_estates.begin() ; eIt != m_estates.end() && (eTmp = *eIt) ; eIt++)
-	{
-		if (startEstate && startEstate == eTmp)
-			useNext = true;
-		if (eTmp->getBoolProperty("jail"))
-		{
-			if (useNext==true)
-				return eTmp;
-			else if (!eFirst)
-				eFirst = eTmp;
+	std::vector<Estate *>::iterator it = m_estates.begin();
+	if (startEstate) {
+		for (; it != m_estates.end(); it++) {
+			if (startEstate == *it) {
+				break;
+			}
+		}
+	}
+	for (; it != m_estates.end(); it++) {
+		if ((*it)->getBoolProperty("jail")) {
+			return *it;
 		}
 	}
-	return eFirst;
+	// reloop
+	if (startEstate) {
+		for (it = m_estates.begin(); it != m_estates.end(); it++) {
+			if ((*it)->getBoolProperty("jail")) {
+				return *it;
+			}
+		}
+	}
+	return NULL;
 }
 
 void Game::transferEstate(Estate *estate, Player *player, const bool verbose)
@@ -1440,10 +1430,13 @@ Player *Game::findPlayer(int playerId)
 
 void Game::removePlayer(Player *p)
 {
-	if (p->getBoolProperty("hasturn")) {
-		if (clientsMoving()) {
-			tokenMovementTimeout();
-		}
+	// note: m_pTurn is NULL when a game is finished
+	if (p == m_pTurn) {
+		// cancel any tax dialog
+		m_pausedForDialog = false;
+		// player left game during its turn, cancel any token movement
+		setAllClientsMoving(0);
+		// and update turn -before- removing player from players vector
 		updateTurn();
 	}
 
@@ -1593,32 +1586,30 @@ unsigned int Game::playerAssets(Player *player)
 
 void Game::updateTurn()
 {
-	if (m_status == Game::End)
-		return;
-
-	Player *pOldTurn = m_pTurn;
 	// Disable turn, roll and buy.
-	pOldTurn->setTurn(false);
+	m_pTurn->setTurn(false);
 
-	Player *player = 0, *pFirst = 0;
-	bool useNext = false;
-	for(std::vector<Player *>::iterator it = m_players.begin() ; it != m_players.end() && (player = *it) ; ++it)
-	{
-		if (!pFirst && !player->getBoolProperty("bankrupt") && !player->getBoolProperty("spectator"))
-			pFirst = player;
+	std::vector<Player *>::iterator it;
+	// find current player
+	for(it = m_players.begin(); it != m_players.end(); it++) {
+		if (*it == m_pTurn) {
+			it++;
+			break;
+		}
+	}
 
-		if (player == pOldTurn)
-			useNext = true;
-		else if (useNext && !player->getBoolProperty("bankrupt") && !player->getBoolProperty("spectator"))
-		{
+	// find next player
+	while (1) {
+		if (it == m_players.end()) {
+			it = m_players.begin();
+			setProperty("turn", getIntProperty("turn") +1);
+		}
+		Player *player = *it;
+		if (!player->getBoolProperty("bankrupt") && !player->getBoolProperty("spectator")) {
 			m_pTurn = player;
-			useNext = false;
 			break;
 		}
-	}
-	if (useNext && pFirst) {
-		m_pTurn = pFirst;
-		setProperty("turn", getIntProperty("turn") +1);
+		it++;
 	}
 
 	// Set turn.
@@ -1629,46 +1620,43 @@ void Game::updateTurn()
 	m_pTurn->setTurn(true);
 }
 
-bool Game::landPlayer(Player *pTurn, const bool directMove, const std::string &rentMath)
+void Game::landPlayer(Player *pTurn, const bool directMove, const std::string &rentMath)
 {
 	Estate *destination = pTurn->destination();
+	if (destination) {
+		std::vector<Estate *>::iterator it;
+
+		// find current player estate
+		for (it = m_estates.begin(); it != m_estates.end(); it++) {
+			if (*it == pTurn->estate()) {
+				it++;
+				break;
+			}
+		}
 
-	if (destination)
-	{
-		bool useNext = false;
 		unsigned int money = 0;
-		Estate *estate = 0;
-		for (std::vector<Estate *>::iterator it = m_estates.begin() ;;)
-		{
-			if (it == m_estates.end())
-			{
+		while (1) {
+			if (it == m_estates.end()) {
 				it = m_estates.begin();
-				continue;
 			}
+			Estate *estate = *it;
 
-			if (!(estate = *it))
-				break;
-
-			if (useNext)
-			{
-				if (estate->getIntProperty("passmoney"))
-				{
-					money += estate->getIntProperty("passmoney");
-					// Write incremental message for direct moves, token
-					// confirmation or timeout didn't do it yet.
-					if (directMove) {
-						Display display;
-						display.setText("%s passes %s and gets %d.", pTurn->getStringProperty("name").c_str(), estate->getStringProperty("name").c_str(), estate->getIntProperty("passmoney"));
-						sendDisplayMsg(&display);
-					}
+			if (estate->getIntProperty("passmoney")) {
+				money += estate->getIntProperty("passmoney");
+				// Write incremental message for direct moves, token
+				// confirmation or timeout didn't do it yet.
+				if (directMove) {
+					Display display;
+					display.setText("%s passes %s and gets %d.", pTurn->getStringProperty("name").c_str(), estate->getStringProperty("name").c_str(), estate->getIntProperty("passmoney"));
+					sendDisplayMsg(&display);
 				}
-				if (estate == destination)
-					break;
 			}
-			else if (estate == pTurn->estate())
-				useNext = true;
 
-			++it;
+			if (estate == destination) {
+				break;
+			}
+
+			it++;
 		}
 		pTurn->setEstate(destination);
 		pTurn->setDestination(0);
@@ -1682,7 +1670,6 @@ bool Game::landPlayer(Player *pTurn, const bool directMove, const std::string &r
 	// sent earlier.
 
 	// What properties does the estate we are landing on have?
-	bool endTurn = true;
 	Player *pOwner = 0;
 	Estate *es = pTurn->estate();
 
@@ -1713,7 +1700,7 @@ bool Game::landPlayer(Player *pTurn, const bool directMove, const std::string &r
 			ioError("This gameboard does not have a jail estate.");
 
 		updateTurn();
-		return true;
+		return;
 	}
 
 	// Any estate can have a pot of gold. This is handled before all other
@@ -1745,7 +1732,7 @@ bool Game::landPlayer(Player *pTurn, const bool directMove, const std::string &r
 				sendDisplayMsg(&display);
 
 				newDebt(pTurn, 0, ePayTarget, estateMoney);
-				return false;
+				return;
 			}
 			else if (ePayTarget && getBoolConfigOption("collectfines"))
 				ePayTarget->addMoney(estateMoney);
@@ -1787,7 +1774,7 @@ bool Game::landPlayer(Player *pTurn, const bool directMove, const std::string &r
 
 				// TODO: port this into a blocking bool in Display which we can check, will be more generic
 				m_pausedForDialog = true;
-				return false;
+				return;
 			}
 		}
 		else
@@ -1805,7 +1792,7 @@ bool Game::landPlayer(Player *pTurn, const bool directMove, const std::string &r
 			sendDisplayMsg(&display);
 
 			newDebt(pTurn, 0, ePayTarget, payAmount);
-			return false;
+			return;
 		}
 		else if (ePayTarget && getBoolConfigOption("collectfines"))
 			ePayTarget->addMoney(payAmount);
@@ -1821,7 +1808,7 @@ bool Game::landPlayer(Player *pTurn, const bool directMove, const std::string &r
 		if (getBoolConfigOption("alwaysshuffle"))
 			cardGroup->shuffleCards();
 
-		endTurn = giveCard(pTurn, cardGroup->nextCard());
+		giveCard(pTurn, cardGroup->nextCard());
 	}
 
 	// Calculate rent for owned estates or offer them for sale.
@@ -1854,7 +1841,7 @@ bool Game::landPlayer(Player *pTurn, const bool directMove, const std::string &r
 					sendDisplayMsg(&display);
 
 					newDebt(pTurn, pOwner, 0, payAmount);
-					return false;
+					return;
 				}
 				Display display;
 				display.setText("%s pays %d rent to %s.", pTurn->getStringProperty("name").c_str(), payAmount, pOwner->getStringProperty("name").c_str());
@@ -1877,17 +1864,17 @@ bool Game::landPlayer(Player *pTurn, const bool directMove, const std::string &r
 			display.addButton(".ea", "Auction", (getBoolConfigOption("auctionsenabled") && totalAssets()));
 			display.addButton(".E", "End Turn", !getBoolConfigOption("auctionsenabled"));
 			pTurn->sendDisplayMsg(&display);
-			return false;
+			return;
 		}
 	}
-	return endTurn;
 }
-bool Game::giveCard(Player *pTurn, Card *card)
+
+void Game::giveCard(Player *pTurn, Card *card)
 {
 	if (!card)
 	{
 		ioError(pTurn->name() + " should get a card, but there don't seem to be any available!");
-		return true;
+		return;
 	}
 
 	Display display;
@@ -1922,7 +1909,6 @@ bool Game::giveCard(Player *pTurn, Card *card)
 				sendDisplayMsg(&display);
 
 				newDebt(pTurn, 0, ePayTarget, payAmount);
-				return false;
 			}
 			else if (ePayTarget && getBoolConfigOption("collectfines"))
 				ePayTarget->addMoney(payAmount);
@@ -2000,7 +1986,6 @@ bool Game::giveCard(Player *pTurn, Card *card)
 				sendDisplayMsg(&display);
 
 				newDebt(pTurn, 0, ePayTarget, payAmount);
-				return false;
 			}
 			else if (ePayTarget && getBoolConfigOption("collectfines"))
 				ePayTarget->addMoney(payAmount);
@@ -2022,9 +2007,8 @@ bool Game::giveCard(Player *pTurn, Card *card)
 			else
 				ioError("Could not find next estate on gameboard.");
 		}
-		return landPlayer(pTurn, true, card->rentMath());
+		landPlayer(pTurn, true, card->rentMath());
 	}
-	return true;
 }
 
 void Game::declareBankrupt(Player *pInput)
@@ -2054,7 +2038,7 @@ void Game::bankruptPlayer(Player *pBroke)
 		++it;
 	}
 
-	// highest bidder might be the player who just left
+	// highest bidder declared bankruptcy (or left)
 	if (m_auction && m_auction->highBidder() == pBroke) {
 		abortAuction();
 	}
@@ -2081,55 +2065,58 @@ void Game::bankruptPlayer(Player *pBroke)
 
 	// Player might still have assets, when he goes bankrupt without debts
 	// (disconnection timeout), so we'll enforce giving assets to the Bank.
-	if (pBroke->assets())
-		enforceDebt(pBroke);
+	enforceDebt(pBroke);
 
 	// Count active (non-bankrupt) players
 	int activePlayers = 0;
 	Player *pTmp = 0;
+	Player *pWinner = 0;
 	for(std::vector<Player *>::iterator it = m_players.begin(); it != m_players.end() && (pTmp =  *it) ; ++it)
 		if (pTmp && !pTmp->getBoolProperty("bankrupt") && !pTmp->getBoolProperty("spectator"))
 		{
 			activePlayers++;
-			m_pWinner = pTmp;
+			pWinner = pTmp;
 		}
 
-	if (activePlayers == 1)
-	{
+	if (activePlayers == 1) {
 		// a user who disconnect might end the game while an auction was running
 		abortAuction();
+		// game might be ended if a player left while a player was moving
+		setAllClientsMoving(0);
 
 		m_status = End;
 		setProperty("status", "end");
-		syslog(LOG_INFO, "game %d ended: %s wins with a fortune of %d.", m_id, m_pWinner->name().c_str(), m_pWinner->assets());
+		syslog(LOG_INFO, "game %d ended: %s wins with a fortune of %d.", m_id, pWinner->name().c_str(), pWinner->assets());
 		setBoolProperty("canbewatched", false);
 
 		Display display;
 		display.resetButtons();  /* Reset any button, game might end if a player left while we were asked to buy an estate for example */
-		display.setText("The game has ended! %s wins with a fortune of %d!", m_pWinner->getStringProperty("name").c_str(), m_pWinner->assets());
+		display.setText("The game has ended! %s wins with a fortune of %d!", pWinner->getStringProperty("name").c_str(), pWinner->assets());
 		display.addButton(".gx", "New Game", true);
 		sendDisplayMsg(&display);
+
+		m_pTurn->setTurn(false);
+		m_pTurn = NULL;
+		return;
 	}
-	else
-	{
-		m_pWinner = 0;
 
-		if (activePlayers && !m_debts.size())
-		{
-			if (debtsWereSolved) {
-				Display display;
-				display.setText("All debts are settled, game continues.");
-				sendDisplayMsg(&display);
-			}
+	if (m_debts.size()) {
+		return;
+	}
 
-			// Update turn. Always when this function is called as command
-			// and possibly necessary when this function is called for a
-			// disconnected user.
+	if (debtsWereSolved) {
+		Display display;
+		display.setText("All debts are settled, game continues.");
+		sendDisplayMsg(&display);
+	}
 
-			if (pBroke == m_pTurn)
-				updateTurn();
-		}
+	if (pBroke == m_pTurn) {
+		updateTurn();
+		return;
 	}
+
+	// necessary when an auction bidder cannot pay and then declared bankruptcy
+	m_pTurn->endTurn();
 }
 
 int Game::totalAssets()
@@ -2172,19 +2159,21 @@ int Game::debts()
 unsigned int Game::clientsMoving()
 {
 	unsigned int moving = 0;
-	Player *pTmp = 0;
-	for(std::vector<Player *>::iterator it = m_players.begin(); it != m_players.end() && (pTmp = *it) ; ++it)
-		if (pTmp->tokenLocation())
+	for(std::vector<Player *>::iterator it = m_players.begin(); it != m_players.end(); ++it) {
+		if ((*it)->tokenLocation()) {
 			moving++;
+		}
+	}
 	return moving;
 }
 
 void Game::setAllClientsMoving(Estate *estate)
 {
-	Player *pTmp = 0;
-	for(std::vector<Player *>::iterator it = m_players.begin(); it != m_players.end() && (pTmp = *it) ; ++it)
-	if (pTmp->socket())
-		pTmp->setTokenLocation(estate);
+	for(std::vector<Player *>::iterator it = m_players.begin(); it != m_players.end(); ++it) {
+		if ((*it)->socket()) {
+			(*it)->setTokenLocation(estate);
+		}
+	}
 }
 
 void Game::sendStatus(Status status, Player *p)
diff --git a/src/game.h b/src/game.h
index f722e95..4fd1e4e 100644
--- a/src/game.h
+++ b/src/game.h
@@ -85,8 +85,8 @@ class Game : public GameObject
 		unsigned int playerAssets(Player *player);
 
 		void updateTurn();
-		bool landPlayer(Player *pTurn, const bool directMove, const std::string &rentmath = "");
-		bool giveCard(Player *player, Card *card);
+		void landPlayer(Player *pTurn, const bool directMove, const std::string &rentmath = "");
+		void giveCard(Player *player, Card *card);
 		void declareBankrupt(Player *player);
 		void bankruptPlayer(Player *player);
 		void sendDisplayMsg(Display *display, Player *except = NULL);
@@ -105,7 +105,6 @@ class Game : public GameObject
 		Debt *findDebtByCreditor(Player *player);
 		void delDebt(Debt *);
 		void solveDebts(Player *player, const bool &verbose = false);
-		bool solveDebt(Debt *debt);
 		void enforceDebt(Player *pBroke, Debt *debt = 0);
 		void newAuction(Player *pInput);
 		Auction *auction();
@@ -163,10 +162,12 @@ private:
 	 */
 	GameObject *newConfigOption(const std::string &name, const std::string &description, bool editable);
 
+	bool solveDebt(Debt *debt);
+
 	Status m_status;
 	unsigned int m_nextCardGroupId, m_nextEstateId, m_nextEstateGroupId, m_nextTradeId, m_nextAuctionId;
 
-	Player *m_master, *m_pTurn, *m_pWinner;
+	Player *m_master, *m_pTurn;
 	Estate *m_goEstate;
 	int m_houses, m_hotels, m_startMoney;
 	bool m_isValid, m_pausedForDialog;
diff --git a/src/player.cpp b/src/player.cpp
index b5eac32..c926c36 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -278,32 +278,54 @@ void Player::rollDice()
 
 void Player::endTurn(bool userRequest)
 {
-	if (m_game->status() == Game::End)
+	if (!getBoolProperty("hasturn")) {
+		if (userRequest)
+			ioError("You cannot end your turn, this is not your turn.");
 		return;
+	}
 
-	if (!getBoolProperty("hasturn"))
+	if (m_game->pausedForDialog()) {
+		if (userRequest)
+			ioError("You cannot end your turn, you must answer the dialog first.");
 		return;
+	}
 
-	if (m_game->findDebt(this))
-    {
-    	if (userRequest)
-    		ioError("You have a debt, cannot end turn.");
-    	return;
-    }
+	if (m_game->auction()) {
+		if (userRequest)
+			ioError("You cannot end your turn, an auction is in progress.");
+		return;
+	}
 
-	if (getBoolProperty("can_buyestate"))
-	{
-		if (m_game->getBoolConfigOption("auctionsenabled"))
-		{
-			if (userRequest)
-				ioError("You cannot end your turn, you must either buy or auction the property you are on.");
+	if (m_game->clientsMoving()) {
+		if (userRequest)
+			ioError("You cannot end your turn, other players are still moving.");
+		return;
+	}
+
+	if (m_game->debts()) {
+		if (userRequest)
+			ioError("You cannot end your turn, there are debts to be settled.");
+		return;
+	}
+
+	if (getBoolProperty("can_buyestate")) {
+		if (!userRequest) {
 			return;
 		}
-		else if (!userRequest)
+
+		if (m_game->getBoolConfigOption("auctionsenabled")) {
+			ioError("You cannot end your turn, you must either buy or auction the property you are on.");
 			return;
+		}
+
+		setBoolProperty("can_buyestate", false);
+		setBoolProperty("canauction", false);
+		Display display;
+		display.resetButtons(); /* Remove buy estate buttons: Buy, Auction, End Turn */
+		sendDisplayMsg(&display);
 	}
-	else if (getBoolProperty("canrollagain"))
-	{
+
+	if (getBoolProperty("canrollagain")) {
 		Display display;
 		display.setText("%s may roll again.", getStringProperty("name").c_str());
 		m_game->sendDisplayMsg(&display, this);
@@ -314,32 +336,19 @@ void Player::endTurn(bool userRequest)
 		setBoolProperty("canrollagain", false);
 		return;
 	}
-	else if (getBoolProperty("can_roll"))
-	{
+
+	if (getBoolProperty("can_roll")) {
 		if (userRequest)
 			ioError("You cannot end your turn, you must roll first!");
 		return;
 	}
-	else if (getBoolProperty("jailed"))
-	{
-		if (userRequest)
-			ioError("You cannot end your turn while jailed.");
-		return;
-	}
 
-	else if (m_game->pausedForDialog())
-	{
+	if (getBoolProperty("jailed")) {
 		if (userRequest)
-			ioError("You must answer the dialog first.");
+			ioError("You cannot end your turn while jailed.");
 		return;
 	}
 
-	if (userRequest) {
-		Display display;
-		display.resetButtons(); /* Remove buy estate buttons: Buy, Auction, End Turn */
-		sendDisplayMsg(&display);
-	}
-
 	// Turn goes to next player
 	m_game->updateTurn();
 }
diff --git a/src/server.cpp b/src/server.cpp
index 26e9c08..8e0a469 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -475,7 +475,7 @@ int MonopdServer::timeleftEvent()
 		}
 
 		timersub(event->launchTime(), &timenow, &timeres);
-		// add 1ms to adjust for precision lost in tv_usec/10000
+		// add 1ms to adjust for precision lost in tv_usec/1000
 		timems = (timeres.tv_sec*1000 + timeres.tv_usec/1000) +1;
 		if (timeleft > timems) {
 			timeleft = timems;
@@ -1016,7 +1016,7 @@ void MonopdServer::processInput(Socket *socket, const std::string data2)
 	}
 
 	if (game->clientsMoving()) {
-		pInput->ioNoSuchCmd("other clients are still moving");
+		pInput->ioNoSuchCmd("other players are still moving");
 		// The rest of the commands are only available when no clients are moving
 		return;
 	}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/monopd.git



More information about the Pkg-games-commits mailing list