TurnController.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <vector>
00022 #include <set>
00023 #include <server/TurnController.h>
00024 #include <server/ScorchedServer.h>
00025 #include <tank/TankContainer.h>
00026 #include <tank/TankSort.h>
00027 #include <tank/TankState.h>
00028 #include <common/OptionsTransient.h>
00029 #include <common/Defines.h>
00030 
00031 TurnController *TurnController::instance_ = 0;
00032 
00033 TurnController *TurnController::instance()
00034 {
00035         if (!instance_)
00036         {
00037                 instance_ = new TurnController;
00038         }
00039         return instance_;
00040 }
00041 
00042 TurnController::TurnController()
00043 {
00044 }
00045 
00046 TurnController::~TurnController()
00047 {
00048 }
00049 
00050 void TurnController::newGame()
00051 {
00052         playerOrder_.clear();
00053 
00054         OptionsGame::TurnType turnType = (OptionsGame::TurnType)
00055                 ScorchedServer::instance()->getOptionsGame().getTurnType().getValue();
00056 
00057         // On the very first round make the order random (if looser first chosen)
00058         // as there is no looser yet!
00059         if ((ScorchedServer::instance()->getOptionsTransient().getCurrentRoundNo() == 1) &&
00060                 turnType == OptionsGame::TurnSequentialLooserFirst)
00061         {
00062                 turnType = OptionsGame::TurnSequentialRandom;
00063         }
00064 
00065         // Standard player ordering is the reverse of the tank score
00066         TankSort::getSortedTanksIds(
00067                 ScorchedServer::instance()->getContext(), 
00068                 playerOrder_,
00069                 true); // All tanks
00070         playerOrder_.reverse();
00071 
00072         // Check for a different ordering
00073         if (turnType == OptionsGame::TurnSequentialRandom)
00074         {
00075                 // Create zero player vector
00076                 std::vector<unsigned int> tmpPlayers;
00077                 for (int i=0; i<(int) playerOrder_.size(); i++)
00078                         tmpPlayers.push_back(0);
00079 
00080                 // Randomize list order into vector
00081                 while (!playerOrder_.empty())
00082                 {
00083                         unsigned int player = playerOrder_.front();
00084                         playerOrder_.pop_front();
00085                         bool done = false;
00086                         while (!done)
00087                         {
00088                                 int pos = int(RAND * float(tmpPlayers.size()));
00089                                 if (pos < int(tmpPlayers.size()) && tmpPlayers[pos] == 0) 
00090                                 {
00091                                         tmpPlayers[pos] = player;
00092                                         done = true;
00093                                 }
00094                         }
00095                 }
00096 
00097                 // Copy vector back to list
00098                 for (int i=0; i<(int) tmpPlayers.size(); i++)
00099                         playerOrder_.push_back(tmpPlayers[i]);
00100         }
00101 }
00102 
00103 void TurnController::nextRound()
00104 {
00105         // Initialize so all players are still to play
00106         playersLeftToMove_.clear();
00107         playersLeftToMove_ = playerOrder_;
00108 }
00109 
00110 void TurnController::nextShot()
00111 {
00112         playersThisShot_.clear();
00113 
00114         OptionsGame::TurnType turnType = (OptionsGame::TurnType)
00115                 ScorchedServer::instance()->getOptionsGame().getTurnType().getValue();
00116                 
00117         // Game number 0 is the weapons choosing round, so every one can do this
00118         // concurrently
00119         if (ScorchedServer::instance()->getOptionsTransient().getCurrentGameNo() == 0)
00120         {
00121                 turnType = OptionsGame::TurnSimultaneous;
00122         }
00123 
00124         // Choose the next player(s) based on game mode
00125         if (turnType == OptionsGame::TurnSequentialRandom ||
00126                 turnType == OptionsGame::TurnSequentialLooserFirst)
00127         {
00128                 // Get the first normal state player and add them to the shot list
00129                 // only this player should make a shot
00130                 Tank *nextTank = 0;
00131                 while (!nextTank || 
00132                         (nextTank->getState().getState() != TankState::sNormal))
00133                 {
00134                         if (playersLeftToMove_.empty()) return; // No valid players, next round
00135                         unsigned int player = playersLeftToMove_.front();
00136                         playersLeftToMove_.pop_front();
00137                         nextTank = ScorchedServer::instance()->getTankContainer().getTankById(player);
00138                 }
00139 
00140                 // Make it this players turn
00141                 playersThisShot_.push_back(nextTank->getPlayerId());
00142         }
00143         else if (turnType == OptionsGame::TurnSimultaneous)
00144         {
00145                 // Move all normal state players into the shot list
00146                 // as all players should make a shot the same time
00147                 std::list<unsigned int>::iterator itor;
00148                 for (itor = playersLeftToMove_.begin();
00149                         itor != playersLeftToMove_.end();
00150                         itor++)
00151                 {
00152                         unsigned int player = *itor;
00153 
00154                         Tank *nextTank = 
00155                                 ScorchedServer::instance()->getTankContainer().getTankById(player);
00156                         if (nextTank &&
00157                                 (nextTank->getState().getState() == TankState::sNormal))
00158                         {
00159                                 // Player is ready and it is their turn
00160                                 playersThisShot_.push_back(nextTank->getPlayerId());
00161                         }
00162                 }
00163 
00164                 // All players should play this shot
00165                 playersLeftToMove_.clear();
00166         }
00167         else
00168         {
00169                 S3D::dialogMessage("TurnController::ready - ",
00170                         S3D::formatStringBuffer("Unknown type %i", turnType));
00171         }
00172 }
00173 
00174 void TurnController::nextTurn()
00175 {
00176         playersThisTurn_.clear();
00177 
00178         std::set<unsigned int> usedDestinations;
00179         std::list<unsigned int> removePlayers;
00180         std::list<unsigned int>::iterator itor;
00181         for (itor = playersThisShot_.begin();
00182                 itor != playersThisShot_.end();
00183                 itor++)
00184         {
00185                 unsigned int player = *itor;
00186                 Tank *nextTank = 
00187                         ScorchedServer::instance()->getTankContainer().getTankById(player);             
00188                 if (nextTank &&
00189                         (nextTank->getState().getState() == TankState::sNormal))
00190                 {
00191                         if (nextTank->getDestinationId() == 0)
00192                         {
00193                                 removePlayers.push_back(player);
00194                                 playersThisTurn_.push_back(player);
00195                         }
00196                         else if (usedDestinations.find(nextTank->getDestinationId()) == usedDestinations.end())
00197                         {
00198                                 removePlayers.push_back(player);
00199                                 playersThisTurn_.push_back(player);
00200                                 usedDestinations.insert(nextTank->getDestinationId());
00201                         }
00202                 }
00203         }
00204 
00205         for (itor = removePlayers.begin();
00206                 itor != removePlayers.end();
00207                 itor++)
00208         {
00209                 unsigned int player = *itor;
00210                 playersThisShot_.remove(player);
00211         }
00212 }
00213 
00214 bool TurnController::playerThisTurn(unsigned int playerId)
00215 {
00216         std::list<unsigned int>::iterator itor;
00217         for (itor = playersThisTurn_.begin();
00218                 itor != playersThisTurn_.end();
00219                 itor++)
00220         {
00221                 unsigned int player = *itor;
00222                 if (playerId == player) return true;
00223         }
00224         return false;
00225 }

Generated on Mon Feb 16 15:14:53 2009 for Scorched3D by  doxygen 1.5.3