TankAIAdder.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 <set>
00022 #include <tankai/TankAIAdder.h>
00023 #include <tankai/TankAIStore.h>
00024 #include <tankai/TankAIStrings.h>
00025 #include <tank/TankColorGenerator.h>
00026 #include <tank/TankContainer.h>
00027 #include <tank/TankModelStore.h>
00028 #include <tank/TankAvatar.h>
00029 #include <tank/TankModelContainer.h>
00030 #include <tank/TankState.h>
00031 #include <server/ServerState.h>
00032 #include <coms/ComsAddPlayerMessage.h>
00033 #include <coms/ComsMessageSender.h>
00034 #include <coms/ComsPlayerStateMessage.h>
00035 #include <common/OptionsScorched.h>
00036 #include <common/OptionsTransient.h>
00037 #include <common/Logger.h>
00038 #include <common/StatsLogger.h>
00039 #include <common/Defines.h>
00040 
00041 unsigned int TankAIAdder::getNextTankId(const char *uniqueId, ScorchedContext &context)
00042 {
00043         // Try to use the persistent stats id
00044         if (uniqueId[0])
00045         {
00046                 unsigned int id = StatsLogger::instance()->getStatsId(uniqueId);
00047                 if (id != 0 &&
00048                         !context.getTargetContainer().getTargetById(id))
00049                 {
00050                         DIALOG_ASSERT(id >= TargetID::MIN_TANK_ID && id <= TargetID::MAX_TANK_ID);
00051                         return id;
00052                 }
00053         }
00054 
00055         // Get the transient id
00056         static unsigned int id = TargetID::START_TRANSIENT_TANK_ID;
00057         while (context.getTargetContainer().getTargetById(id))
00058         {
00059                 ++id;
00060                 if (id >= TargetID::MAX_TANK_ID) id = TargetID::START_TRANSIENT_TANK_ID;
00061         }
00062 
00063         DIALOG_ASSERT(id >= TargetID::START_TRANSIENT_TANK_ID && id <= TargetID::MAX_TANK_ID);
00064         return id;
00065 }
00066 
00067 unsigned int TankAIAdder::getNextTargetId(ScorchedContext &context)
00068 {
00069         unsigned int targetId_ = TargetID::MIN_TARGET_TRANSIENT_ID;
00070         while (context.getTargetContainer().getTargetById(targetId_))
00071         {
00072                 ++targetId_;
00073                 if (targetId_ >= TargetID::MAX_TARGET_ID) targetId_ = TargetID::MIN_TARGET_TRANSIENT_ID;
00074         }
00075 
00076         return targetId_;
00077 }
00078 
00079 void TankAIAdder::addTankAIs(ScorchedServer &context)
00080 {
00081         // On the server
00082         // Ensure that we cannot add more ais than the server is setup for
00083         int maxComputerAIs = context.getOptionsGame().getNoMaxPlayers();
00084         for (int i=0; i<maxComputerAIs; i++)
00085         {
00086                 const char *playerType = 
00087                         context.getOptionsGame().getPlayerType(i);
00088                 if (0 != stricmp(playerType, "Human"))
00089                 {
00090                         addTankAI(context, playerType);
00091                 }
00092         }
00093 }
00094 
00095 void TankAIAdder::addTankAI(ScorchedServer &context, const char *aiName)
00096 {
00097         TankAI *ai = context.getTankAIs().getAIByName(aiName);
00098         if (ai)
00099         {
00100                 // Create our uniqueid
00101                 char uniqueId[256];
00102                 {
00103                         std::set<int> usedIds;
00104                         snprintf(uniqueId, 256, "%s - computer - %%i", aiName);
00105                         std::map<unsigned int, Tank *> &playingTanks = 
00106                                 context.getTankContainer().getPlayingTanks();
00107                         std::map<unsigned int, Tank *>::iterator playingItor;
00108                         for (playingItor = playingTanks.begin();
00109                                 playingItor != playingTanks.end();
00110                                 playingItor++)
00111                         {
00112                                 Tank *current = (*playingItor).second;
00113                                 if (current->getDestinationId() == 0)
00114                                 {
00115                                         int id = 1;
00116                                         if (sscanf(current->getUniqueId(), uniqueId, &id) == 1)
00117                                         {
00118                                                 usedIds.insert(id);
00119                                         }
00120                                 }
00121                         }
00122 
00123                         int uniqueIdCount = 1;
00124                         while (usedIds.find(uniqueIdCount) != usedIds.end()) uniqueIdCount++;
00125 
00126                         snprintf(uniqueId, 256, "%s - computer - %i", aiName, uniqueIdCount);
00127                 }
00128 
00129                 // Chose this tanks team
00130                 int team = 0;
00131                 if (context.getOptionsGame().getTeams() > 1)
00132                 {
00133                         team = context.getOptionsTransient().getLeastUsedTeam(
00134                                 context.getTankContainer());
00135                 }
00136 
00137                 // For the tank ai's name
00138                 LangString newname = 
00139                         LANG_STRING(context.getOptionsGame().getBotNamePrefix());
00140                 newname += LANG_STRING(TankAIStrings::instance()->getAIPlayerName(
00141                         ScorchedServer::instance()->getContext()));
00142 
00143                 // Form the tank ai model
00144                 Vector color = TankColorGenerator::instance()->getNextColor(
00145                         context.getTankContainer().getPlayingTanks());
00146                 TankModel *tankModel = 
00147                         context.getTankModels().getRandomModel(team, false);
00148 
00149                 // Create the new tank
00150                 Tank *tank = new Tank(
00151                         context.getContext(),
00152                         getNextTankId(uniqueId, context.getContext()),
00153                         0,
00154                         newname,
00155                         color,
00156                         tankModel->getName(),
00157                         tankModel->getTypeName());
00158 
00159                 tank->getAvatar().loadFromFile(S3D::getDataFile("data/avatars/computer.png"));
00160                 tank->setUniqueId(uniqueId);
00161                 tank->setTankAI(ai->createCopy(tank));
00162                 tank->getState().setState(TankState::sInitializing);
00163                 tank->getState().setState(TankState::sPending);
00164                 context.getTankContainer().addTank(tank);
00165 
00166                 if (context.getOptionsGame().getTeams() > 1)
00167                 {
00168                         tank->setTeam(team);
00169                 }
00170 
00171                 Logger::log(S3D::formatStringBuffer("Player connected dest=\"%i\" id=\"%i\" name=\"%s\" unique=[%s]",
00172                         tank->getDestinationId(),
00173                         tank->getPlayerId(),
00174                         tank->getCStrName().c_str(),
00175                         tank->getUniqueId()));
00176 
00177                 StatsLogger::instance()->tankConnected(tank);
00178                 StatsLogger::instance()->tankJoined(tank);
00179 
00180                 if (true) // Raise an event
00181                 {
00182                         // Tell the clients to create this tank
00183                         ComsAddPlayerMessage addPlayerMessage(
00184                                 tank->getPlayerId(),
00185                                 tank->getTargetName(),
00186                                 tank->getColor(),
00187                                 tank->getModelContainer().getTankModelName(),
00188                                 tank->getModelContainer().getTankTypeName(),
00189                                 tank->getDestinationId(),
00190                                 tank->getTeam(),
00191                                 ""); 
00192                         addPlayerMessage.setPlayerIconName(tank->getAvatar().getName());
00193                         addPlayerMessage.getPlayerIcon().addDataToBuffer(
00194                                 tank->getAvatar().getFile().getBuffer(),
00195                                 tank->getAvatar().getFile().getBufferUsed());
00196                         ComsMessageSender::sendToAllConnectedClients(addPlayerMessage);
00197                 }
00198 
00199                 if (context.getGameState().getState() == ServerState::ServerStateTooFewPlayers ||
00200                         context.getGameState().getState() == ServerState::ServerStateStarting)
00201                 {
00202                         ComsPlayerStateMessage message(false, false);
00203                         ComsMessageSender::sendToAllConnectedClients(message);
00204                 }
00205         }
00206 }

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