Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List

Bombing.cpp

00001 /*
00002 Copyright 2003 - 2005 Grant Speelman, Elliott Kleinrock
00003 
00004 This file is part of FreeStars, a free clone of the Stars! game.
00005 
00006 FreeStars 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 FreeStars 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 FreeStars; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 The full GPL Copyright notice should be in the file COPYING.txt
00021 
00022 */
00023 #include <map>
00024 
00025 #include "FSServer.h"
00026 
00027 #include "Bombing.h"
00028 #include "Component.h"
00029 #include "algorithm"
00030 
00031 #ifdef _DEBUG
00032 #define new DEBUG_NEW
00033 #endif
00034 
00035 
00036 Bombing::Bombing(const Location & loc) : Location(loc)
00037 {
00038         mTargetPlanet = NULL;
00039         mPopulationLoss = 0;
00040         mMinesLoss = mFactoriesLoss = mDefensesLoss = 0;
00041 }
00042 
00043 
00044 Bombing::~Bombing()
00045 {
00046 }
00047 
00048 void Bombing::SetPlanet(Planet* targetPlanet)
00049 {
00050         mTargetPlanet = targetPlanet;
00051 }
00052 
00053 void Bombing::AddFleets()
00054 {
00055         // Find all fleets orbiting the planet that want to Bomb it
00056         for (unsigned int j = 0; j < TheGame->NumberPlayers(); ++j )
00057         {
00058                 Player* player = TheGame->NCGetPlayer(j);
00059                         
00060                 if(player->AddBombingFleets(this,mTargetPlanet->GetOwner(),BT_NORMAL))
00061                         mNormalBombingPlayers.push_back(player);
00062                         
00063                 if(player->AddBombingFleets(this,mTargetPlanet->GetOwner(),BT_SMART))
00064                         mSmartBombingPlayers.push_back(player);
00065                 
00066                 if(player->AddBombingFleets(this,mTargetPlanet->GetOwner(),BT_TERRA))
00067                         mTerraBombingPlayers.push_back(player);
00068         }
00069 }
00070 
00071 double Bombing::GetSmartKillper() const
00072 {
00073         // Smart bombs do *not* add linearly; instead, they use this formula:
00074         // (1 - multiply[ (1 - kill_perc(n)^#n) ])
00075 
00076         // Where "multiply[x(n)]" is the math "big-pi" operator, which means
00077         // multiply all the terms together, i.e.:
00078         //multiply[x(n)] = x(n1)*x(n2)*x(n3)... *x(ni) 
00079         
00080         map<const Component*,int> bombtype_count;
00081 
00082         // TODO This could possible be optimize
00083         for (deque<Fleet*>::const_iterator k = mSmartBombingFleets.begin(); k != mSmartBombingFleets.end(); ++k)
00084         {
00085                 for(deque<Stack>::const_iterator i = (*k)->mStacks.begin(); i != (*k)->mStacks.end(); ++i)
00086                 {
00087                         for(deque<Slot>::const_iterator j = i->mShip->mSlots.begin(); j != i->mShip->mSlots.end(); ++j )
00088                         {
00089                                 const Component* comp = j->GetComp();
00090                                 if(comp->IsType(CT_BOMB) && comp->GetBombType() == BT_SMART)
00091                                 {
00092                                         if(bombtype_count.count(comp) == 0)
00093                                                 bombtype_count[comp] = 1;
00094                                         else
00095                                                 bombtype_count[comp]++;
00096                                 }
00097                         }
00098                 }
00099         }
00100         
00101         double killper = 1;
00102         for (map<const Component*,int>::const_iterator t = bombtype_count.begin(); t != bombtype_count.end(); ++t)
00103         {
00104                 double base = t->first->GetSmartKillper();
00105                 double result = 1 - pow(base,t->second);
00106                 killper *= result;
00107         }
00108         
00109         return killper;
00110 }
00111 
00112 void Bombing::DoPopulationLosses(const double& normal_killper, const long& normal_minimum , const double& smart_killper)
00113 {
00114         long population_loss = 0;
00115         long population = mTargetPlanet->GetPopulation();
00116         double normal_coverage = 1.0 - mTargetPlanet->GetDefenseValue();
00117         double smart_coverage = 1.0 - mTargetPlanet->GetSmartDefenseValue();
00118         
00119         // killper or minimum for normal bombing
00120         if((normal_killper * normal_coverage * population) > (normal_minimum * normal_coverage))
00121                 population_loss += static_cast<long>(normal_killper * normal_coverage * population);
00122         else
00123                 population_loss += static_cast<long>(normal_minimum * normal_coverage);
00124         
00125         // add smart bombing killper
00126         population_loss += static_cast<long>(smart_killper * smart_coverage);
00127         
00128         //Apply Losses
00129         mTargetPlanet->AdjustPopulation(-mPopulationLoss);
00130 }
00131 
00132 void Bombing::DoInstallationLosses(const long& installation_loss)
00133 {
00134         long installations_sum = mTargetPlanet->GetFactories() + mTargetPlanet->GetMines() + mTargetPlanet->GetDefenses();
00135         double coverage = 1.0 - mTargetPlanet->GetInstallationDefenseValue();
00136         
00137         // Calculate Losses
00138         if(long(installation_loss * coverage) > installations_sum)
00139         {
00140                 mFactoriesLoss = mTargetPlanet->GetFactories();
00141                 mMinesLoss = mTargetPlanet->GetMines();
00142                 mDefensesLoss = mTargetPlanet->GetDefenses();
00143         }
00144         else
00145         {
00146                 double factories_ratio, mines_ratio, defenses_ratio;
00147                 factories_ratio = mTargetPlanet->GetFactories() / installations_sum;
00148                 mines_ratio = mTargetPlanet->GetMines() / installations_sum;
00149                 defenses_ratio = mTargetPlanet->GetDefenses() / installations_sum;
00150                 
00151                 mFactoriesLoss = long(factories_ratio * installation_loss + 0.5);
00152                 mDefensesLoss = long(defenses_ratio * installation_loss + 0.5);
00153                 mMinesLoss = long(mines_ratio * installation_loss + 0.5);
00154         }
00155         
00156         // Apply Losses
00157         mTargetPlanet->AdjustFactories(-mFactoriesLoss);
00158         mTargetPlanet->AdjustFactories(-mMinesLoss);
00159         mTargetPlanet->AdjustDefenses(-mDefensesLoss);
00160 }
00161 
00162 void Bombing::DoTerraTransforming()
00163 {
00164         for (deque<Fleet*>::iterator k = mTerraBombingFleets.begin(); k != mTerraBombingFleets.end(); ++k)
00165         {
00166                 (*k)->RemoteTerraform(true);
00167         }
00168 }
00169 
00170 void Bombing::Resolve()
00171 {
00172         // Are there any Fleets
00173         if( mSmartBombingFleets.size() == 0 && mNormalBombingFleets.size() == 0 && mTerraBombingFleets.size() == 0)
00174                 return;
00175                 
00176         // Calculate Total bombing  
00177         double normal_killper = 0.0;
00178         double smart_killper = 0.0;
00179         long normal_minimum = 0;
00180         long installation_loss = 0;
00181         
00182         // Calculate Normal bombing (Sum up bombing)
00183         for (deque<Fleet*>::iterator k = mNormalBombingFleets.begin(); k != mNormalBombingFleets.end(); ++k)
00184         {
00185                 normal_killper += (*k)->GetNormalKillper();
00186                 normal_minimum += (*k)->GetMinKill();
00187                 installation_loss += (*k)->GetInstKill();
00188         }
00189         
00190         smart_killper = GetSmartKillper();
00191         
00192         // percentage stopped 
00193         mNormalPercentageStopped = mTargetPlanet->GetDefenseValue();
00194         mSmartPercentageStopped = mTargetPlanet->GetSmartDefenseValue();
00195         
00196         // Population Loss
00197         DoPopulationLosses(normal_killper,normal_minimum,smart_killper);
00198         
00199         // Installation Losses 
00200         DoInstallationLosses(installation_loss);
00201         
00202         // check if planet is now uninhabited later in turn processing, don't check now
00203         
00204         // Do Remote Terrraforming
00205         DoTerraTransforming();
00206                         
00207         // Send Messages To Everyone
00208         SendMessages();
00209 }
00210 
00211 void Bombing::SendNormalMessages() 
00212 {
00213         // Check if there was a bomb
00214         if(mNormalBombingPlayers.size() == 0)
00215                 return;
00216                 
00217         // First to Planet Owner
00218         Message * mess = mTargetPlanet->AddMessageOwner("PlanetBombed");
00219         mess->AddItem("Target", this);
00220         mess->AddLong("Population lost", mPopulationLoss);
00221         mess->AddFloat("Defense effectiveness", mNormalPercentageStopped);
00222         mess->AddLong("Factories lost", mFactoriesLoss);
00223         mess->AddLong("Mines lost", mMinesLoss);
00224         mess->AddLong("Defenses lost", mDefensesLoss);
00225         
00226         // Other Players
00227         for (deque<Player*>::iterator i = mNormalBombingPlayers.begin(); i != mNormalBombingPlayers.end(); ++i)
00228         {
00229                 Message * mess = (*i)->AddMessage("FleetBombed");
00230                 mess->AddItem("Target", this);
00231                 mess->AddLong("Population lost", mPopulationLoss);
00232                 mess->AddFloat("Defense effectiveness", mNormalPercentageStopped);
00233                 mess->AddLong("Installations lost", mFactoriesLoss + mMinesLoss + mDefensesLoss);
00234         }
00235 }
00236 
00237 void Bombing::SendTerraMessages() 
00238 {
00239         // Check if there was a bomb
00240         if(mTerraBombingPlayers.size() == 0)
00241                 return;
00242                 
00243         // First to Planet Owner
00244         Message * mess = mTargetPlanet->AddMessageOwner("PlanetTerraBombed");
00245         mess->AddItem("Target", this);
00246         // TODO add needed data
00247 
00248         
00249         // Other Players
00250         for (deque<Player*>::iterator i = mTerraBombingPlayers.begin(); i != mTerraBombingPlayers.end(); ++i)
00251         {
00252                 Message * mess = (*i)->AddMessage("FleetTerraBombed");
00253                 mess->AddItem("Target", this);
00254                 // TODO add needed data
00255 
00256         }
00257 }
00258 
00259 
00260 void Bombing::SendSmartMessages() 
00261 {
00262         // Check if there was a bomb
00263         if(mSmartBombingPlayers.size() == 0)
00264                 return;
00265                 
00266         // First to Planet Owner
00267         Message * mess = mTargetPlanet->AddMessageOwner("PlanetSmartBombed");
00268         mess->AddItem("Target", this);
00269         mess->AddLong("Population lost", mPopulationLoss);
00270         mess->AddFloat("Defense effectiveness", mSmartPercentageStopped);
00271         
00272         // Other Players
00273         for (deque<Player*>::iterator i = mSmartBombingPlayers.begin(); i != mSmartBombingPlayers.end(); ++i)
00274         {
00275                 Message * mess = (*i)->AddMessage("FleetSmartBombed");
00276                 mess->AddItem("Target", this);
00277                 mess->AddLong("Population lost", mPopulationLoss);
00278                 mess->AddFloat("Defense effectiveness", mSmartPercentageStopped);
00279         }
00280 }

Generated on Mon Aug 8 21:33:42 2005 for Freestars by  doxygen 1.4.2-20050421