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

Galaxy.cpp

00001 /*
00002 Copyright 2003 - 2005 Elliott Kleinrock, Dan Neely, Kurt W. Over, Damon Domjan
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 Contact:
00023 Email Elliott at 9jm0tjj02@sneakemail.com
00024 */
00025 
00026 #include "FSServer.h"
00027 
00028 #include "Packet.h"
00029 #include "Bombing.h"
00030 #include "Creation.h"
00031 #include "Salvage.h"
00032 #include "Wormhole.h"
00033 #include "TempFleet.h"
00034 
00035 #ifdef _DEBUG
00036 #define new DEBUG_NEW
00037 #endif
00038 
00039 Galaxy * TheGalaxy;
00040 
00041 
00042 Galaxy::~Galaxy()
00043 {
00044         int i;
00045         for (i = 0; i < mPlanets.size(); ++i)
00046                 delete mPlanets[i];
00047 
00048         for (i = 0; i < invasions.size(); ++i)
00049                 delete invasions[i];
00050 
00051         for (i = 0; i < mScrap.size(); ++i)
00052                 delete mScrap[i];
00053 
00054         for (i = 0; i < mPackets.size(); ++i)
00055                 delete mPackets[i];
00056 
00057         for (i = 0; i < mWormholes.size(); ++i)
00058                 delete mWormholes[i];
00059 
00060         for (i = 0; i < mJettison.size(); ++i)
00061                 delete mJettison[i];
00062 }
00063 
00064 Planet * Galaxy::GetPlanet(int posX, int posY)
00065 {
00066         // Search list of planets for one at this position
00067         deque<Planet *>::iterator iter;
00068 
00069         for (iter = mPlanets.begin(); iter != mPlanets.end(); ++iter) {
00070                 if ((*iter)->GetPosX() == posX && (*iter)->GetPosY() == posY)
00071                         return iter[0];
00072         }
00073 
00074         return NULL;
00075 }
00076 
00077 Planet * Galaxy::GetPlanet(const CargoHolder * loc)
00078 {
00079         Planet * p = dynamic_cast<Planet *>(loc->GetAlsoHere()->at(0));
00080         if (p != NULL)
00081                 return p;
00082         else
00083                 return GetPlanet(loc->GetPosX(), loc->GetPosY());
00084 }
00085 
00086 Planet * Galaxy::GetPlanet(const char * name)
00087 {
00088         // Search list of planets for one at this position
00089         deque<Planet *>::iterator iter;
00090 
00091         if (!name || !*name)
00092                 return NULL;
00093 
00094         for (iter = mPlanets.begin(); iter != mPlanets.end(); ++iter) {
00095                 if ((*iter)->GetName() == name)
00096                         return iter[0];
00097         }
00098 
00099         return NULL;
00100 }
00101 
00102 void Galaxy::AddInvasion(Planet * planet)
00103 {
00104         deque<Planet *>::const_iterator iter;
00105 
00106         for (iter = invasions.begin(); iter != invasions.end(); ++iter)
00107                 if (planet == *iter)
00108                         return;
00109 
00110         invasions.insert(invasions.end(), planet);
00111 }
00112 
00113 void Galaxy::ResolveInvasions()
00114 {
00115         deque<Planet *>::iterator iter;
00116 
00117         for (iter = invasions.begin(); iter != invasions.end(); ++iter)
00118                 (*iter)->ResolveInvasion();
00119 
00120         invasions.clear();
00121 }
00122 
00123 bool Galaxy::ParseSize(const TiXmlNode * node)
00124 {
00125         if (node == NULL)
00126                 return false;
00127 
00128         mMinX = GetLong(node->FirstChild("MinX"), -1);
00129         mMinY = GetLong(node->FirstChild("MinY"), -1);
00130         mMaxX = GetLong(node->FirstChild("MaxX"), -1);
00131         mMaxY = GetLong(node->FirstChild("MaxY"), -1);
00132 
00133         if (mMinX < 0 || mMinY < 0 || (mMinX + 100 > mMaxX) || (mMinY + 100 > mMaxY))
00134                 return false;
00135         else
00136                 return true;
00137 }
00138 
00139 bool Galaxy::ParseNode(const TiXmlNode * node)
00140 {
00141         if (stricmp(node->Value(), "Galaxy") != 0)
00142                 return false;
00143 
00144         bool addit;
00145         const TiXmlNode * child1;
00146         for (child1 = node->FirstChild(); child1; child1 = child1->NextSibling()) {
00147                 if (child1->Type() == TiXmlNode::COMMENT)
00148                         continue;
00149 
00150                 if (stricmp(child1->Value(), "Planet") == 0) {
00151                         Planet * p;
00152                         p = GetPlanet(GetString(child1->FirstChild("Name")));
00153                         addit = p == NULL;
00154                         if (p == NULL) {
00155                                 p = new Planet();
00156                                 mPlanets.push_back(p);
00157                         }
00158 
00159                         if (!p->ParseNode(child1))
00160                                 return false;
00161 
00162                         if (addit)
00163                                 TheGame->AddAlsoHere(p);
00164                         assert(mMaxX > p->GetPosX() && mMaxY > p->GetPosY());
00165                 } else if (stricmp(child1->Value(), "Salvage") == 0) {
00166                         Salvage * s = new Salvage();
00167                         if (!s->ParseNode(child1)) {
00168                                 delete s;
00169                                 return false;
00170                         }
00171 
00172                         mScrap.insert(mScrap.end(), s);
00173                         TheGame->AddAlsoHere(s);
00174                 } else if (stricmp(child1->Value(), "Packet") == 0) {
00175                         Packet * p = new Packet();
00176                         if (!p->ParseNode(child1)) {
00177                                 delete p;
00178                                 return false;
00179                         }
00180 
00181                         mPackets.insert(mPackets.end(), p);
00182                         TheGame->AddAlsoHere(p);
00183                 }else if (stricmp(child1->Value(), "MTs") == 0) { // MTs Mysterious Trader
00184                         // TODO MT parsing
00185                         // TheGame->AddAlsoHere(p);
00186                 }else if (stricmp(child1->Value(), "Wormhole") == 0) {
00187                         // TODO Wormhole parsing
00188                         // TheGame->AddAlsoHere(p);
00189                 } else {
00190                         Message * mess = TheGame->AddMessage("Warning: Unknown section in Galaxy");
00191                         mess->AddItem("Section", child1->Value());
00192                         continue;
00193                 }
00194         }
00195 
00196         deque<Planet *>::iterator it;
00197         for (it = mPlanets.begin(); it != mPlanets.end(); ++it)
00198                 (*it)->SetDestinations();
00199 
00200         return true;
00201 }
00202 
00203 void Galaxy::WriteNode(TiXmlNode * node, const Player * viewer) const
00204 {
00205         int i;
00206         for (i = 0; i < mPlanets.size(); ++i) {
00207                 TiXmlElement * planet = new TiXmlElement("Planet");
00208                 mPlanets[i]->WriteNode(planet, viewer);
00209                 if (!planet->NoChildren())
00210                         node->LinkEndChild(planet);
00211                 else
00212                         delete planet;
00213         }
00214 
00215         for (i = 0; i < mScrap.size(); ++i) {
00216                 TiXmlElement * salvage = new TiXmlElement("Salvage");
00217                 mScrap[i]->WriteNode(salvage, viewer);
00218                 if (!salvage->NoChildren())
00219                         node->LinkEndChild(salvage);
00220                 else
00221                         delete salvage;
00222         }
00223 
00224         for (i = 0; i < mPackets.size(); ++i) {
00225                 TiXmlElement * packet = new TiXmlElement("Packet");
00226                 mPackets[i]->WriteNode(packet, viewer);
00227                 if (!packet->NoChildren())
00228                         node->LinkEndChild(packet);
00229                 else
00230                         delete packet;
00231         }
00232 
00233         for (i = 0; i < mWormholes.size(); ++i) {
00234                 TiXmlElement * wormhole = new TiXmlElement("Wormhole");
00235                 mWormholes[i]->WriteNode(wormhole, viewer);
00236                 if (!wormhole->NoChildren())
00237                         node->LinkEndChild(wormhole);
00238                 else
00239                         delete wormhole;
00240         }
00241 }
00242 
00243 void Galaxy::WriteXYFile(TiXmlNode * node)
00244 {
00245         deque<Planet *>::const_iterator pi;
00246         for (pi = mPlanets.begin(); pi != mPlanets.end(); ++pi) {
00247                 TiXmlElement planet("Planet");
00248                 planet.SetAttribute("IDNumber", (*pi)->GetID());
00249                 AddString(&planet, "Name", (*pi)->GetName().c_str());
00250                 (*pi)->Location::WriteNode(&planet);
00251                 node->InsertEndChild(planet);
00252         }
00253 }
00254 
00255 Salvage * Galaxy::GetSalvage(long n) const
00256 {
00257         deque<Salvage *>::const_iterator it;
00258         for (it = mScrap.begin(); it != mScrap.end(); ++it) {
00259                 if ((*it)->GetID() == n)
00260                         return *it;
00261         }
00262 
00263         return NULL;
00264 }
00265 
00266 Salvage * Galaxy::AddSalvage(const CargoHolder & ch)
00267 {
00268         for (int i = 0; i < mScrap.size(); ++i) {
00269                 if (mScrap[i]->IsWith(ch) && mScrap[i]->GetOwner() == ch.GetOwner())
00270                         return mScrap[i];
00271         }
00272 
00273         Salvage * scrap = new Salvage(ch);
00274         mScrap.insert(mScrap.end(), scrap);
00275         return scrap;
00276 }
00277 
00278 const Packet * Galaxy::GetPacket(long n) const
00279 {
00280         deque<Packet *>::const_iterator it;
00281         for (it = mPackets.begin(); it != mPackets.end(); ++it) {
00282                 if ((*it)->GetID() == n)
00283                         return *it;
00284         }
00285 
00286         return NULL;
00287 }
00288 
00289 bool Galaxy::Mine()
00290 {
00291         deque<Planet *>::iterator pi;
00292         for (pi = mPlanets.begin(); pi != mPlanets.end(); ++pi) {
00293                 (*pi)->Mine();
00294         }
00295 
00296         return true;
00297 }
00298 
00299 void Galaxy::DecaySalvage()
00300 {
00301         deque<Salvage *>::iterator si;
00302         for (si = mScrap.begin(); si != mScrap.end(); ++si)
00303                 (*si)->Decay();
00304 }
00305 
00306 void Galaxy::GrowPop()
00307 {
00308         deque<Planet *>::iterator pi;
00309         for (pi = mPlanets.begin(); pi != mPlanets.end(); ++pi) {
00310                 (*pi)->AdjustPopulation((*pi)->PopGrowth());
00311         }
00312 }
00313 
00314 void Galaxy::DoProduction()
00315 {
00316         mTechSpent.erase(mTechSpent.begin(), mTechSpent.end());
00317         mTechSpent.insert(mTechSpent.begin(), Rules::MaxTechType, 0);
00318 
00319         deque<Planet *>::iterator pi;
00320         for (pi = mPlanets.begin(); pi != mPlanets.end(); ++pi) {
00321                 (*pi)->DoProduction();
00322         }
00323 }
00324 
00325 void Galaxy::TechSpent(long TechGain, TechType tech)
00326 {
00327         if (tech < 0 || tech >= Rules::MaxTechType)
00328                 return;
00329 
00330         assert(TheGame->GetTurnPhase() == TP_PRODUCTION);
00331         mTechSpent[tech] += TechGain;
00332 }
00333 
00334 void Galaxy::GainSpyTech(Player * player)
00335 {
00336         long gain;
00337         for (TechType tech = 0; tech < Rules::MaxTechType; ++tech) {
00338                 gain = long(player->SpyTechBonus() * mTechSpent[tech] / TheGame->NumberPlayers() + .5);
00339                 if (gain > 0)
00340                         player->GainSpyTech(gain, tech);
00341         }
00342 }
00343 
00344 void Galaxy::DeadCheck()
00345 {
00346         deque<Planet *>::iterator pi;
00347         for (pi = mPlanets.begin(); pi != mPlanets.end(); ++pi) {
00348                 (*pi)->DeadCheck();
00349         }
00350 }
00351 
00352 void Galaxy::DoBombing()
00353 {
00354         // Go through all planets
00355         for (deque<Planet *>::iterator target_planet = mPlanets.begin(); target_planet != mPlanets.end(); ++target_planet)
00356         {
00357                 // Check if planet has owner
00358                 Player* planet_owner = const_cast<Player*>((*target_planet)->GetOwner());
00359                 if (planet_owner == NULL)
00360                         continue;
00361                         
00362                 // Check if Planet has a Starbase
00363                 if((*target_planet)->GetBaseNumber() != -1)
00364                         continue;
00365                         
00366                 Bombing bom(*(*target_planet));
00367                 bom.SetPlanet((*target_planet));
00368                 bom.AddFleets();
00369                 bom.Resolve();
00370         }
00371 }
00372 
00373 template<class II> long GetID(II first, II last)
00374 {
00375         long Result;
00376         bool retry;
00377         long trys = 0;
00378 
00379         do {
00380                 Result = genrand_int32();
00381                 retry = Result == 0;
00382                 II i;
00383                 for (i = first; !retry && i != last; ++i) {
00384                         if (Result == (*i)->GetID()) {
00385                                 retry = true;
00386                                 break;
00387                         }
00388                 }
00389         } while (retry && trys++ < 1000);
00390 
00391         assert(!retry);
00392         return Result;
00393 }
00394 
00395 long Galaxy::GetPacketID() const
00396 {
00397         return GetID(mPackets.begin(), mPackets.end());
00398 }
00399 
00400 long Galaxy::GetSalvageID() const
00401 {
00402         return GetID(mScrap.begin(), mScrap.end());
00403 }
00404 
00405 long Galaxy::GetWormholeID() const
00406 {
00407         return GetID(mWormholes.begin(), mWormholes.end());
00408 }
00409 
00410 void Galaxy::Build(Creation * c)
00411 {
00412         long i;
00413 
00414         // add planets
00415         for (i = GetPlanetCount(); i < c->mWorlds; ++i) {
00416                 // create a planet
00417                 Planet * p;
00418                 p = new Planet();
00419                 c->SetLocation(p);
00420                 p->CreateRandom(c);
00421                 mPlanets.push_back(p);
00422                 TheGame->AddAlsoHere(p);
00423         }
00424 
00425         // add wormholes
00426         if (TheGame->GetRandomEvents() | RE_WORMHOLE) {
00427                 i = TheGame->MinWormholes() + Random(TheGame->MaxWormholes() - TheGame->MinWormholes());
00428                 for ( ; i > 0; --i) {
00429                         Wormhole * wh1 = new Wormhole();
00430                         Wormhole * wh2 = new Wormhole();
00431                         wh1->Shift();
00432                         wh2->Shift();
00433                         wh1->SetAttached(wh2);
00434                         wh2->SetAttached(wh1);
00435                         mWormholes.push_back(wh1);
00436                         mWormholes.push_back(wh2);
00437                         TheGame->AddAlsoHere(wh1);
00438                         TheGame->AddAlsoHere(wh2);
00439                 }
00440         }
00441 }
00442 
00443 void Galaxy::PlacePlayer(Player * player)
00444 {
00445         if (player->HasHW())
00446                 return;
00447 
00448         Planet * world;
00449         world = TheGame->GetCreation()->GetNextHW();
00450         if (world == NULL) {
00451                 // for now, just random selection
00452                 long count = 0;
00453                 while (count++ < 100) {
00454                         world = mPlanets[Random(GetPlanetCount())];
00455                         if (world->GetOwner() != NULL)
00456                                 continue;
00457 
00458                         break;
00459                 }
00460         }
00461 
00462         player->PlaceHW(world);
00463 
00464 
00465         // place secondary planets
00466         if (player->HasSecondPlanet() && TheGame->GetCreation()->mSecondaryWorlds) {
00467                 Planet * second = NULL;
00468                 second = TheGame->GetCreation()->GetSecond(player);
00469                 if (second == NULL) {
00470                         long count = 0;
00471                         long dist;
00472                         long w;
00473                         while (count++ < 100) {
00474                                 w = Random(GetPlanetCount());
00475                                 if (mPlanets[w]->GetOwner() != NULL)
00476                                         continue;
00477 
00478                                 second = mPlanets[w];
00479                                 dist = long(second->Distance(*world));
00480                                 if (dist < TheGame->GetCreation()->mMinSWDistance || dist > TheGame->GetCreation()->mMaxSWDistance)
00481                                         continue;
00482 
00483                                 break;
00484                         }
00485                 }
00486 
00487                 player->PlaceSW(second, world);
00488         }
00489 }
00490 
00491 const Planet * Galaxy::ClosestPlanet(const Location * loc)
00492 {
00493         long dist = -1;
00494         Planet * Result = NULL;
00495         // Search list of planets for closest
00496         deque<Planet *>::iterator iter;
00497 
00498         for (iter = mPlanets.begin(); iter != mPlanets.end(); ++iter) {
00499                 if (dist < 0 || dist > loc->Distance(**iter)) {
00500                         dist = long(loc->Distance(**iter));
00501                         Result = *iter;
00502                 }
00503         }
00504 
00505         return Result;
00506 }
00507 
00508 void Galaxy::LoadPlanets()
00509 {
00510         int i;
00511         for (i = 0; i < mPlanets.size(); ++i)
00512                 TheGame->AddAlsoHere(mPlanets[i]);
00513 }
00514 
00515 void Galaxy::LoadScrap()
00516 {
00517         int i;
00518         for (i = 0; i < mScrap.size(); ++i)
00519                 TheGame->AddAlsoHere(mScrap[i]);
00520 }
00521 
00522 void Galaxy::LoadPackets()
00523 {
00524         int i;
00525         for (i = 0; i < mPackets.size(); ++i)
00526                 TheGame->AddAlsoHere(mPackets[i]);
00527 }
00528 
00529 void Galaxy::LoadWormholes()
00530 {
00531         int i;
00532         for (i = 0; i < mWormholes.size(); ++i)
00533                 TheGame->AddAlsoHere(mWormholes[i]);
00534 }
00535 
00536 CargoHolder * Galaxy::GetJettison(const CargoHolder * ch, CargoHolder * ch2)
00537 {
00538         if (ch2 == NULL) {
00539                 Planet * planet = dynamic_cast<Planet *>(ch->GetAlsoHere()->at(0));
00540                 if (planet != NULL)
00541                         ch2 = planet;
00542 
00543                 const deque<CargoHolder *> & deq = *ch->GetAlsoHere();
00544                 int i;
00545                 for (i = 0; i < deq.size(); ++i) {
00546                         Packet * packet = dynamic_cast<Packet *>(deq[i]);
00547                         if (packet != NULL) {
00548                                 return packet;
00549                         }
00550                 }
00551         }
00552 
00553         if (ch->GetOwner() == ch2->GetOwner())
00554                 return ch2;
00555 
00556         int i;
00557         for (i = 0; i < mJettison.size(); ++i) {
00558                 if (ch->IsWith(*mJettison[i]) && mJettison[i]->GetRealCH() == ch2)
00559                         break;
00560         }
00561 
00562         if (i == mJettison.size())
00563                 mJettison.push_back(new TempFleet(ch, ch2));
00564 
00565         return mJettison[i];
00566 }
00567 
00568 void Galaxy::CleanJettison()
00569 {
00570         int i;
00571         CargoHolder * ch;
00572         for (i = 0; i < mJettison.size(); ++i) {
00573                 ch = mJettison[i]->GetRealCH();
00574                 if (ch == NULL) {
00575                         delete mJettison[i];
00576                         continue;
00577                 }
00578 
00579                 assert(mJettison[i]->GetPopulation() >= 0);
00580                 if (mJettison[i]->GetPopulation() > 0) {
00581                         Planet * p = dynamic_cast<Planet *>(ch);
00582                         if (p == NULL) {
00583                                 delete mJettison[i];
00584                                 continue;
00585                         }
00586 
00587                         p->Invade(mJettison[i]->NCGetOwner(), mJettison[i]->GetPopulation());
00588                 }
00589 
00590                 assert(mJettison[i]->GetFuel() >= 0);
00591                 if (mJettison[i]->GetFuel() > 0) {
00592                         Fleet * f = dynamic_cast<Fleet *>(ch);
00593                         if (f == NULL) {
00594                                 delete mJettison[i];
00595                                 continue;
00596                         }
00597 
00598                         f->AdjustFuel(mJettison[i]->GetFuel());
00599                 }
00600 
00601                 for (int ct = 0; ct < Rules::MaxMinType; ++ct) {
00602                         assert(mJettison[i]->GetContain(ct) >= 0);
00603                         ch->AdjustAmounts(ct, mJettison[i]->GetContain(ct));
00604                 }
00605 
00606                 delete mJettison[i];
00607         }
00608 }
00609 
00610 void Galaxy::RepairBases()
00611 {
00612         int i;
00613         for (i = 0; i < mPlanets.size(); ++i)
00614                 mPlanets[i]->RepairBase();
00615 }
00616 
00617 void Galaxy::Instaform()
00618 {
00619         int i;
00620         for (i = 0; i < mPlanets.size(); ++i)
00621                 mPlanets[i]->Instaform();
00622 }
00623 
00624 void Galaxy::MovePackets(bool firstyear)
00625 {
00626         int i;
00627         for (i = 0; i < mPackets.size(); ++i) {
00628                 if (mPackets[i]->Move(firstyear)) {
00629                         delete mPackets[i];
00630                         mPackets.erase(mPackets.begin() + i);
00631                         --i;
00632                 }
00633         }
00634 }
00635 
00636 void Galaxy::AddPacket(Packet * packet, const Planet * planet)
00637 {
00638         Message * mess = packet->NCGetOwner()->AddMessage("Packet built", planet);
00639         int i;
00640         for (i = 0; i < mPackets.size(); ++i) {
00641                 if (mPackets[i]->IsWith(*packet) &&
00642                         mPackets[i]->GetOwner() == packet->GetOwner() &&
00643                         mPackets[i]->GetDestination() == packet->GetDestination() &&
00644                         mPackets[i]->GetSpeed() == packet->GetSpeed())
00645                 {
00646                         for (int ct = 0; ct < Rules::MaxMinType; ++ct)
00647                                 mPackets[i]->AdjustAmounts(ct, packet->GetContain(ct));
00648 
00649                         delete packet;
00650                         mess->AddItem("Added to", mPackets[i]);
00651                         return;
00652                 }
00653         }
00654 
00655         mess->AddItem("Packet", packet);
00656         mPackets.insert(mPackets.end(), packet);
00657 }
00658 
00659 const Wormhole * Galaxy::GetWormhole(long id) const
00660 {
00661         int i;
00662         for (i = 0; i < mWormholes.size(); ++i) {
00663                 if (mWormholes[i]->GetID() == id)
00664                         return mWormholes[i];
00665         }
00666 
00667         return NULL;
00668 }
00669 
00670 void Galaxy::JiggleWormholes()
00671 {
00672         int i;
00673         for (i = 0; i < mWormholes.size(); ++i)
00674                 mWormholes[i]->Jiggle();
00675 }
00676 
00677 void Galaxy::AdjustWormholeTraverse()
00678 {
00679         int i;
00680         for (i = 0; i < mWormholes.size(); ++i)
00681                 mWormholes[i]->AdjustTraverse();
00682 }

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