00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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) {
00184
00185
00186 }else if (stricmp(child1->Value(), "Wormhole") == 0) {
00187
00188
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
00355 for (deque<Planet *>::iterator target_planet = mPlanets.begin(); target_planet != mPlanets.end(); ++target_planet)
00356 {
00357
00358 Player* planet_owner = const_cast<Player*>((*target_planet)->GetOwner());
00359 if (planet_owner == NULL)
00360 continue;
00361
00362
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
00415 for (i = GetPlanetCount(); i < c->mWorlds; ++i) {
00416
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
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
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
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
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 }