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

Race.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 
00029 #include "RacialTrait.h"
00030 
00031 Race::Race()
00032 {
00033         ResetDefaults();
00034         mHabCenter.insert(mHabCenter.begin(), Rules::MaxHabType, 50);
00035         mHabWidth.insert(mHabWidth.begin(), Rules::MaxHabType, 20);
00036         mTechCostFactor.insert(mTechCostFactor.begin(), Rules::MaxTechType, 1.0);
00037         mStartMinerals = 0;
00038         mStartConcentrations = 0;
00039         mStartMines = 0;
00040         mStartFactories = 0;
00041         mStartDefneses = 0;
00042         mStartAt = false;
00043 }
00044 
00045 Race::~Race()
00046 {
00047 }
00048 
00049 double Race::RadDamage(HabType ht) const
00050 {
00051         if (ht == -1)
00052                 return 0.0;
00053         else if (mHabWidth[ht] == -1)   // immune
00054                 return 0.0;
00055         else if (mHabCenter[ht] >= 85)
00056                 return 0.0;
00057         else {
00058                 return (86 - mHabCenter[ht]) / 100.0;
00059         }
00060 }
00061 
00062 double Race::HabFactor(HabType ht, long tick) const     // gives how habitable this is abs(tick - midpoint)/width or negative if outside range
00063 {
00064         if (ht < 0 && ht >= Rules::MaxHabType)
00065                 return 0;
00066         else if (mHabWidth[ht] == -1)   // immune
00067                 return 1;
00068         else if (tick < mHabCenter[ht] - mHabWidth[ht]) // too low
00069                 return max(-15L, tick - (mHabCenter[ht] - mHabWidth[ht]));
00070         else if (tick > mHabCenter[ht] + mHabWidth[ht]) // too high
00071                 return max(-15L, (mHabCenter[ht] + mHabWidth[ht]) - tick);
00072         else
00073                 return 1.0 - double(abs(tick - mHabCenter[ht])) / double(mHabWidth[ht]);
00074 }
00075 
00076 long Race::HabFactor(const Planet * p) const    // gives how habitable this planet is
00077 {
00078         double Result = 0;
00079         double LowMultiplier = 1;
00080         HabType ht;
00081         for (ht = 0; ht < Rules::MaxHabType; ++ht) {
00082                 double temp = HabFactor(ht, p->GetHabValue(ht));
00083                 if (temp < 0 && Result < 0)
00084                         Result += temp;
00085                 else if (temp < 0 && Result >= 0)
00086                         Result = temp;
00087                 else if (temp >= 0 && Result >= 0) {
00088                         Result = Result + temp * temp;
00089                 } /* else do nothing */
00090 
00091                 if (temp < .5)
00092                         LowMultiplier *= temp + 0.5;
00093         }
00094 
00095         if (Result < 0)
00096                 return long(Result - .5);
00097 
00098         Result = sqrt(Result / Rules::MaxHabType);
00099         Result *= LowMultiplier;
00100 
00101         return long(Result * 100 + .5);
00102 }
00103 
00104 long Race::HabCenter(HabType ht) const
00105 {
00106         if (ht >= 0 && ht < Rules::MaxHabType)
00107                 return mHabCenter[ht];
00108         else
00109                 return 0;
00110 }
00111 
00112 long Race::HabWidth(HabType ht) const
00113 {
00114         if (ht >= 0 && ht < Rules::MaxHabType)
00115                 return mHabWidth[ht];
00116         else
00117                 return 0;
00118 }
00119 
00120 double Race::TechCostFactor(TechType tt) const
00121 {
00122         if (tt >= 0 && tt < Rules::MaxTechType)
00123                 return mTechCostFactor[tt];
00124         else
00125                 return 0;
00126 }
00127 
00128 bool Race::ParseNode(const TiXmlNode * node, bool other)
00129 {
00130         const TiXmlNode * child1;
00131         const TiXmlNode * child2;
00132         long i;
00133         const char * ptr;
00134 
00135         for (child1 = node->FirstChild(); child1; child1 = child1->NextSibling()) {
00136                 if (child1->Type() == TiXmlNode::COMMENT)
00137                         continue;
00138 
00139                 if (stricmp(child1->Value(), "Randomize") == 0) {
00140                         // used elsewhere, ignore here
00141                 } else if (stricmp(child1->Value(), "SingularName") == 0) {
00142                         ptr = GetString(child1);
00143                         if (ptr != NULL)
00144                                 mSingularName = ptr;
00145                 } else if (stricmp(child1->Value(), "PluralName") == 0) {
00146                         ptr = GetString(child1);
00147                         if (ptr != NULL)
00148                                 mPluralName = ptr;
00149                 } else if (stricmp(child1->Value(), "PrimaryRacialTrait") == 0) {
00150                         mPRT = TheGame->ParsePRT(GetString(child1));
00151                 } else if (stricmp(child1->Value(), "LesserRacialTrait") == 0) {
00152                         const RacialTrait * rt;
00153                         rt = TheGame->ParseLRT(GetString(child1));
00154                         if (rt == NULL) {
00155                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00156                                 mess->AddItem("Race", mSingularName);
00157                                 mess->AddItem("LesserRacialTrait", GetString(child1));
00158                                 return false;
00159                         } else
00160                                 mLRTs.insert(mLRTs.end(), rt);
00161                 } else if (stricmp(child1->Value(), "HabSettings") == 0) {
00162                         for (child2 = child1->FirstChild("Hab"); child2; child2 = child2->NextSibling("Hab")) {
00163                                 const TiXmlElement * el;
00164                                 el = child2->ToElement();
00165                                 int i = Rules::HabID(el->Attribute("Name"));
00166                                 if (i < 0 || i >= Rules::MaxHabType) {
00167                                         Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00168                                         mess->AddItem("Race", mSingularName);
00169                                         mess->AddItem("Hab type", el->Attribute("Name"));
00170                                         return false;
00171                                 }
00172 
00173                                 mHabCenter[i] = GetLong(child2->FirstChild("Center"));
00174                                 if (mHabCenter[i] != -1 && (mHabCenter[i] < 10 || mHabCenter[i] > 90)) {
00175                                         Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00176                                         mess->AddItem("Race", mSingularName);
00177                                         mess->AddLong("Hab center", mHabCenter[i]);
00178                                         return false;
00179                                 }
00180                                 mHabWidth[i] = GetLong(child2->FirstChild("Width"));
00181                                 if ((mHabCenter[i] == -1 && mHabWidth[i] != -1) ||
00182                                         (mHabCenter[i] != -1 && mHabWidth[i] == -1) || 
00183                                         (mHabWidth[i] > mHabCenter[i] || mHabWidth[i] > 100 - mHabCenter[i]))
00184                                 {
00185                                         Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00186                                         mess->AddItem("Race", mSingularName);
00187                                         mess->AddLong("Hab width", mHabCenter[i]);
00188                                         return false;
00189                                 }
00190                         }
00191                 } else if (stricmp(child1->Value(), "GrowthRate") == 0) {
00192                         mGrowthRate = GetDouble(child1);
00193                         if (mGrowthRate < 0.009 || mGrowthRate > 0.201) {//magic number
00194                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00195                                 mess->AddItem("Race", mSingularName);
00196                                 mess->AddFloat("GrowthRate", mGrowthRate);
00197                                 return false;
00198                         }
00199                 } else if (stricmp(child1->Value(), "PopEfficiency") == 0) {
00200                         mPopEfficiency = GetLong(child1);
00201                         if (mPopEfficiency < 700 || mPopEfficiency > 2500) {//magic number
00202                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00203                                 mess->AddItem("Race", mSingularName);
00204                                 mess->AddLong("PopEfficiency", mPopEfficiency);
00205                                 return false;
00206                         }
00207                 } else if (stricmp(child1->Value(), "FactoryRate") == 0) {
00208                         mFactoryRate = GetLong(child1);
00209                         if (mFactoryRate < 5 || mFactoryRate > 15) {//magic number
00210                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00211                                 mess->AddItem("Race", mSingularName);
00212                                 mess->AddLong("FactoryRate", mFactoryRate);
00213                                 return false;
00214                         }
00215                 } else if (stricmp(child1->Value(), "FactoryCost") == 0) {
00216                         mFactoryCost.ReadCosts(child1);
00217                 } else if (stricmp(child1->Value(), "FactoriesRun") == 0) {
00218                         mFactoriesRun = GetLong(child1);
00219                         if (mFactoriesRun < 5 || mFactoriesRun > 25) {//magic number
00220                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00221                                 mess->AddItem("Race", mSingularName);
00222                                 mess->AddLong("FactoriesRun", mFactoriesRun);
00223                                 return false;
00224                         }
00225                 } else if (stricmp(child1->Value(), "MineRate") == 0) {
00226                         mMineRate = GetLong(child1);
00227                         if (mMineRate < 5 || mMineRate > 15) {//magic number
00228                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00229                                 mess->AddItem("Race", mSingularName);
00230                                 mess->AddLong("MineRate", mMineRate);
00231                                 return false;
00232                         }
00233                 } else if (stricmp(child1->Value(), "MineCost") == 0) {
00234                         mMineCost.ReadCosts(child1);
00235                 } else if (stricmp(child1->Value(), "MinesRun") == 0) {
00236                         mMinesRun = GetLong(child1);
00237                         if (mMinesRun < 5 || mMinesRun > 25) {//magic number
00238                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00239                                 mess->AddItem("Race", mSingularName);
00240                                 mess->AddLong("MinesRun", mMinesRun);
00241                                 return false;
00242                         }
00243                 } else if (stricmp(child1->Value(), "TechFactor") == 0) {
00244                         Rules::ParseArrayFloat(child1, mTechCostFactor, TECHS);
00245                 } else if (stricmp(child1->Value(), "StartAt") == 0) {
00246                         ptr = GetString(child1);
00247                         if (ptr && stricmp(ptr, "true") == 0)
00248                                 mStartAt = true;
00249                 } else if (stricmp(child1->Value(), "StartMinerals") == 0) {
00250                         mStartMinerals = GetLong(child1);
00251                         if (mStartMinerals < 0 || mStartMinerals > 50) {//magic number
00252                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00253                                 mess->AddItem("Race", mSingularName);
00254                                 mess->AddLong("StartMinerals", mStartMinerals);
00255                                 return false;
00256                         }
00257                 } else if (stricmp(child1->Value(), "StartConcentrations") == 0) {
00258                         mStartConcentrations = GetLong(child1);
00259                         if (mStartConcentrations < 0 || mStartConcentrations > 50) {//magic number
00260                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00261                                 mess->AddItem("Race", mSingularName);
00262                                 mess->AddLong("StartConcentrations", mStartConcentrations);
00263                                 return false;
00264                         }
00265                 } else if (stricmp(child1->Value(), "StartMines") == 0) {
00266                         mStartMines = GetLong(child1);
00267                         if (mStartMines < 0 || mStartMines > 50) {//magic number
00268                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00269                                 mess->AddItem("Race", mSingularName);
00270                                 mess->AddLong("StartMines", mStartMines);
00271                                 return false;
00272                         }
00273                 } else if (stricmp(child1->Value(), "StartFactories") == 0) {
00274                         mStartFactories = GetLong(child1);
00275                         if (mStartFactories < 0 || mStartFactories > 50) {//magic number
00276                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00277                                 mess->AddItem("Race", mSingularName);
00278                                 mess->AddLong("StartFactories", mStartFactories);
00279                                 return false;
00280                         }
00281                 } else if (stricmp(child1->Value(), "StartDefneses") == 0) {
00282                         mStartDefneses = GetLong(child1);
00283                         if (mStartDefneses < 0 || mStartDefneses > 50) {//magic number
00284                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00285                                 mess->AddItem("Race", mSingularName);
00286                                 mess->AddLong("StartDefneses", mStartDefneses);
00287                                 return false;
00288                         }
00289                 } else if (stricmp(child1->Value(), "RaceEmblem") == 0) {
00290                         mRaceEmblem = GetLong(child1);
00291                         if (mRaceEmblem < 0 || mRaceEmblem > 16) { //magic number
00292                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00293                                 mess->AddItem("Race", mSingularName);
00294                                 mess->AddLong("RaceEmblem", mRaceEmblem);
00295                                 return false;
00296                         }
00297                 } else if (!other && stricmp(child1->Value(), "Password") == 0) {
00298                         ptr = GetString(child1);
00299                         if (ptr != NULL)
00300                                 mPassword = ptr;
00301                 } else if (stricmp(child1->Value(), "MetaInfo") == 0) {
00302                         // skip it
00303                 } else {
00304                         Message * mess = TheGame->AddMessage("Warning: Unknown section");
00305                         mess->AddItem("Race", mSingularName);
00306                         mess->AddItem("Section", child1->Value());
00307                         continue;
00308                 }
00309         }
00310 
00311         if (!other && mPRT == NULL) {
00312                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00313                 mess->AddItem("Race", mSingularName);
00314                 mess->AddItem("Missing PRT", "");
00315                 return false;
00316         }
00317         if (!other && mGrowthRate <= 0.009) {
00318                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00319                 mess->AddItem("Race", mSingularName);
00320                 mess->AddFloat("GrowthRate", mGrowthRate);
00321                 return false;
00322         }
00323 
00324         if (!other) {
00325                 for (i = 0; i < Rules::MaxHabType; ++i) {
00326                         if (mHabCenter[i] == 0 || mHabWidth[i] == 0) {
00327                                 Message * mess = TheGame->AddMessage("Error: Invalid racial setting");
00328                                 mess->AddItem("Race", mSingularName);
00329                                 mess->AddItem("missing Hab Setting", Rules::GetHabName(i));
00330                                 return false;
00331                         }
00332                 }
00333         }
00334 
00335         return true;
00336 }
00337 
00338 void Race::WriteHabs(TiXmlNode * node) const
00339 {
00340         TiXmlElement HS("HabSettings");
00341         for (int i = 0; i < Rules::MaxHabType; ++i) {
00342                 TiXmlElement hab("Hab");
00343                 hab.SetAttribute("Name", Rules::GetHabName(i));
00344                 AddLong(&hab, "Center", mHabCenter[i]);
00345                 AddLong(&hab, "Width", mHabWidth[i]);
00346                 HS.InsertEndChild(hab);
00347         }
00348         node->InsertEndChild(HS);
00349 }
00350 
00351 void Race::WriteNode(TiXmlNode * node) const
00352 {
00353         AddString(node, "SingularName", mSingularName.c_str());
00354         AddString(node, "PluralName", mPluralName.c_str());
00355         AddString(node, "PrimaryRacialTrait", mPRT->Name().c_str());
00356         
00357         deque<const RacialTrait *>::const_iterator rti;
00358         for (rti = mLRTs.begin(); rti != mLRTs.end(); ++rti) {
00359                 AddString(node, "LesserRacialTrait", (*rti)->Name().c_str());
00360         }
00361 
00362         TiXmlElement HS("HabSettings");
00363         for (int i = 0; i < Rules::MaxHabType; ++i) {
00364                 TiXmlElement hab("Hab");
00365                 hab.SetAttribute("Name", Rules::GetHabName(i));
00366                 AddLong(&hab, "Center", mHabCenter[i]);
00367                 AddLong(&hab, "Width", mHabWidth[i]);
00368                 HS.InsertEndChild(hab);
00369         }
00370         node->InsertEndChild(HS);
00371 
00372         AddDouble(node, "GrowthRate", mGrowthRate);
00373         AddLong(node, "PopEfficiency", mPopEfficiency);
00374         AddLong(node, "FactoryRate", mFactoryRate);
00375         mFactoryCost.WriteCosts(node, "FactoryCost");
00376         AddLong(node, "FactoriesRun", mFactoriesRun);
00377         AddLong(node, "MineRate", mMineRate);
00378         mMineCost.WriteCosts(node, "MineCost");
00379         AddLong(node, "MinesRun", mMinesRun);
00380         node->LinkEndChild(Rules::WriteArrayFloat("TechFactor", mTechCostFactor, TECHS));
00381 
00382         if (mStartAt)
00383                 AddString(node, "StartAt", "true");
00384 
00385         if (mStartMinerals > 0)                 AddLong(node, "StartMinerals", mStartMinerals);
00386         if (mStartConcentrations > 0)   AddLong(node, "StartConcentrations", mStartConcentrations);
00387         if (mStartMines > 0)                    AddLong(node, "StartMines", mStartMines);
00388         if (mStartFactories > 0)                AddLong(node, "StartFactories", mStartFactories);
00389         if (mStartDefneses > 0)                 AddLong(node, "StartDefneses", mStartDefneses);
00390 
00391         AddLong(node, "RaceEmblem", mRaceEmblem);
00392         AddString(node, "Password", mPassword.c_str());
00393 
00394         deque<double>::const_iterator li;
00395         li = max_element(CVEngineFailure.begin(), CVEngineFailure.end());
00396         if (*li > 0.0) {
00397                 node->LinkEndChild(Rules::WriteArrayFloat("CVEngineFailure", "Warp", "Speed", CVEngineFailure));
00398         }
00399 }
00400 
00401 void Race::ResetDefaults()
00402 {
00403         CCalcGroundAttackFactor = false;
00404         CCalcGroundDefenseFactor = false;
00405         CCalcGrowthRateFactor = false;
00406         CCalcPopulationFactor = false;
00407         CVCloakCargo = -1;
00408         CVMineSpeedBonus = -1;
00409         CCalcSpyTechBonus = false;
00410         CCalcBattleSpeedBonus = false;
00411         CCalcPermaformChance = false;
00412         CVCanSeeHabSettings = -1;
00413         CVTemporaryTerraform = -1;
00414         CVScanDesign = -1;
00415         CCalcRepairFactor = false;
00416         CCalcFreighterReproduction = false;
00417         CVMineFieldScanning = -1;
00418         CVCanRemoteDetonate = -1;
00419         CCalcMineDecayFactor = false;
00420 
00421         CVPacketTerraform = -1;
00422         CVPacketScanning = -1;
00423         CCalcPacketCostMinFactor = false;
00424         CVPacketSizeOneMin = -1;
00425         CVPacketSizeMixed = -1;
00426         CVPacketCostResources = -1;
00427         CCalcPacketDecayFactor = false;
00428         CCalcPacketCatchFactor = false;
00429         CVPacketDecayPenalty = -1;
00430 
00431         CVStartAtBonus = -1;
00432         CVGateCargo = -1;
00433         CCalcOvergateLossFactor = false;
00434         CVGateScanning = -1;
00435         CVARTechType = -2;
00436         CCalcFuelFactor = false;
00437         CVGeneralResearch = -1;
00438         CVUltimateRecycle = -1;
00439         CCalcSpaceScanFactor = false;
00440         CCalcPenScanFactor = false;
00441         CCalcStartingPopFactor = false;
00442         CCalcZeroTechCost = false;
00443         CCalcMaxMiniturize = false;
00444         CCalcMiniturizeRate = false;
00445         CCalcShieldFactor = false;
00446         CCalcArmorFactor = false;
00447         CCalcShieldRegenRate = false;
00448         CCalcDefenseFactor = false;
00449 
00450         CVEngineFailure.clear();
00451         CVEngineFailure.insert(CVEngineFailure.begin(), Rules::GetConstant("MaxSpeed"), -1.0);
00452 }
00453 
00454 bool Race::HasSecondPlanet() const
00455 {
00456         return mPRT->HasSecondPlanet();
00457 }
00458 
00459 long lInherentCloaking(long v, const RacialTrait * lrt, HullType hc)
00460 {
00461         return v + (((lrt->InherentCloakHull() & hc) == hc) ? lrt->InherentCloakAmount() : 0);
00462 }
00463 
00464 long Race::InherentCloaking(HullType hc) const
00465 {
00466         return accumulate(      mLRTs.begin(),
00467                                                 mLRTs.end(),
00468                                                 ((mPRT->InherentCloakHull() & hc) == hc) ? mPRT->InherentCloakAmount() : 0,
00469                                                 lInherentCloaking,
00470                                                 hc);
00471 }
00472 
00473 double lComponentCostFactor(double v, const RacialTrait * lrt, ComponentType ct)
00474 {
00475         return v * (double(lrt->ComponentCostFactor(ct)));
00476 }
00477 
00478 double Race::ComponentCostFactor(ComponentType ct) const
00479 {
00480         return accumulate(mLRTs.begin(),
00481                                                 mLRTs.end(),
00482                                                 double(mPRT->ComponentCostFactor(ct)),
00483                                                 lComponentCostFactor,
00484                                                 ct);
00485 }
00486 
00487 long lStartingTech(long v, const RacialTrait * lrt, TechType tt)
00488 {
00489         return v + lrt->StartingTech(tt);
00490 }
00491 
00492 long Race::PRTStartTech(TechType tt) const
00493 {
00494         return mPRT->StartingTech(tt);
00495 }
00496 
00497 long Race::LRTStartTech(TechType tt) const
00498 {
00499         return accumulate(      mLRTs.begin(),
00500                                                 mLRTs.end(),
00501                                                 0,
00502                                                 lStartingTech,
00503                                                 tt);
00504 }
00505 
00506 double lEngineFailure(double v, const RacialTrait * lrt, long speed)
00507 {
00508         return (1.0 - (1.0 - v) * (1.0 - lrt->EngineFailure(speed)));
00509 }
00510 
00511 double Race::EngineFailure(long speed) const
00512 {
00513         if (CVEngineFailure[speed-1] >= 0.0) {
00514                 double Result = accumulate(mLRTs.begin(),
00515                                                                         mLRTs.end(),
00516                                                                         mPRT->EngineFailure(speed),
00517                                                                         lEngineFailure,
00518                                                                         speed);
00519                 const_cast<Race *>(this)->CVEngineFailure[speed-1] = Result;
00520         }
00521         return CVEngineFailure[speed-1];
00522 }
00523 
00524 long Race::BuiltinScan(const Player * player, HullType hc, bool PenScan, long pop /*= 0*/) const
00525 {
00526         long Result = mPRT->BuiltinScan(player, hc, PenScan, pop);
00527         deque<const RacialTrait *>::const_iterator lrt;
00528         for (lrt = mLRTs.begin(); lrt != mLRTs.end(); ++lrt)
00529                 Result = max(Result, (*lrt)->BuiltinScan(player, hc, PenScan, pop));
00530 
00531         return Result;
00532 }
00533 
00534 
00535 //Macros for the rest of the functions:
00536 // define a local function that adds current total, and LRT capability
00537 // make a member function that accumulates all RacialTraits using the local function, and initial value of the PRT capability
00538 
00539 // Get the sum of the PRT and all LRTs
00540 #define GET_RACE_SUM(Function)                                                  \
00541         long l##Function(long v, const RacialTrait * lrt)       \
00542         {                                                                                                       \
00543                 return v + lrt->Function();                                             \
00544         }                                                                                                       \
00545                                                                                                                 \
00546         long Race::Function() const                                                     \
00547         {                                                                                                       \
00548                 if (CV##Function == -1)                                                 \
00549                         const_cast<Race *>(this)->CV##Function = accumulate(mLRTs.begin(), mLRTs.end(), mPRT->Function(), l##Function); \
00550                 return CV##Function;                                                            \
00551         }
00552 // Get the sum of the PRT and all LRTs
00553 #define GET_RACE_SUMD(Function)                                                 \
00554         double l##Function(long v, const RacialTrait * lrt)     \
00555         {                                                                                                       \
00556                 return v + lrt->Function();                                             \
00557         }                                                                                                       \
00558                                                                                                                 \
00559         double Race::Function() const                                                   \
00560         {                                                                                                       \
00561                 if (!CCalc##Function) {                                                         \
00562                         const_cast<Race *>(this)->CCalc##Function = true;\
00563                         const_cast<Race *>(this)->CV##Function = accumulate(mLRTs.begin(), mLRTs.end(), mPRT->Function(), l##Function); \
00564                 }                                                                                                       \
00565                 return CV##Function;                                                            \
00566         }
00567 // Get the product of all LRTs multiplied by each other
00568 #define GET_RACE_PRODUCT(Function)                                                      \
00569         double l##Function(double v, const RacialTrait * lrt)   \
00570         {                                                                                                               \
00571                 return v * double(lrt->Function());                                     \
00572         }                                                                                                               \
00573                                                                                                                         \
00574         double Race::Function() const                                                   \
00575         {                                                                                                               \
00576                 if (!CCalc##Function) {                                                         \
00577                         const_cast<Race *>(this)->CCalc##Function = true;\
00578                         const_cast<Race *>(this)->CV##Function = accumulate(mLRTs.begin(), mLRTs.end(), double(mPRT->Function()), l##Function); \
00579                 }                                                                                                       \
00580                 return CV##Function;                                                            \
00581         }
00582 // Get the product of all LRTs multiplied by each other as a %
00583 #define GET_RACE_PRODUCT_PER(Function)                                          \
00584         double l##Function(double v, const RacialTrait * lrt)   \
00585         {                                                                                                               \
00586                 return (1.0 - (1.0 - v) * (1.0 - lrt->Function()));     \
00587         }                                                                                                               \
00588                                                                                                                         \
00589         double Race::Function() const                                                   \
00590         {                                                                                                               \
00591                 if (!CCalc##Function) {                                                         \
00592                         const_cast<Race *>(this)->CCalc##Function = true;\
00593                         const_cast<Race *>(this)->CV##Function = accumulate(mLRTs.begin(), mLRTs.end(), mPRT->Function(), l##Function); \
00594                 }                                                                                                       \
00595                 return CV##Function;                                                            \
00596         }
00597 // Get the min value of all LRTs on the race
00598 #define GET_RACE_MIN(Function)                                                          \
00599         long l##Function(long v, const RacialTrait * lrt)               \
00600         {                                                                                                               \
00601                 return min(v, lrt->Function());                                         \
00602         }                                                                                                               \
00603                                                                                                                         \
00604         long Race::Function() const                                                             \
00605         {                                                                                                               \
00606                 return accumulate(mLRTs.begin(), mLRTs.end(), mPRT->Function(), l##Function);   \
00607         }
00608 // Get the max value of all LRTs on the race
00609 #define GET_RACE_MAX(Function)                                                          \
00610         long l##Function(long v, const RacialTrait * lrt)               \
00611         {                                                                                                               \
00612                 return max(v, lrt->Function());                                         \
00613         }                                                                                                               \
00614                                                                                                                         \
00615         long Race::Function() const                                                             \
00616         {                                                                                                               \
00617                 return accumulate(mLRTs.begin(), mLRTs.end(), mPRT->Function(), l##Function);   \
00618         }
00619 // Get the max value of all LRTs on the race
00620 #define GET_RACE_MAXD(Function)                                                         \
00621         double l##Function(double v, const RacialTrait * lrt)   \
00622         {                                                                                                               \
00623                 return max(v, lrt->Function());                                         \
00624         }                                                                                                               \
00625                                                                                                                         \
00626         double Race::Function() const                                                   \
00627         {                                                                                                               \
00628                 return accumulate(mLRTs.begin(), mLRTs.end(), mPRT->Function(), l##Function);   \
00629         }
00630 // Get true if the race has the capability, false otherwise
00631 #define GET_RACE_HAS(Function)                                                          \
00632         bool Race::Function() const                                                             \
00633         {                                                                                                               \
00634                 if (CV##Function != -1)                                                         \
00635                         return CV##Function ? true : false;                             \
00636                 const_cast<Race *>(this)->CV##Function = 1;                     \
00637                 if (mPRT->Function())                                                           \
00638                         return true;                                                                    \
00639                 for (deque<const RacialTrait *>::const_iterator i = mLRTs.begin(); i != mLRTs.end(); ++i)       \
00640                         if ((*i)->Function())                                                   \
00641                                 return true;                                                            \
00642                 const_cast<Race *>(this)->CV##Function = 0;                     \
00643                 return false;                                                                           \
00644         }
00645 
00646 GET_RACE_PRODUCT(GroundAttackFactor)
00647 GET_RACE_PRODUCT(GroundDefenseFactor)
00648 GET_RACE_PRODUCT(GrowthRateFactor)
00649 GET_RACE_PRODUCT(PopulationFactor)
00650 GET_RACE_HAS(CloakCargo)
00651 GET_RACE_SUM(MineSpeedBonus)
00652 GET_RACE_SUMD(SpyTechBonus)
00653 GET_RACE_SUMD(BattleSpeedBonus)
00654 GET_RACE_PRODUCT_PER(PermaformChance)
00655 GET_RACE_HAS(CanSeeHabSettings)
00656 GET_RACE_HAS(TemporaryTerraform)
00657 GET_RACE_HAS(ScanDesign)
00658 GET_RACE_PRODUCT(RepairFactor)
00659 GET_RACE_PRODUCT_PER(FreighterReproduction)
00660 GET_RACE_HAS(MineFieldScanning)
00661 GET_RACE_HAS(CanRemoteDetonate)
00662 GET_RACE_PRODUCT(MineDecayFactor)
00663 
00664 GET_RACE_HAS(PacketTerraform)
00665 GET_RACE_HAS(PacketScanning)
00666 GET_RACE_PRODUCT_PER(PacketCostMinFactor)
00667 GET_RACE_MIN(PacketSizeOneMin)
00668 GET_RACE_MIN(PacketSizeMixed)
00669 GET_RACE_MIN(PacketCostResources)
00670 GET_RACE_PRODUCT(PacketDecayFactor)
00671 GET_RACE_PRODUCT(PacketCatchFactor)
00672 GET_RACE_SUM(PacketDecayPenalty)
00673 
00674 GET_RACE_MAX(StartAtBonus)
00675 GET_RACE_HAS(GateCargo)
00676 GET_RACE_PRODUCT(OvergateLossFactor)
00677 GET_RACE_HAS(GateScanning)
00678 GET_RACE_MAX(ARTechType)
00679 GET_RACE_PRODUCT(FuelFactor)
00680 GET_RACE_HAS(GeneralResearch)
00681 GET_RACE_HAS(UltimateRecycle)
00682 GET_RACE_PRODUCT(SpaceScanFactor)
00683 GET_RACE_PRODUCT(PenScanFactor)
00684 GET_RACE_PRODUCT(StartingPopFactor)
00685 GET_RACE_PRODUCT(ZeroTechCost)
00686 GET_RACE_MAXD(MaxMiniturize)
00687 GET_RACE_MAXD(MiniturizeRate)
00688 GET_RACE_PRODUCT(ShieldFactor)
00689 GET_RACE_PRODUCT(ArmorFactor)
00690 GET_RACE_PRODUCT_PER(ShieldRegenRate)
00691 
00692 GET_RACE_PRODUCT(DefenseFactor)

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