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 }
1.5.3