// ################################
// ##  Objekty lodi a zakladen   ##
// ##   a objekty jejich casti   ##
// ################################

#pragma once
#ifndef FORTRESS_SKELET_H
#define FORTRESS_SKELET_H

#include "common.h"

#include <map>
#include <deque>
#include <vector>
#include <list>
#include <string>
#include <sstream>

#include "datetime.h"
#include "common_routines.h"
#include "mathfunc.h"

#include "fortress_classes.h"
#include "cache_list.h"
#include "context.h"
#include "items.h"
#include "dblists.h"
#include "space.h"

using namespace std;

// ################################
// ################################

class fortressClass;

class fortressSectionClass;

class mechanicsClass;

class commonItemClass;

class energeticAccumulatorClass;

class navigationComputerClass;
class quarkGluonCoreClass;
class subspaceBeaconClass;
class inertialDampersClass;

class impulsJetEngineClass;
class mechanicalDampersClass;

class mainframeClass;

class deflectorShieldsGeneratorClass;

class weaponEnergyCircuitClass;
class droneMissilesClass;
class droneMissileLauncherClass;
class laserGunClass;

class transportBeamGeneratorClass;

class androidsClass;

class highResolutionSensorsClass;
class longRangeSensorsClass;

class cloakingDeviceClass;

class probeClass;

class magneticalGridClass;
class transportContainerClass;
class energeticCellClass;

class plasmaFilterClass;
class scientificLabClass;
class lifeSupportClass;
class subspaceTransmitterClass;

class magneticalCollectorsOfPlasmaClass;
class submersibleFiltrationTankClass;
class submarineMiningMachineClass;
class undergroundDrillingMachineClass;

class magneticalFilterClass;
class deuteriumDecomposerClass;
class zirconiumReactorClass;
class ilmeniteFurnaceClass;

class hangarClass;

// ################################
// ################################

enum powerState
{
	PS_TURNED_ON,
	PS_TURNED_OFF,
	PS_ENERGY_LACK,
	PS_ENERGY_NOT_REQ
};

// ################################
// ################################

#define SHIP_LOADING_WEIGHT_LIMIT             16
#define BASE_LOADING_WEIGHT_LIMIT             128
#define SHELL_ANDROIDS_LOADING_LIMIT          0.5f
#define SHELL_ENERGETIC_CELLS_LOADING_LIMIT   0.25f

#define SHELL_MIN_BUILDING_TITANIUM           100000000 /* 100M */
#define SHELL_MAX_BUILDING_TITANIUM           400000000 /* 400M */

#define MINIMAL_DENSITY_OF_SHIP_CARGO         5120
#define MINIMAL_DENSITY_OF_BASE_CARGO         4096

#define SHIP_QUARRYING_MODIFIER_MULTIPLICATOR 1
#define BASE_QUARRYING_MODIFIER_MULTIPLICATOR 2

#define FORCE_BY_WEIGHT_LANDING_MULTIPLICATOR 32768
#define TAKING_OFF_BY_LANDING_MULTIPLICATOR   2

#define RING1_RANGE_IN_KM                     (double)1
#define RING2_RANGE_IN_KM                     (double)384403
#define RING4_RANGE_IN_KM                     (double)149597871
#define RING6_RANGE_IN_KM                     (double)9460730472581
#define RING7_RANGE_IN_KM                     (double)4.365f * RING6_RANGE_IN_KM

// ################################

#define SECONDS_TO_HOUR                                   3600
#define HOURS_TO_DAY                                      24

#define MAX_SECONDS_BETWEEN_QUARK_GLUON_PLASMA_UPDATES    8  * SECONDS_TO_HOUR * GAME_TIME_TO_WALL_TIME_SPEED_RATIO
#define MAX_SECONDS_BETWEEN_CONTAINERED_RESOURCES_UPDATES 8  * SECONDS_TO_HOUR * GAME_TIME_TO_WALL_TIME_SPEED_RATIO
#define MAX_SECONDS_BETWEEN_ENERGETIC_PHASES              4  * SECONDS_TO_HOUR * GAME_TIME_TO_WALL_TIME_SPEED_RATIO
#define MAX_SECONDS_BETWEEN_FABRICATING_CHANGES           16 * SECONDS_TO_HOUR * GAME_TIME_TO_WALL_TIME_SPEED_RATIO

#define MIN_SECONDS_BETWEEN_WEAPONS_WHOLE_CHARGING        4  * GAME_TIME_TO_WALL_TIME_SPEED_RATIO

#define MIN_CLIENT_UPDATE_DELAY_IN_SECONDS                1

// ################################
// ################################

class energyStateClass;
class tradableItemCountsClass;
typedef pair    <droneMissileLauncherClass*, energyStateClass       *> droneMissileLauncherPEnergyStatePPair;
typedef pair    <droneMissileLauncherClass*, energyStateClass        > droneMissileLauncherPEnergyStatePair;
typedef deque   <droneMissileLauncherPEnergyStatePair                > droneMissileLauncherPEnergyStatePairDeque;
typedef pair    <laserGunClass            *, energyStateClass       *> laserGunPEnergyStatePPair;
typedef pair    <laserGunClass            *, energyStateClass        > laserGunPEnergyStatePair;
typedef deque   <laserGunPEnergyStatePair                            > laserGunPEnergyStatePairDeque;
typedef pair    <dtIdentifier              , energyStateClass        > dtIdentifierEnergyStatePair;
typedef dbdeque <dtIdentifierEnergyStatePair                         > dtIdentifierEnergyStatePairDeque;
typedef deque   <hangarClass                                        *> hangarsPDeque;
typedef dbdeque <dtIdentifier                                        > dtIdentifierDeque;
typedef deque   <unsigned long                                       > unsignedLongDeque;
typedef vector  <unsigned long                                       > unsignedLongVector;
typedef vector  <unsigned long long                                  > unsignedLongLongVector;
typedef list    <commonItemClass                                    *> commonItemsPList;
typedef dblist  <dtIdentifier                                        > dtIdentifierList;
typedef vector  <fortressSectionClass                               *> fortressSectionPVector;
typedef map     <dtIdentifier              , tradableItemCountsClass > tradeMap;
typedef set     <dtIdentifier                                        > dtIdentifierSet;
typedef map     <dtIdentifier              , unsigned long long      > weaponIDEnergyMap;
typedef map     <dtIdentifier              , double                  > weaponIDGradientMap;

// ################################
// ################################

class powerStateClass
{
private:
	powerState state_;
	double     narrowCharging_;
public:
	powerStateClass()                      { state_ = PS_TURNED_OFF; narrowCharging_ = 0;                                                      };
    void DB_Init(powerState ps, double nc) { state_ = ps; narrowCharging_ = nc;                                                                };

	powerState getState     () { return state_;                                                                                                };
	bool       isWorking    () { if (PS_TURNED_ON == state_) return 1; else return 0;                                                          };
	void       turnOn       () { if (PS_TURNED_OFF == state_) state_ = PS_TURNED_ON; if (PS_ENERGY_NOT_REQ == state_) state_ = PS_ENERGY_LACK; };
	void       turnOff      () { if (PS_TURNED_ON == state_) state_ = PS_TURNED_OFF; if (PS_ENERGY_LACK == state_) state_ = PS_ENERGY_NOT_REQ; };
	void       energyLack   () { if (PS_TURNED_ON == state_) state_ = PS_ENERGY_LACK; if (PS_TURNED_OFF == state_) state_ = PS_ENERGY_NOT_REQ; };
	void       enoughEnergy () { if (PS_ENERGY_LACK == state_) state_ = PS_TURNED_ON; if (PS_ENERGY_NOT_REQ == state_) state_ = PS_TURNED_OFF; };
	void       turnOnByForce() { state_ = PS_TURNED_ON;                                                                                        };

	double     getNarrowCharging(            ) { return narrowCharging_;                                                                       };
	void       setNarrowCharging(double newNC) { narrowCharging_ = newNC;                                                                      };
};

// ################################

class energyStateClass
{
public:
	unsigned long long energy;
	unsigned long long targetEnergy;

	energyStateClass() { energy = 0; targetEnergy = 0; };
};

// ################################

class energyDivisionClass
#define ED_MIN_PRIORITY    1
#define ED_MAX_PRIORITY    16
{
public:
	unsigned char priority;
	unsigned int  ratio;
	double        maxPowerDrain;
	bool          shutDownOnEnergyLack;

	energyDivisionClass() { priority = ED_MIN_PRIORITY; ratio = 1; maxPowerDrain = 0; shutDownOnEnergyLack = 0; };
};

// ################################

class androidsAssignmentClass
#define AA_MIN_PRIORITY    1
#define AA_MAX_PRIORITY    16
{
public:
	unsigned char      priority;
	unsigned int       ratio;
	unsigned long long assignedDroids;

	androidsAssignmentClass() { priority = AA_MIN_PRIORITY; ratio = 1; assignedDroids = 0; };
};

// ################################

class tradableItemCountsClass
{
public:
	tradableItemCountsClass(unsigned long long working, unsigned long long damaged) { workingCount = working; damagedCount = damaged; };

	unsigned long long workingCount;
	unsigned long long damagedCount;
};

// ################################

class tradeBundleClass
{
private:
	tradeMap           itemsMap_;

	unsigned long long quarkGluonPlasma_;
	unsigned long long ulrea_;
	unsigned long long heavyWater_;
	unsigned long long deuterium_;
	unsigned long long zirconiumCrystal_;
	unsigned long long energy_;
	unsigned long long ilmenite_;
	unsigned long long titanium_;

	unsigned long long itemsWeight_;
	unsigned long long itemsSize_;

	unsigned long long quarkGluonPlasmaFreeSpace_;
	unsigned long long containeredResourcesFreeSpace_;
	unsigned long long energyFreeSpace_;

	commonItemClass  * getItemByID(dtIdentifier itemID) { return actx->cacheItemsList.getItem<commonItemClass>(itemID); };

	bool isEqual(const tradeBundleClass & secondBundle);
	bool isItemInBundleInCorrectCount(commonItemClass * item  )                                                                                                      ;
	bool isItemInBundleInCorrectCount(dtIdentifier      itemID) { return this->isItemInBundleInCorrectCount(actx->cacheItemsList.getItem<commonItemClass>(itemID)); };

	unsigned long long containeredResourcesSize();
public:
	tradeBundleClass() { itemsMap_.clear(); quarkGluonPlasma_ = 0; ulrea_ = 0; heavyWater_ = 0; deuterium_ = 0; zirconiumCrystal_ = 0; energy_ = 0; ilmenite_ = 0; titanium_ = 0; itemsWeight_ = 0; itemsSize_ = 0; quarkGluonPlasmaFreeSpace_ = 0; containeredResourcesFreeSpace_ = 0; energyFreeSpace_ = 0; };

	bool checkStorageOwnershipAndValidity(fortressClass * owner);
	void clearBundleToMatchAShell(fortressClass * shell);
	void updateWeightAndSize(bool validateItemsCounts);

	void insertQuarkGluonPlasma(unsigned long long quarkGluonPlasmaInMg) {                                                  this->quarkGluonPlasma_ += quarkGluonPlasmaInMg; };
	void insertUlrea           (unsigned long long ulreiCount          ) {                                                  this->ulrea_            += ulreiCount          ; };
	void insertHeavyWater      (unsigned long long heavyWaterInKg      ) { this->itemsWeight_      += heavyWaterInKg      ; this->heavyWater_       += heavyWaterInKg      ; };
	void insertDeuterium       (unsigned long long deuteriumInKg       ) { this->itemsWeight_      += deuteriumInKg       ; this->deuterium_        += deuteriumInKg       ; };
	void insertZirconiumCrystal(unsigned long long zirconiumCrystalInKg) { this->itemsWeight_      += zirconiumCrystalInKg; this->zirconiumCrystal_ += zirconiumCrystalInKg; };
	void insertEnergy          (unsigned long long energyInTJ          ) {                                                  this->energy_           += energyInTJ          ; };
	void insertIlmenite        (unsigned long long ilmeniteInKg        ) { this->itemsWeight_      += ilmeniteInKg        ; this->ilmenite_         += ilmeniteInKg        ; };
	void insertTitanium        (unsigned long long titaniumInKg        ) { this->itemsWeight_      += titaniumInKg        ; this->titanium_         += titaniumInKg        ; };
	void deleteQuarkGluonPlasma(unsigned long long quarkGluonPlasmaInMg) {                                                  this->quarkGluonPlasma_ -= quarkGluonPlasmaInMg; };
	void deleteUlrea           (unsigned long long ulreiCount          ) {                                                  this->ulrea_            -= ulreiCount          ; };
	void deleteHeavyWater      (unsigned long long heavyWaterInKg      ) { this->itemsWeight_      -= heavyWaterInKg      ; this->heavyWater_       -= heavyWaterInKg      ; };
	void deleteDeuterium       (unsigned long long deuteriumInKg       ) { this->itemsWeight_      -= deuteriumInKg       ; this->deuterium_        -= deuteriumInKg       ; };
	void deleteZirconiumCrystal(unsigned long long zirconiumCrystalInKg) { this->itemsWeight_      -= zirconiumCrystalInKg; this->zirconiumCrystal_ -= zirconiumCrystalInKg; };
	void deleteEnergy          (unsigned long long energyInTJ          ) {                                                  this->energy_           -= energyInTJ          ; };
	void deleteIlmenite        (unsigned long long ilmeniteInKg        ) { this->itemsWeight_      -= ilmeniteInKg        ; this->ilmenite_         -= ilmeniteInKg        ; };
	void deleteTitanium        (unsigned long long titaniumInKg        ) { this->itemsWeight_      -= titaniumInKg        ; this->titanium_         -= titaniumInKg        ; };

	unsigned long long & getQuarkGluonPlasmaInMg() { return quarkGluonPlasma_; };
	unsigned long long & getUlreaCount          () { return ulrea_           ; };
	unsigned long long & getHeavyWaterInKg      () { return heavyWater_      ; };
	unsigned long long & getDeuteriumInKg       () { return deuterium_       ; };
	unsigned long long & getZirconiumCrystalInKg() { return zirconiumCrystal_; };
	unsigned long long & getEnergyInTJ          () { return energy_          ; };
	unsigned long long & getIlmeniteInKg        () { return ilmenite_        ; };
	unsigned long long & getTitaniumInKg        () { return titanium_        ; };

	void insertItem(commonItemClass    * newItem    , unsigned long long working, unsigned long long damaged)                                                                             ;
	void insertItem(commonItemClass    * newItem                                                            ) {        this->insertItem(newItem                     ,       1,       0); };
	void insertItem(dtIdentifier         newItemID  , unsigned long long working, unsigned long long damaged) {        this->insertItem(this->getItemByID(newItemID), working, damaged); };
	void insertItem(dtIdentifier         newItemID                                                          ) {        this->insertItem(this->getItemByID(newItemID),       1,       0); };
	void deleteItem(tradeMap::iterator   oldIterator, unsigned long long working, unsigned long long damaged)                                                                             ;
	void deleteItem(tradeMap::iterator   oldIterator                                                        ) {        this->deleteItem(oldIterator                 ,       1,       0); };
	bool deleteItem(commonItemClass    * oldItem    , unsigned long long working, unsigned long long damaged)                                                                             ;
	bool deleteItem(commonItemClass    * oldItem                                                            ) { return this->deleteItem(oldItem                     ,       1,       0); };
	bool deleteItem(dtIdentifier         oldItemID  , unsigned long long working, unsigned long long damaged) { return this->deleteItem(this->getItemByID(oldItemID), working, damaged); };
	bool deleteItem(dtIdentifier         oldItemID                                                          ) { return this->deleteItem(this->getItemByID(oldItemID),       1,       0); };

	tradeMap::iterator bundleBegin() { return this->itemsMap_.begin(); };
	tradeMap::iterator bundleEnd()   { return this->itemsMap_.end()  ; };

	unsigned long long getTotalWeight()                                {                                                 return this->itemsWeight_;     };
	unsigned long long getTotalSize()                                  {                                                 return this->itemsSize_;       };
	unsigned long long getUpdatedTotalWeight(bool validateItemsCounts) { this->updateWeightAndSize(validateItemsCounts); return this->getTotalWeight(); };
	unsigned long long getUpdatedTotalSize  (bool validateItemsCounts) { this->updateWeightAndSize(validateItemsCounts); return this->getTotalSize();   };

	unsigned long long quarkGluonPlasmaOverheadInMg()                                    {                                                            return this->quarkGluonPlasma_ - min(this->quarkGluonPlasma_, this->quarkGluonPlasmaFreeSpace_    ); };
	unsigned long long containeredResourcesOverheadInM3()                                { unsigned long long CRS = this->containeredResourcesSize(); return CRS                     - min(CRS                    , this->containeredResourcesFreeSpace_); };
	unsigned long long energyOverheadInTJ()                                              {                                                            return this->energy_           - min(this->energy_          , this->energyFreeSpace_              ); };
	unsigned long long quarkGluonPlasmaUpdatedOverheadInMg    (bool validateItemsCounts) { this->updateWeightAndSize(validateItemsCounts);            return this->quarkGluonPlasmaOverheadInMg();                                                         };
	unsigned long long containeredResourcesUpdatedOverheadInM3(bool validateItemsCounts) { this->updateWeightAndSize(validateItemsCounts);            return this->containeredResourcesOverheadInM3();                                                     };
	unsigned long long energyUpdatedOverheadInTJ              (bool validateItemsCounts) { this->updateWeightAndSize(validateItemsCounts);            return this->energyOverheadInTJ();                                                                   };

	bool getItemsRecord(dtIdentifier itemID, unsigned long long & working, unsigned long long & damaged)                                                                                                   ;
	bool getItemsRecord(dtIdentifier itemID                                                            ) { unsigned long long working; unsigned long long damaged; return getItemsRecord(itemID, working, damaged); };

	bool operator== (const tradeBundleClass & secondBundle) { return this->isEqual(secondBundle);  };
	bool operator!= (const tradeBundleClass & secondBundle) { return (!((*this) == secondBundle)); };
};

// ################################
// ################################

class fortressSectionClass
{
public:
	androidsAssignmentClass androidsAssignment;

	fortressSectionClass() {};
	~fortressSectionClass() {};

	static  unsigned long long getMaxRepairingMechanicsBySize(double size) { if (0 < size) return max(1, (unsigned long long)(ANDROIDS_COUNT_FROM_SIZE_MULTIPLICATOR * pow(size, ANDROIDS_COUNT_FROM_SIZE_EXPONENT))); else return 0; };
	// kdyby tady mel nekdo nutkani vracet u getMaxRepairingMechanicsBySize minimalne 1, tak ROZHODNE NE (!!); pri oprave null itemu si pak zadaji kladne androidy, coz zacykli energetickou fazi, protoze cas do checkpointu itemu je 0

	virtual unsigned long long repairingAndroidsRequired()                                                            = 0;
	virtual          void      repair(fortressClass * owningFortress, unsigned long long seconds)                     = 0; // bere aktualne prirazene droidy a opravuje
	virtual unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange) = 0; // kdy se neco opravi; trupu je treba nastavit gradient
};

// ################################

class structuralIntegrityVoidSectionClass : public fortressSectionClass
{
private:
	fortressClass * owningFortress_;
	double          structuralIntegrityGradient_;
public:
	void setOwningFortress(fortressClass * owningFortress) { owningFortress_ = owningFortress; };

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &hullPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	double getGradient(                     ) { return structuralIntegrityGradient_;     };
    void   setGradient(const double gradient) { structuralIntegrityGradient_ = gradient; };

	structuralIntegrityVoidSectionClass() { owningFortress_ = NULL; structuralIntegrityGradient_ = 0; };
};

// ################################

class energeticSystemClass : public fortressSectionClass
{
private:
	dtIdentifier energeticAccumulatorID_;
	double       gradient_;
	bool         isGradientCalculated_;
public:
	energyStateClass energeticAccumulatorEnergyState;

	//void setEnergeticAccumulatorID(dtIdentifier newID) { energeticAccumulatorID_ = newID;                };
	//void removeEnergeticAccumulator()                  { setEnergeticAccumulatorID(NOT_VALID_ID);        };
	energeticAccumulatorClass * energeticAccumulator();
	bool nullEnergeticAccumulator()  { return NOT_VALID_ID == energeticAccumulatorID_;                                                                                                          };
	bool avalEnergeticAccumulator()  { return !nullEnergeticAccumulator();                                                                                                                      };
	dtIdentifier changeEnergeticAccumulator(dtIdentifier newID);
	void crushEnergeticAccumulator() { if (this->avalEnergeticAccumulator()) actx->cacheItemsList.deleteItem(energeticAccumulatorID_); energeticAccumulatorID_ = NOT_VALID_ID;                  };
	void annihilate();
	unsigned long long getEnergeticSystemWeight();
	unsigned long long getEnergy(fortressClass * owner);
	double             getGradient(fortressClass * owningFortress);
	void               setGradient(double newGradient)  { this->gradient_ = newGradient; this->isGradientCalculated_ = 1;                                                                       };

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &accPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	energeticSystemClass()  { energeticAccumulatorID_ = 0; gradient_ = 0; isGradientCalculated_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
    void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class subspaceDriveClass : public fortressSectionClass
#define MAX_PERC_DAMAGE_DUE_TO_WARP_FALL_OUT 90
{
private:
	dtIdentifier navigationComputerID_;
	dtIdentifier quarkGluonCoreID_;
	dtIdentifier subspaceBeaconID_;
	dtIdentifier inertialDampersID_;
	double       actualSpeedToC_;
public:
	bool isWorking()                                 { return 0 < actualSpeedToC_;                   };

	void switchToWarp()                              { actualSpeedToC_ = min(min(min(navigationComputer()->actualMaxSpeedToC(), quarkGluonCore()->actualMaxSpeedToC()), subspaceBeacon()->actualMaxSpeedToC()), inertialDampers()->actualMaxSpeedToC()); };
	void jumpOutOfWarp()                             { actualSpeedToC_ = 0;                          };
	double actualSpeedToC()                          { return actualSpeedToC_;                       };
	unsigned long actualConsumption()                { if (isWorking()) return quarkGluonCore()->actualConsumption(); else return 0;                                                                                                                     };

	bool         mountNavigationComputer(dtIdentifier newID) { if (avalNavigationComputer()) return 0; navigationComputerID_ = newID; return 1;                            };
	dtIdentifier unmountNavigationComputer()                 { dtIdentifier oldNaviComp = navigationComputerID_; navigationComputerID_ = NOT_VALID_ID; return oldNaviComp; };
	bool         mountQuarkGluonCore(dtIdentifier newID)     { if (avalQuarkGluonCore()) return 0; quarkGluonCoreID_ = newID; return 1;                                    };
	dtIdentifier unmountQuarkGluonCore()                     { dtIdentifier oldQGC = quarkGluonCoreID_; quarkGluonCoreID_ = NOT_VALID_ID; return oldQGC;                   };
	bool         mountSubspaceBeacon(dtIdentifier newID)     { if (avalSubspaceBeacon()) return 0; subspaceBeaconID_ = newID; return 1;                                    };
	dtIdentifier unmountSubspaceBeacon()                     { dtIdentifier oldSBC = subspaceBeaconID_; subspaceBeaconID_ = NOT_VALID_ID; return oldSBC;                   };
	bool         mountInertialDampers(dtIdentifier newID)    { if (avalInertialDampers()) return 0; inertialDampersID_ = newID; return 1;                                  };
	dtIdentifier unmountInertialDampers()                    { dtIdentifier oldInDam = inertialDampersID_; inertialDampersID_ = NOT_VALID_ID; return oldInDam;             };
	navigationComputerClass * navigationComputer();
	quarkGluonCoreClass     * quarkGluonCore();
	subspaceBeaconClass     * subspaceBeacon();
	inertialDampersClass    * inertialDampers();
	bool nullNavigationComputer()                    { return NOT_VALID_ID == navigationComputerID_; };
	bool nullQuarkGluonCore()                        { return NOT_VALID_ID == quarkGluonCoreID_    ; };
	bool nullSubspaceBeacon()                        { return NOT_VALID_ID == subspaceBeaconID_    ; };
	bool nullInertialDampers()                       { return NOT_VALID_ID == inertialDampersID_   ; };
	bool avalNavigationComputer()                    { return !nullNavigationComputer()            ; };
	bool avalQuarkGluonCore()                        { return !nullQuarkGluonCore()                ; };
	bool avalSubspaceBeacon()                        { return !nullSubspaceBeacon()                ; };
	bool avalInertialDampers()                       { return !nullInertialDampers()               ; };
	void annihilate();
	unsigned long long getSubspaceDriveWeight();

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &jetPts, unsigned long long &cmpPts, unsigned long long &becPts, unsigned long long &damPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	subspaceDriveClass() { navigationComputerID_ = 0; quarkGluonCoreID_ = 0; subspaceBeaconID_ = 0; inertialDampersID_ = 0; actualSpeedToC_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class impulsDriveClass : public fortressSectionClass
{
private:
	dtIdentifier   impulsJetEngineID_;
	dtIdentifier   mechanicalDampersID_;
	unsigned long  actualJetForce_;
public:
	bool          isWorking()                       { if (actualJetForce_) return 1; else return 0;                                                                                                                                                                                    };
	unsigned long getActualJetForce()               { return actualJetForce_;                                                                                                                                                                                                          };
	unsigned long actualConsumption()               { if (this->impulsJetEngine()->actualForceInGN()) return (unsigned long) ceil((double)actualJetForce_ / (double)this->impulsJetEngine()->actualForceInGN() * (double)this->impulsJetEngine()->actualConsumption()); else return 0; };

	void fullIgnite()                               { actualJetForce_ = this->impulsJetEngine()->actualForceInGN();                                                };
	void partitialIgnite(unsigned long long force)  { actualJetForce_ = (unsigned long)min((unsigned long long)this->impulsJetEngine()->actualForceInGN(), force); };
	void fireOut()                                  { actualJetForce_ = 0;                                                                                         };

	bool         mountImpulsJetEngine(dtIdentifier newID)   { if (avalImpulsJetEngine()) return 0; impulsJetEngineID_ = newID; return 1;                              };
	dtIdentifier unmountImpulsJetEngine()                   { dtIdentifier oldJet = impulsJetEngineID_; impulsJetEngineID_ = NOT_VALID_ID; return oldJet;             };
	bool         mountMechanicalDampers(dtIdentifier newID) { if (avalMechanicalDampers()) return 0; mechanicalDampersID_ = newID; return 1;                          };
	dtIdentifier unmountMechanicalDampers()                 { dtIdentifier oldMechDam = mechanicalDampersID_; mechanicalDampersID_ = NOT_VALID_ID; return oldMechDam; };
	impulsJetEngineClass   * impulsJetEngine();
	mechanicalDampersClass * mechanicalDampers();
	bool nullImpulsJetEngine()                      { return NOT_VALID_ID == impulsJetEngineID_  ;  };
	bool nullMechanicalDampers()                    { return NOT_VALID_ID == mechanicalDampersID_;  };
	bool avalImpulsJetEngine()                      { return !nullImpulsJetEngine()              ;  };
	bool avalMechanicalDampers()                    { return !nullMechanicalDampers()            ;  };
	void annihilate();
	unsigned long long getImpulsDriveWeight();

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &jetPts, unsigned long long &damPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	impulsDriveClass() { impulsJetEngineID_ = 0; mechanicalDampersID_ = 0; actualJetForce_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s );  
};

// ################################

class deflectorShieldsClass : public fortressSectionClass
{
private:
	dtIdentifier     deflectorShieldsGeneratorID_;
	double           narrowCharging_;
public:
	energyStateClass    deflectorShieldsEnergyState;
	energyDivisionClass deflectorsEnergyDivision;

	bool         mountDeflectorShieldsGenerator(dtIdentifier newID) { if (avalDeflectorShieldsGenerator()) return 0; deflectorShieldsGeneratorID_ = newID; deflectorShieldsEnergyState.targetEnergy = deflectorShieldsGenerator()->clientAccumulator(); return 1;                                                                   };
	dtIdentifier unmountDeflectorShieldsGenerator()                 { dtIdentifier oldDeflector = deflectorShieldsGeneratorID_; deflectorShieldsGeneratorID_ = NOT_VALID_ID; deflectorShieldsEnergyState.energy = 0; deflectorShieldsEnergyState.targetEnergy = 0; deflectorsEnergyDivision.maxPowerDrain = 0; return oldDeflector; };
	deflectorShieldsGeneratorClass * deflectorShieldsGenerator();
	bool nullDeflectorShieldsGenerator()                            { return NOT_VALID_ID == deflectorShieldsGeneratorID_; };
	bool avalDeflectorShieldsGenerator()                            { return !nullDeflectorShieldsGenerator()            ; };
	void annihilate();
	unsigned long long getDeflectorShieldsWeight();
	double             getActualEnergyConsumption()                 { return narrowCharging_;                                                                                              };
	void               setNarrowCharging(double nc)                 { narrowCharging_ = nc;                                                                                                };
	unsigned long long getEnergy(fortressClass * owner)                                                                                                                                     ;
	double             getGradient()                                { return narrowCharging_ - min(deflectorShieldsGenerator()->actualLeak(), (double)deflectorShieldsEnergyState.energy); };

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &defPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	deflectorShieldsClass() { deflectorShieldsGeneratorID_ = 0; narrowCharging_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class weaponsClass : public fortressSectionClass
{
private:
	dtIdentifier                     weaponEnergyCircuitID_;
	dtIdentifierEnergyStatePairDeque droneMissileLaunchersIDs_;
	dtIdentifier                     droneMissilesID_;
	dtIdentifierEnergyStatePairDeque laserGunsIDs_;
	double                           narrowCharging_;
public:
	energyDivisionClass weaponsEnergyDivision;

	bool         mountWeaponEnergyCircuit(dtIdentifier newID)                                  { if (avalWeaponEnergyCircuit()) return 0; weaponEnergyCircuitID_ = newID; return 1;                                                                                                                      };
	dtIdentifier unmountWeaponEnergyCircuit()                                                  { dtIdentifier oldWeaponCircuit = weaponEnergyCircuitID_; weaponEnergyCircuitID_ = NOT_VALID_ID; weaponsEnergyDivision.maxPowerDrain = 0; return oldWeaponCircuit;                                        };
	void         mountDroneMissiles(droneMissilesClass * pattern, unsigned long long count)    { if (pattern->isNull()) return; if (nullDroneMissiles()) droneMissilesID_ = (actx->cacheItemsList).insertItem(pattern->createEmptyCopyOfItemOfTheSameClass()); this->droneMissiles()->addWorking(count); };
	bool         mountDroneMissileLauncher(fortressClass * owningFortress, dtIdentifier newID);
	dtIdentifier unmountDroneMissileLauncherByID(dtIdentifier DMLID)                           { if (eraseByFirstValueInPair<dtIdentifierEnergyStatePairDeque, dtIdentifier>(droneMissileLaunchersIDs_, DMLID, 1)) return DMLID; else return NOT_VALID_ID;                                               };
	void         unmountAllDroneMissileLaunchers()                                             { droneMissileLaunchersIDs_.clear();                                                                                                                                                                      };
	bool         mountLaserGun(fortressClass * owningFortress, dtIdentifier newID);
	dtIdentifier unmountLaserGubByID(dtIdentifier LGID)                                        { if (eraseByFirstValueInPair<dtIdentifierEnergyStatePairDeque, dtIdentifier>(laserGunsIDs_, LGID, 1)) return LGID; else return NOT_VALID_ID;                                                             };
	void         unmountAllLaserGuns()                                                         { laserGunsIDs_.clear();                                                                                                                                                                                  };
	weaponEnergyCircuitClass              * weaponEnergyCircuit();
	droneMissileLauncherPEnergyStatePPair   droneMissileLaunchers(unsigned long position)      { if (position < droneMissileLaunchersIDs_.size()) return make_pair(actx->cacheItemsList.getItem<droneMissileLauncherClass>(droneMissileLaunchersIDs_[position].first), &(droneMissileLaunchersIDs_[position].second)); else return make_pair((droneMissileLauncherClass*)NULL, (energyStateClass*)NULL); };
	droneMissileLauncherClass             * droneMissileLaunchersOnly(unsigned long position)  { return droneMissileLaunchers(position).first;                                                                                                                                                           };
	droneMissilesClass                    * droneMissiles();
	laserGunPEnergyStatePPair               laserGuns(unsigned long position)                  { if (position < laserGunsIDs_.size())             return make_pair(actx->cacheItemsList.getItem<laserGunClass            >(laserGunsIDs_            [position].first), &(laserGunsIDs_            [position].second)); else return make_pair((laserGunClass            *)NULL, (energyStateClass*)NULL); };
	laserGunClass                         * laserGunsOnly(unsigned long position)              { return laserGuns(position).first                                                                                                                                                                      ; };
	bool nullWeaponEnergyCircuit()                                                             { return NOT_VALID_ID == weaponEnergyCircuitID_                                                                                                                                                         ; };
	bool nullDroneMissileLaunchers()                                                           { return droneMissileLaunchersIDs_.empty()                                                                                                                                                              ; };
	bool nullDroneMissiles()                                                                   { return NOT_VALID_ID == droneMissilesID_                                                                                                                                                               ; };
	bool nullLaserGuns()                                                                       { return laserGunsIDs_.empty()                                                                                                                                                                          ; };
	bool avalWeaponEnergyCircuit()                                                             { return !nullWeaponEnergyCircuit()                                                                                                                                                                     ; };
	bool avalDroneMissileLaunchers()                                                           { return !nullDroneMissileLaunchers()                                                                                                                                                                   ; };
	bool avalDroneMissiles()                                                                   { return !nullDroneMissiles()                                                                                                                                                                           ; };
	bool avalLaserGuns()                                                                       { return !nullLaserGuns()                                                                                                                                                                               ; };
	void               annihilate();
	void               dischargeAllWeapons();
	bool               isWeaponCharging(fortressClass * owner, commonItemClass * weapon, energyStateClass * es);
	unsigned long long weaponFireLimit(fortressClass * owner, commonItemClass * weapon, energyStateClass * es);
	unsigned long long energyToWeaponFireLimit(fortressClass * owner, commonItemClass * weapon, energyStateClass * es);
	unsigned long long getTotalWeaponsCharging(fortressClass * owner, unsigned long long * resultWithoutCircuit);
	bool               getDistanceToTheWeaponsTarget(fortressClass * owningFortress, dist_t & distance);
	unsigned long long getWeaponsWeight();
	unsigned long long getDroneMissilesSize();
	unsigned long      getDroneMissileLaunchersCount()                { return (unsigned long)droneMissileLaunchersIDs_.size();                   };
	unsigned long      getLaserGunsCount()                            { return (unsigned long)laserGunsIDs_.size();                               };
	unsigned long      getWeaponsCount()                              { return this->getDroneMissileLaunchersCount() + this->getLaserGunsCount(); };
	double             getActualEnergyConsumption()                   { return narrowCharging_;                                                   };
	void               setNarrowCharging(double nc)                   { narrowCharging_ = nc;                                                     };
	void               getEnergies(fortressClass * owningFortress, weaponIDGradientMap * gradientsMapFromGetGradientsMethod, weaponIDEnergyMap * energies);
	void               getGradients(fortressClass * owningFortress, weaponIDGradientMap * gradients);

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &cirPts, unsigned long long &droPts, vector<unsigned long long> &lauPts, vector<unsigned long long> &gunPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	weaponsClass() { weaponEnergyCircuitID_ = 0; droneMissilesID_ = 0; droneMissileLaunchersIDs_.clear(); laserGunsIDs_.clear(); narrowCharging_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  dtIdentifier ID, IBPP :: Statement& s );
	void               __internal_DB_Save       (  dtIdentifier ID, IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  dtIdentifier ID, IBPP :: Statement& s ); 
};

// ################################

class transportBeamClass : public fortressSectionClass
{
private:
	dtIdentifier transportBeamGeneratorID_;
	double narrowCharging_;
public:
	energyStateClass    tBeamEnergyState;
	energyDivisionClass tBeamEnergyDivision;

	bool         mountTransportBeamGenerator(dtIdentifier newID) { if (avalTransportBeamGenerator()) return 0; transportBeamGeneratorID_ = newID; tBeamEnergyState.targetEnergy = transportBeamGenerator()->clientAccumulator(); return 1;                                          };
	dtIdentifier unmountTransportBeamGenerator()                 { dtIdentifier oldTBG = transportBeamGeneratorID_; transportBeamGeneratorID_ = NOT_VALID_ID; tBeamEnergyState.energy = 0; tBeamEnergyState.targetEnergy = 0; tBeamEnergyDivision.maxPowerDrain = 0; return oldTBG; };
	transportBeamGeneratorClass * transportBeamGenerator();
	bool nullTransportBeamGenerator()                            { return NOT_VALID_ID == transportBeamGeneratorID_;                                                                                                                                                                };
	bool avalTransportBeamGenerator()                            { return !nullTransportBeamGenerator();                                                                                                                                                                            };
	void annihilate();
	unsigned long long getTransportBeamWeight();
	double getActualEnergyConsumption()                          { return narrowCharging_;                                                                                                                                                                                          };
	void   setNarrowCharging(double nc)                          { narrowCharging_ = nc;                                                                                                                                                                                            };
	double getGradient()                                         { return narrowCharging_;                                                                                                                                                                                          };

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &tbmPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	transportBeamClass() { transportBeamGeneratorID_ = 0; narrowCharging_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class miningDevicesClass : public fortressSectionClass
{
private:
	dtIdentifier magneticalCollectorsOfPlasmaID_;
	dtIdentifier submersibleFiltrationTankID_;
	dtIdentifier submarineMiningMachineID_;
	dtIdentifier undergroundDrillingMachineID_;

	double       quarkGluonPlasmaQuarrying_;
	double       heavyWaterQuarrying_;
	double       zirconiumCrystalQuarrying_;
	double       ilmeniteQuarrying_;
public:
	//bool         mountMagneticalCollectorsOfPlasma(dtIdentifier newID) { if (avalMagneticalCollectorsOfPlasma()) return 0; magneticalCollectorsOfPlasmaID_ = newID; return 1;                  };
	//dtIdentifier unmountMagneticalCollectorsOfPlasma()                 { dtIdentifier oldMCP = magneticalCollectorsOfPlasmaID_; magneticalCollectorsOfPlasmaID_ = NOT_VALID_ID; return oldMCP; };
	//bool         mountSubmersibleFiltrationTank(dtIdentifier newID)    { if (avalSubmersibleFiltrationTank()) return 0; submersibleFiltrationTankID_ = newID; return 1;                        };
	//dtIdentifier unmountSubmersibleFiltrationTank()                    { dtIdentifier oldSFT = submersibleFiltrationTankID_; submersibleFiltrationTankID_ = NOT_VALID_ID; return oldSFT;       };
	//bool         mountSubmarineMiningMachine(dtIdentifier newID)       { if (avalSubmarineMiningMachine()) return 0; submarineMiningMachineID_ = newID; return 1;                              };
	//dtIdentifier unmountSubmarineMiningMachine()                       { dtIdentifier oldSMM = submarineMiningMachineID_; submarineMiningMachineID_ = NOT_VALID_ID; return oldSMM;             };
	//bool         mountUndergroundDrillingMachine(dtIdentifier newID)   { if (avalUndergroundDrillingMachine()) return 0; undergroundDrillingMachineID_ = NOT_VALID_ID; return 1;               };
	//dtIdentifier unmountUndergroundDrillingMachine()                   { dtIdentifier oldUDM = undergroundDrillingMachineID_; undergroundDrillingMachineID_ = NOT_VALID_ID; return oldUDM;     };
	void mountMagneticalCollectorsOfPlasma(magneticalCollectorsOfPlasmaClass * pattern, unsigned long long count) { if (pattern->isNull()) return; if (this->nullMagneticalCollectorsOfPlasma()) this->magneticalCollectorsOfPlasmaID_ = (actx->cacheItemsList).insertItem(pattern->createEmptyCopyOfItemOfTheSameClass()); this->magneticalCollectorsOfPlasma()->addWorking(count); };
	void mountSubmersibleFiltrationTanks  (submersibleFiltrationTankClass * pattern   , unsigned long long count) { if (pattern->isNull()) return; if (this->nullSubmersibleFiltrationTank()   ) this->submersibleFiltrationTankID_    = (actx->cacheItemsList).insertItem(pattern->createEmptyCopyOfItemOfTheSameClass()); this->submersibleFiltrationTank()->addWorking(count)   ; };
	void mountSubmarineMiningMachines     (submarineMiningMachineClass * pattern      , unsigned long long count) { if (pattern->isNull()) return; if (this->nullSubmarineMiningMachine()      ) this->submarineMiningMachineID_       = (actx->cacheItemsList).insertItem(pattern->createEmptyCopyOfItemOfTheSameClass()); this->submarineMiningMachine()->addWorking(count)      ; };
	void mountUndergroundDrillingMachines (undergroundDrillingMachineClass * pattern  , unsigned long long count) { if (pattern->isNull()) return; if (this->nullUndergroundDrillingMachine()  ) this->undergroundDrillingMachineID_   = (actx->cacheItemsList).insertItem(pattern->createEmptyCopyOfItemOfTheSameClass()); this->undergroundDrillingMachine()->addWorking(count)  ; };
	magneticalCollectorsOfPlasmaClass * magneticalCollectorsOfPlasma();
	submersibleFiltrationTankClass    * submersibleFiltrationTank();
	submarineMiningMachineClass       * submarineMiningMachine();
	undergroundDrillingMachineClass   * undergroundDrillingMachine();
	bool nullMagneticalCollectorsOfPlasma()                            { return NOT_VALID_ID == magneticalCollectorsOfPlasmaID_; };
	bool nullSubmersibleFiltrationTank()                               { return NOT_VALID_ID == submersibleFiltrationTankID_   ; };
	bool nullSubmarineMiningMachine()                                  { return NOT_VALID_ID == submarineMiningMachineID_      ; };
	bool nullUndergroundDrillingMachine()                              { return NOT_VALID_ID == undergroundDrillingMachineID_  ; };
	bool avalMagneticalCollectorsOfPlasma()                            { return !nullMagneticalCollectorsOfPlasma()            ; };
	bool avalSubmersibleFiltrationTank()                               { return !nullSubmersibleFiltrationTank()               ; };
	bool avalSubmarineMiningMachine()                                  { return !nullSubmarineMiningMachine()                  ; };
	bool avalUndergroundDrillingMachine()                              { return !nullUndergroundDrillingMachine()              ; };
	void annihilate();
	unsigned long long getMiningDevicesWeight();
	unsigned long long getMiningDevicesSize();
	
	double getQuarkGluonPlasmaQuarrying()                                              { return	max(0, quarkGluonPlasmaQuarrying_);                                                                                                               };
	double getHeavyWaterQuarrying()                                                    { return max(0, heavyWaterQuarrying_      );                                                                                                               };
	double getZirconiumCrystalQuarrying()                                              { return max(0, zirconiumCrystalQuarrying_);                                                                                                               };
	double getIlmeniteQuarrying()                                                      { return max(0, ilmeniteQuarrying_        );                                                                                                               };
    bool   isActuallyQuarkGluonPlasmaQuarrying()                                       { return 0 < quarkGluonPlasmaQuarrying_;                                                                                                                   };
    bool   isActuallyHeavyWaterQuarrying()                                             { return 0 < heavyWaterQuarrying_;                                                                                                                         };
    bool   isActuallyZirconiumCrystalQuarrying()                                       { return 0 < zirconiumCrystalQuarrying_;                                                                                                                   };
    bool   isActuallyIlmeniteQuarrying()                                               { return 0 < ilmeniteQuarrying_;                                                                                                                           };
	double startQuarkGluonPlasmaQuarrying(dtIdentifier realmID)                        { return quarkGluonPlasmaQuarrying_ = (double)magneticalCollectorsOfPlasma()->actualTotalWindingSpeedInMilligrams(realmID); /* QGP defaultne v mg */       };
	double startHeavyWaterQuarrying(dtIdentifier realmID, double planetModifier)       { return heavyWaterQuarrying_       = planetModifier * (double)submersibleFiltrationTank()->actualTotalWindingSpeed(realmID);                              };
	double startZirconiumCrystalQuarrying(dtIdentifier realmID, double planetModifier) { return zirconiumCrystalQuarrying_ = planetModifier * (double)submarineMiningMachine()->actualTotalWindingSpeedInGrams(realmID)     * GRAMS_TO_KILOGRAMS; };
	double startIlmeniteQuarrying(dtIdentifier realmID, double planetModifier)         { return ilmeniteQuarrying_         = planetModifier * (double)undergroundDrillingMachine()->actualTotalWindingSpeedInGrams(realmID) * GRAMS_TO_KILOGRAMS; };
	void   finishQuarkGluonPlasmaQuarrying()                                           { quarkGluonPlasmaQuarrying_ = -1;                                                                                                                         };
	void   finishHeavyWaterQuarrying()                                                 { heavyWaterQuarrying_       = -1;                                                                                                                         };
	void   finishZirconiumCrystalQuarrying()                                           { zirconiumCrystalQuarrying_ = -1;                                                                                                                         };
	void   finishIlmeniteQuarrying()                                                   { ilmeniteQuarrying_         = -1;                                                                                                                         };
	void   finishAllQuarrying()                                                        { finishQuarkGluonPlasmaQuarrying(); finishHeavyWaterQuarrying(); finishZirconiumCrystalQuarrying(); finishIlmeniteQuarrying();                            };
	void   quarkGluonPlasmaDeviceChange(dtIdentifier realmID)                          { if (!(0 > quarkGluonPlasmaQuarrying_)) startQuarkGluonPlasmaQuarrying(realmID);                                                                          };
	void   heavyWaterDeviceChange(dtIdentifier realmID, double planetModifier)         { if (!(0 > heavyWaterQuarrying_      )) startHeavyWaterQuarrying(realmID, planetModifier);                                                                };
	void   zirconiumCrystalDeviceChange(dtIdentifier realmID, double planetModifier)   { if (!(0 > zirconiumCrystalQuarrying_)) startZirconiumCrystalQuarrying(realmID, planetModifier);                                                          };
	void   ilmeniteDeviceChange(dtIdentifier realmID, double planetModifier)           { if (!(0 > ilmeniteQuarrying_        )) startIlmeniteQuarrying(realmID, planetModifier);                                                                  };
	void   quarryingDevicesChange(dtIdentifier realmID, double HeWPM, double ZrCPM, double IlmPM)
		{ quarkGluonPlasmaDeviceChange(realmID); heavyWaterDeviceChange(realmID, HeWPM); zirconiumCrystalDeviceChange(realmID, ZrCPM); ilmeniteDeviceChange(realmID, IlmPM); };

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &mcpPts, unsigned long long &sftPts, unsigned long long &smmPts, unsigned long long &udmPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	miningDevicesClass() { magneticalCollectorsOfPlasmaID_ = 0; submersibleFiltrationTankID_ = 0; submarineMiningMachineID_ = 0; undergroundDrillingMachineID_ = 0; quarkGluonPlasmaQuarrying_ = 0; heavyWaterQuarrying_ = 0; zirconiumCrystalQuarrying_ = 0; ilmeniteQuarrying_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class probeDevicesClass : public fortressSectionClass
{
private:
	dtIdentifierDeque probesIDs_;
public:
	bool         mountProbe(dtIdentifier newID)     { probesIDs_.push_back(newID); return 1;                                                                                     };
	dtIdentifier unmountProbeByID(dtIdentifier PID) { if (eraseByValue<dtIdentifierDeque, dtIdentifier> (probesIDs_, PID, 1)) return PID; else return NOT_VALID_ID;              };
	void         unmountAllProbes()                 { probesIDs_.clear();                                                                                                        };
	probeClass * probes(unsigned long position)     { if (position < probesIDs_.size()) return actx->cacheItemsList.getItem<probeClass>(probesIDs_[position]); else return NULL; };
	bool nullProbes()                               { return probesIDs_.empty();                                                                                                 };
	bool avalProbes()                               { return !nullProbes();                                                                                                      };
	void annihilate();
	unsigned long long getProbeDevicesWeight();
	unsigned long long getProbeDevicesSize();

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(vector<unsigned long long> &proPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	probeDevicesClass() { probesIDs_.clear(); };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  dtIdentifier ID, IBPP :: Statement& s );
	void               __internal_DB_Save       (  dtIdentifier ID, IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  dtIdentifier ID, IBPP :: Statement& s ); 
};

// ################################

class sensorsClass : public fortressSectionClass
{
private:
	dtIdentifier highResolutionSensorsID_;
	dtIdentifier longRangeSensorsID_;
public:
	powerStateClass     sensorsHRPowerState    ;
	powerStateClass     sensorsLRPowerState    ;
	energyDivisionClass sensorsHREnergyDivision;
	energyDivisionClass sensorsLREnergyDivision;

	bool         mountHighResolutionSensors(dtIdentifier newID) { if (avalHighResolutionSensors()) return 0; if (NOT_VALID_ID != newID) sensorsHRPowerState.turnOn(); highResolutionSensorsID_ = newID; return 1;                                   };
	dtIdentifier unmountHighResolutionSensors()                 { dtIdentifier oldHRS = highResolutionSensorsID_; sensorsHRPowerState.turnOff(); sensorsHREnergyDivision.maxPowerDrain = 0; highResolutionSensorsID_ = NOT_VALID_ID; return oldHRS; };
	bool         mountLongRangeSensors(dtIdentifier newID)      { if (avalLongRangeSensors()) return 0; if (NOT_VALID_ID != newID) sensorsLRPowerState.turnOn(); longRangeSensorsID_ = newID; return 1;                                             };
	dtIdentifier unmountLongRangeSensors()                      { dtIdentifier oldLRS = longRangeSensorsID_; sensorsLRPowerState.turnOff(); sensorsLREnergyDivision.maxPowerDrain = 0; longRangeSensorsID_ = NOT_VALID_ID; return oldLRS;           };
	highResolutionSensorsClass * highResolutionSensors();
	longRangeSensorsClass      * longRangeSensors();
	bool nullHighResolutionSensors()                     { return NOT_VALID_ID == highResolutionSensorsID_                                  ; };
	bool nullLongRangeSensors()                          { return NOT_VALID_ID == longRangeSensorsID_                                       ; };
	bool avalHighResolutionSensors()                     { return !nullHighResolutionSensors()                                              ; };
	bool avalLongRangeSensors()                          { return !nullLongRangeSensors()                                                   ; };
	void annihilate();
	unsigned long long getSensorsWeight();
	double             getActualEnergyConsumptionHR()    { return sensorsHRPowerState.getNarrowCharging();                                    };
	double             getActualEnergyConsumptionLR()    { return sensorsLRPowerState.getNarrowCharging();                                    };

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &hrsPts, unsigned long long &lrsPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	sensorsClass() { highResolutionSensorsID_ = 0; longRangeSensorsID_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class cloakingClass : public fortressSectionClass
{
private:
	dtIdentifier cloakingDeviceID_;
public:
	powerStateClass     cloakingPowerState    ;
	energyDivisionClass cloakingEnergyDivision;

	bool         mountCloakingDevice(dtIdentifier newID) { if (avalCloakingDevice()) return 0; cloakingDeviceID_ = newID; if (NOT_VALID_ID != newID) cloakingPowerState.turnOn(); return 1;                                        };
	dtIdentifier unmountCloakingDevice()                 { dtIdentifier oldCloDev = cloakingDeviceID_; cloakingPowerState.turnOff(); cloakingEnergyDivision.maxPowerDrain = 0; cloakingDeviceID_ = NOT_VALID_ID; return oldCloDev; };
	cloakingDeviceClass * cloakingDevice();
	bool nullCloakingDevice()                    { return NOT_VALID_ID == cloakingDeviceID_                           ; };
	bool avalCloakingDevice()                    { return !nullCloakingDevice()                                       ; };
	unsigned long actualCloakingLevel();
	void annihilate();
	unsigned long long getCloakingWeight();
	double getActualEnergyConsumption()          { return cloakingPowerState.getNarrowCharging();                       };
	
	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &cloPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	cloakingClass() { cloakingDeviceID_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class crewClass : public fortressSectionClass
{
// cim nizsi je cislo typu posadky, tim vyssi je priorita leceni doktory
#define CREW_CAPITAN         0
#define CREW_DOCTOR          1
#define CREW_OFFICER         2
#define CREW_ENGINEER        3
#define CREW_PILOT           4
#define CREW_SCIENTIST       5
#define CREW_PASSENGER       6
#define CREW_COUNT_TOTAL     7
#define PEOPLE_WEIGHT        80
#define OFFICERS_EFFECTIVITY (double)0.1
#define DOC_RES_CHANCE       (double)0.9
#define DOC_CAN_HEAL         2
#define SELF_HEALING         (double)0.04
#define ROUNDING_ERROR_LIMIT 16
private:
	//unsigned long      weight_;   
	//unsigned long      transport_;
	// tohle budou asi konstanty
	unsignedLongVector ableCrew_;
	unsignedLongVector woundedCrew_;
public:
	crewClass(/*unsigned long weight, unsigned long transport*/)
	  { /*weight_ = weight; transport_ = transport;*/ ableCrew_.resize(CREW_COUNT_TOTAL, 0); woundedCrew_.resize(CREW_COUNT_TOTAL, 0); };
	unsigned long getEffectiveCountOf (unsigned short position                        )                                                                        ;
	unsigned long getAblesCountOf     (unsigned short position                        ) { return ableCrew_[position];                                         };
	unsigned long getWoundedCountOf   (unsigned short position                        ) { return woundedCrew_[position];                                      };
	unsigned long getTotalCountOf     (unsigned short position                        ) { return ableCrew_[position] + woundedCrew_[position];                };
	void          acceptSomeNewAbles  (fortressClass * owningFortress, unsigned short position, unsigned long & acceptedCount)                                 ;
	void          acceptSomeNewWounded(fortressClass * owningFortress, unsigned short position, unsigned long & acceptedCount)                                 ;
	void          releaseSomeAbles    (unsigned short position, unsigned long count   ) { ableCrew_   [position] = ulSafeSub(ableCrew_   [position], count);  };
	void          releaseSomeWounded  (unsigned short position, unsigned long count   ) { woundedCrew_[position] = ulSafeSub(woundedCrew_[position], count);  };
	void          healSome            (unsigned short position, unsigned long healed  ) { ulShiftPile(woundedCrew_[position], ableCrew_[position], healed );  };
	void          woundSome           (unsigned short position, unsigned long wounded ) { ulShiftPile(ableCrew_[position], woundedCrew_[position], wounded);  };
	void          killSomeWounded     (unsigned short position, unsigned long killed  ) { woundedCrew_[position] = ulSafeSub(woundedCrew_[position], killed); };
	void          reasonableSacrifice (                         unsigned long killed  )                                                                        ;
	void          healingPhase        (                                               )                                                                        ;
	void          annihilate          (                                               ) { return;                                                             };
	unsigned long getTotalCrewCount   (                                               )                                                                        ;
	unsigned long long getCrewWeight  (                                               )                                                                        ;
	void          dropPassengers      (fortressClass * owningFortress, unsigned long count, unsigned long & VIPPayers, unsigned long & commonPayers, unsigned long & poorPayers, unsigned long & miserablePayers);
//	void          setAblesCountOf     (unsigned short position, unsigned long newCount) { ableCrew_[position]    = newCount;                                  };
//	void          setWoundedCountOf   (unsigned short position, unsigned long newCount) { woundedCrew_[position] = newCount;                                  };

	unsigned long long repairingAndroidsRequired()                                                            { return 0                 ; };
	void repair(fortressClass * owningFortress, unsigned long long seconds)                                   {                          ; };
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange) { return maxSecondsToChange; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class accommodationsClass : public fortressSectionClass
{
#define ID_OF_APARTMENTS      1
#define ID_OF_ROOMS           2
#define ID_OF_CABINS          3
#define ID_OF_WAREHOUSES      4
#define POINTS_FOR_APARTMENT  8
#define POINTS_FOR_ROOM       4
#define POINTS_FOR_CABIN      2
#define POINTS_FOR_WAREHOUSE  1
#define APARTMENT_SIZE       32
#define ROOM_SIZE            16
#define CABIN_SIZE            8
#define WAREHOUSE_SIZE        4
private:
	unsigned long luxuryApartments_         ;
	unsigned long comfortableRooms_         ;
	unsigned long commonCabins_             ;
	unsigned long warehousesWithLifeSupport_;

	void divideOneCrewType(unsigned long count, unsigned short preferedAccomodationID, unsigned long & apartments, unsigned long & rooms, unsigned long & cabins, unsigned long & warehouses);
public:
	accommodationsClass() { luxuryApartments_ = 0; comfortableRooms_ = 0; commonCabins_ = 0; warehousesWithLifeSupport_ = 0; };
	unsigned long getLuxuryApartments          ()                       { return luxuryApartments_                                                                 ; };
	unsigned long getComfortableRooms          ()                       { return comfortableRooms_                                                                 ; };
	unsigned long getCommonCabins              ()                       { return commonCabins_                                                                     ; };
	unsigned long getWarehousesWithLifeSupport ()                       { return warehousesWithLifeSupport_                                                        ; };
	unsigned long getLivingSpaces              ()                       { return luxuryApartments_ + comfortableRooms_ + commonCabins_ + warehousesWithLifeSupport_; };
	         void getFreeAccomodationUnits     (fortressClass * owner, unsigned long & apartments, unsigned long & rooms, unsigned long & cabins, unsigned long & warehouses, bool skipPassengers = 0);
			 void addLuxuryApartments          (fortressClass * constructingFortress, unsigned long & moreAccommodationUnits);
			 void addComfortableRooms          (fortressClass * constructingFortress, unsigned long & moreAccommodationUnits);
			 void addCommonCabins              (fortressClass * constructingFortress, unsigned long & moreAccommodationUnits);
			 void addWarehousesWithLifeSupport (fortressClass * constructingFortress, unsigned long & moreAccommodationUnits);
	         void annihilate                   ()                       {                                                               ; };
	unsigned long getConsumedPoints            ()                       { return this->luxuryApartments_          * POINTS_FOR_APARTMENT +
		                                                                         this->comfortableRooms_          * POINTS_FOR_ROOM      +
																				 this->commonCabins_              * POINTS_FOR_CABIN     +
																				 this->warehousesWithLifeSupport_ * POINTS_FOR_WAREHOUSE; };
	unsigned long long getAccomodationsWeight();
	unsigned long long getAccomodationsSize();

	unsigned long long repairingAndroidsRequired()                                                            { return 0                 ; };
	void repair(fortressClass * owningFortress, unsigned long long seconds)                                   {                          ; };
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange) { return maxSecondsToChange; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class mechanicsClass : public fortressSectionClass
{
private:
	dtIdentifier           androidsID_;		
	unsigned long long     maxWorkingAndroids_;
	unsigned long long     maxRepairingAndroids_;
	fortressSectionPVector repairingVector_;
	unsigned long long     actualRepairingAndroids_;
	unsigned long long     actualConstructingAndroids_;
public:
	powerStateClass     androidsPowerState    ;
	energyDivisionClass androidsEnergyDivision;

	void initRepairingVector(fortressClass * owningFortress);
	void mountAndroids(androidsClass * pattern, unsigned long long count);
	androidsClass * androids();
	bool nullAndroids()                                      { return NOT_VALID_ID == androidsID_                            ; };
	bool avalAndroids()                                      { return !nullAndroids()                                        ; };
	void annihilate();
	unsigned long long getMechanicsWeight();
	unsigned long long getMechanicsSize();
	double getActualEnergyConsumption()                      { return androidsPowerState.getNarrowCharging();                  };

	void repairingPhase(fortressClass * owningFortress, unsigned long long secondsFromTheLastUpdate);
	unsigned long long repairingDistribution(fortressClass * owningFortress, unsigned long long maxSecondsToChange); // vraci sekundy, za jak dlouho ma dojit k dalsi repairingPhase

	unsigned long long getMaxWorkingAndroids()                              { return                         min(maxWorkingAndroids_  , this->androids()->getWorking   ());    };
	unsigned long long getMaxWorkingAndroidsSoft()                          { return                         min(maxWorkingAndroids_  , this->androids()->getCount     ());    };
	unsigned long long setMaxWorkingAndroids(unsigned long long androids)   { return maxWorkingAndroids_   = min(androids             , this->androids()->getCount     ());    };
	unsigned long long getMaxRepairingAndroids()                            { return                         min(maxRepairingAndroids_, this->getMaxWorkingAndroids    ());    };
	unsigned long long getMaxRepairingAndroidsSoft()                        { return                         min(maxRepairingAndroids_, this->getMaxWorkingAndroidsSoft());    };
	unsigned long long setMaxRepairingAndroids(unsigned long long androids) { return maxRepairingAndroids_ = min(androids             , this->getMaxWorkingAndroidsSoft());    };
	unsigned long long getMaxConstructingAndroids()                         { return ullSafeSub(this->getMaxWorkingAndroids(), this->getMaxRepairingAndroids());               };
	unsigned long long getMaxConstructingAndroidsSoft()                     { return ullSafeSub(this->getMaxWorkingAndroidsSoft(), this->getMaxRepairingAndroidsSoft());       };
	unsigned long long getActualWorkingAndroids()                           { return actualRepairingAndroids_ + actualConstructingAndroids_;                                   };
	unsigned long long getActualRepairingAndroids()                         { return actualRepairingAndroids_;                                                                 };
	unsigned long long getActualConstructingAndroids()                      { return actualConstructingAndroids_;                                                              };

	unsigned long long clientAndroidsStateSliderMax()                       { return this->androids()->getCount();                                                             };
	unsigned long long clientAndroidsStateSliderBackground()                { return min(this->clientAndroidsStateSliderMax()  , this->androids()->getWorking()             ); };
	unsigned long long clientWorkingAndroidsSliderMax()                     { return this->clientAndroidsStateSliderMax();                                                     };
	unsigned long long clientWorkingAndroidsSliderValue()                   { return min(this->clientWorkingAndroidsSliderMax(), this->getMaxWorkingAndroidsSoft()          ); };
	unsigned long long clientWorkingAndroidsSliderBackground()              { return min(this->clientWorkingAndroidsSliderMax(), this->clientAndroidsStateSliderBackground()); };
	unsigned long long clientRepConSliderMax()                              { return this->clientWorkingAndroidsSliderValue();                                                 };
	unsigned long long clientRepConSliderValue()                            { return min(this->clientRepConSliderMax()         , this->getMaxRepairingAndroidsSoft()        ); };
	unsigned long long clientRepConSliderBackground()                       { return min(this->clientRepConSliderMax()         , this->clientAndroidsStateSliderBackground()); };
	         void      commitWorkingAndroidsSlider(unsigned long long val)  { this->setMaxWorkingAndroids(val);                                                                };
			 void      commitRepConSlider(unsigned long long val)           { this->setMaxRepairingAndroids(val);                                                              };

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &andPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	mechanicsClass() { androidsID_ = 0; maxWorkingAndroids_ = 0; maxRepairingAndroids_ = 0; repairingVector_.clear(); actualRepairingAndroids_ = 0; actualConstructingAndroids_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class warehouseClass : public fortressSectionClass
{
private:
	dtIdentifier     magneticalGridID_;
	dtIdentifier     transportContainerID_;
	dtIdentifier     energeticCellID_;
	dtIdentifierList storageIDs_;

	void addCachedSeparateItem            (separateItemClass  * separateItem                                                                                         );
	void addUncachedSeparateItemAndCacheIt(separateItemClass  * separateItem                                                                                         );
	void addStackableItem                 (stackableItemClass * stackableItem, unsigned long long working, unsigned long long damaged, bool removePatternIfEmpty     );

	void subBundleFromItemsAndLeftItCached(tradeBundleClass   * bundle                                                                                               );
	void mergeItemsWithBundle             (tradeBundleClass   * bundle                                                                                               );
	void freeEmptyItemsInBundle           (tradeBundleClass   * bundle, bool doNotFreeSeparateItems                                                                  );

	static void tradeSubingPhase(warehouseClass * firstWarehouse, tradeBundleClass * firstOffer, warehouseClass * secondWarehouse, tradeBundleClass * secondOffer    );
	static void tradeAddingPhase(warehouseClass * firstWarehouse, tradeBundleClass * firstOffer, warehouseClass * secondWarehouse, tradeBundleClass * secondOffer    );
	static void tradePurifyPhase(warehouseClass * firstWarehouse, tradeBundleClass * firstOffer, warehouseClass * secondWarehouse, tradeBundleClass * secondOffer    );
public:
	magneticalGridClass                 * magneticalGrid()    ;
	transportContainerClass             * transportContainer();
	energeticCellClass                  * energeticCell()     ;
	bool nullMagneticalGrid()                        { return NOT_VALID_ID == magneticalGridID_;                                                                     };
	bool nullTransportContainer()                    { return NOT_VALID_ID == transportContainerID_;                                                                 };
	bool nullEnergeticCell()                         { return NOT_VALID_ID == energeticCellID_;                                                                      };
	bool avalMagneticalGrid()                        { return !nullMagneticalGrid();                                                                                 };
	bool avalTransportContainer()                    { return !nullTransportContainer();                                                                             };
	bool avalEnergeticCell()                         { return !nullEnergeticCell();                                                                                  };
	void setMagneticalGridID(dtIdentifier newID)     { if (this->avalMagneticalGrid()    ) errLogicalError("MGID lost"); magneticalGridID_     = newID;              };
	void setTransportContainerID(dtIdentifier newID) { if (this->avalTransportContainer()) errLogicalError("TCID lost"); transportContainerID_ = newID;              };
	void setEnergeticCellID(dtIdentifier newID)      { if (this->avalEnergeticCell()     ) errLogicalError("ECID lost"); energeticCellID_      = newID;              };
	void annihilate();

	void addItem(commonItemClass * item  , unsigned long long working, unsigned long long damaged, bool removePatternIfEmpty)                                         ;
	void addItem(commonItemClass * item  ,                                                         bool removePatternIfEmpty)                                         ;
	void addItem(dtIdentifier      itemID, unsigned long long working, unsigned long long damaged, bool removePatternIfEmpty)
	                                                 { this->addItem(actx->cacheItemsList.getItem<commonItemClass>(itemID), working, damaged, removePatternIfEmpty); };
	void addItem(dtIdentifier      itemID,                                                         bool removePatternIfEmpty)
	                                                 { this->addItem(actx->cacheItemsList.getItem<commonItemClass>(itemID),                   removePatternIfEmpty); };
	void dropItem(dtIdentifierList::iterator itemIterator, unsigned long long working, unsigned long long damaged, bool removeItemIfEmpty)                            ;
	void dropItem(dtIdentifierList::iterator itemIterator,                                         bool removeItemIfEmpty)                                            ;
	void dropItem(dtIdentifier itemID                    , unsigned long long working, unsigned long long damaged, bool removeItemIfEmpty)
	                                                 { this->dropItem(this->getIteratorByID(itemID), working, damaged, removeItemIfEmpty);                           };
	void dropItem(dtIdentifier itemID                    ,                                         bool removeItemIfEmpty)
	                                                 { this->dropItem(this->getIteratorByID(itemID),                   removeItemIfEmpty);                           };
	void dropItem(commonItemClass * item                 , unsigned long long working, unsigned long long damaged, bool removeItemIfEmpty)
	                                                 { this->dropItem(item->getID(),                 working, damaged, removeItemIfEmpty);                           };
	void dropItem(commonItemClass * item                 ,                                         bool removeItemIfEmpty)
	                                                 { this->dropItem(item->getID(),                                   removeItemIfEmpty);                           };
	dtIdentifierList::iterator storageBegin()        { return storageIDs_.begin();                                                                                   };
	dtIdentifierList::iterator storageEnd()          { return storageIDs_.end();                                                                                     };
	dtIdentifierList::iterator getIteratorByID(dtIdentifier itemID);

	unsigned long long getWarehouseWeight();
	unsigned long long getSizeOfItemsInWarehouse();

	static void tradeItemsWithoutAnyControl(warehouseClass * firstWarehouse, tradeBundleClass * firstOffer, warehouseClass * secondWarehouse, tradeBundleClass * secondOffer);
	       void transferBundleIntoShell(fortressClass * shell, tradeBundleClass * bundle);
		   void throwBundleIntoTheSpace(                       tradeBundleClass * bundle) { this->subBundleFromItemsAndLeftItCached(bundle);                                                      this->freeEmptyItemsInBundle(bundle, 0); };

	unsigned long long repairingAndroidsRequired();
	void warehouseClass::androidsDistribution(unsigned long long &mgrPts, unsigned long long &tcnPts, unsigned long long &eclPts, vector<unsigned long long> &itmPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	warehouseClass() { magneticalGridID_ = 0; transportContainerID_ = 0; energeticCellID_ = 0; storageIDs_.clear(); };

	//template<class itemClass> itemClass * getNthItemOfType(unsigned long position);
	//void removeItemByIteratorAndLeftItInCacheList(dtIdentifierList::iterator itemIt) { storageIDs_.erase(itemIt); };
	//void removeItemByID(dtIdentifier IID) { eraseByValue<dtIdentifierList, dtIdentifier> (storageIDs_, IID, 1); };
	//void removeAllItems() { storageIDs_.clear(); };
	//bool isItemInStorage(dtIdentifier itemID) { isItemInContainer<dtIdentifierList, dtIdentifier>(storageIDs_, itemID); };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  dtIdentifier ID, IBPP :: Statement& s );
	void               __internal_DB_Save       (  dtIdentifier ID, IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  dtIdentifier ID, IBPP :: Statement& s ); 
};

// ################################

class otherEquipmentClass : public fortressSectionClass
{
private:
	dtIdentifier plasmaFilterID_;
	dtIdentifier scientificLabID_;
	dtIdentifier lifeSupportID_;
	dtIdentifier subspaceTransmitterID_;
	double narrowCharging_;
public:
	energyDivisionClass lifeSupportEnergyDivision;

	bool         mountPlasmaFilter(dtIdentifier newID)        { if (avalPlasmaFilter()) return 0; plasmaFilterID_ = newID; return 1;                                                           };
	dtIdentifier unmountPlasmaFilter()                        { dtIdentifier oldPF = plasmaFilterID_; plasmaFilterID_ = NOT_VALID_ID; return oldPF;                                            };
	bool         mountScientificLab(dtIdentifier newID)       { if (avalScientificLab()) return 0; scientificLabID_ = newID; return 1;                                                         };
	dtIdentifier unmountScientificLab()                       { dtIdentifier oldSL = scientificLabID_; scientificLabID_ = NOT_VALID_ID; return oldSL;                                          };
	bool         mountLifeSupport(dtIdentifier newID)         { if (avalLifeSupport()) return 0; lifeSupportID_ = newID; return 1;                                                             };
	dtIdentifier unmountLifeSupport()                         { dtIdentifier oldLS = lifeSupportID_; lifeSupportID_ = NOT_VALID_ID; lifeSupportEnergyDivision.maxPowerDrain = 0; return oldLS; };
	bool         mountSubspaceTransmitter(dtIdentifier newID) { if (avalSubspaceTransmitter()) return 0; subspaceTransmitterID_ = newID; return 1;                                             };
	dtIdentifier unmountSubspaceTransmitter()                 { dtIdentifier oldST = subspaceTransmitterID_; subspaceTransmitterID_ = NOT_VALID_ID; return oldST;                              };
	plasmaFilterClass        * plasmaFilter();
	scientificLabClass       * scientificLab();
	lifeSupportClass         * lifeSupport();
	subspaceTransmitterClass * subspaceTransmitter();
	bool nullPlasmaFilter()                           { return NOT_VALID_ID == plasmaFilterID_                                              ; };
	bool nullScientificLab()                          { return NOT_VALID_ID == scientificLabID_                                             ; };
	bool nullLifeSupport()                            { return NOT_VALID_ID == lifeSupportID_                                               ; };
	bool nullSubspaceTransmitter()                    { return NOT_VALID_ID == subspaceTransmitterID_                                       ; };
	bool avalPlasmaFilter()                           { return !nullPlasmaFilter()                                                          ; };
	bool avalScientificLab()                          { return !nullScientificLab()                                                         ; };
	bool avalLifeSupport()                            { return !nullLifeSupport()                                                           ; };
	bool avalSubspaceTransmitter()                    { return !nullSubspaceTransmitter()                                                   ; };
	void annihilate();
	unsigned long long getOtherEquipmentWeight();
	double getActualEnergyConsumption()               { return narrowCharging_; };
	void   setNarrowCharging(double nc)               { narrowCharging_ = nc;   };

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &pflPts, unsigned long long &sclPts, unsigned long long &lspPts, unsigned long long &stmPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	otherEquipmentClass() { plasmaFilterID_ = 0; scientificLabID_ = 0; lifeSupportID_ = 0; subspaceTransmitterID_ = 0; narrowCharging_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class mainframeSystemClass : public fortressSectionClass
{
private:
	dtIdentifier mainframeID_;
	double narrowCharging_;
public:
	energyDivisionClass mainframeEnergyDivision;

	mainframeClass * mainframe();
	bool nullMainframe()                       { return NOT_VALID_ID == mainframeID_                                                                  ; };
	bool avalMainframe()                       { return !nullMainframe()                                                                              ; };
	void annihilate();
	dtIdentifier changeMainframe(dtIdentifier newMainframeID);
	void crushMainframe()                      { if (this->avalMainframe()) actx->cacheItemsList.deleteItem(mainframeID_); mainframeID_ = NOT_VALID_ID; };
	unsigned long long getMainframeSystemWeight();
	bool   isMainframeLackingEnergy()          { return this->narrowCharging_ < this->mainframe()->actualConsumption();                                 };
	bool   isMainframeWorking()                { return (!(this->isMainframeLackingEnergy()));                                                          };
	double getActualEnergyConsumption()        { return narrowCharging_;                                                                                };
	void   setNarrowCharging(double nc)        { narrowCharging_ = nc;                                                                                  };

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &mfrPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	mainframeSystemClass() { mainframeID_ = 0; narrowCharging_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################

class hangarsPortClass : public fortressSectionClass
{
private:
	dtIdentifierDeque hangarsIDs_;
public:
	bool         mountHangar(dtIdentifier newID)     { hangarsIDs_.push_back(newID); return 1;                                                                                       };
	dtIdentifier unmountHangarByID(dtIdentifier HID) { if (eraseByValue<dtIdentifierDeque, dtIdentifier> (hangarsIDs_, HID, 1)) return HID; else return NOT_VALID_ID;                };
	void         unmountAllHangars()                 { hangarsIDs_.clear();                                                                                                          };
	hangarClass * hangars(unsigned long position)    { if (position < hangarsIDs_.size()) return actx->cacheItemsList.getItem<hangarClass>(hangarsIDs_[position]); else return NULL; };
	bool nullHangars()                               { return hangarsIDs_.empty()                                                                                                  ; };
	bool avalHangars()                               { return !nullHangars()                                                                                                       ; };
	void annihilate();
	unsigned long long getHangarsPortWeight();
	unsigned long long getHangarsPortSize();
	unsigned long long totalConstructingAndroidsRequired();
	bool isHangarMounted(dtIdentifier hangarID);
    dtIdentifierDeque :: const_iterator beginHangarsIdentifiers() const   { return hangarsIDs_.begin();               };
    dtIdentifierDeque :: const_iterator endHangarsIdentifiers() const     { return hangarsIDs_.end();                 };
	unsigned long getHangarsCount()                                       { return (unsigned long)hangarsIDs_.size(); };
    hangarClass * hangarByIdentifier(dtIdentifier id) { return actx->cacheItemsList.getItem<hangarClass>(id); };

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(vector<unsigned long long> &hngPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	hangarsPortClass() { hangarsIDs_.clear(); };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  dtIdentifier ID, IBPP :: Statement& s );
	void               __internal_DB_Save       (  dtIdentifier ID, IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  dtIdentifier ID, IBPP :: Statement& s ); 
};

// ################################

class factoriesClass : public fortressSectionClass
{
private:
	dtIdentifier magneticalFilterID_;
	dtIdentifier deuteriumDecomposerID_;
	dtIdentifier zirconiumReactorID_;
	dtIdentifier ilmeniteFurnaceID_;
public:
	void mountMagneticalFilters   (magneticalFilterClass    * pattern, unsigned long long count) { if (pattern->isNull()) return; if (this->nullMagneticalFilter()   ) this->magneticalFilterID_    = (actx->cacheItemsList).insertItem(pattern->createEmptyCopyOfItemOfTheSameClass()); this->magneticalFilter()->addWorking(count)   ; };
	void mountDeuteriumDecomposers(deuteriumDecomposerClass * pattern, unsigned long long count) { if (pattern->isNull()) return; if (this->nullDeuteriumDecomposer()) this->deuteriumDecomposerID_ = (actx->cacheItemsList).insertItem(pattern->createEmptyCopyOfItemOfTheSameClass()); this->deuteriumDecomposer()->addWorking(count); };
	void mountZirconiumReactors   (zirconiumReactorClass    * pattern, unsigned long long count) { if (pattern->isNull()) return; if (this->nullZirconiumReactor()   ) this->zirconiumReactorID_    = (actx->cacheItemsList).insertItem(pattern->createEmptyCopyOfItemOfTheSameClass()); this->zirconiumReactor()->addWorking(count)   ; };
	void mountIlmeniteFurnaces    (ilmeniteFurnaceClass     * pattern, unsigned long long count) { if (pattern->isNull()) return; if (this->nullIlmeniteFurnace()    ) this->ilmeniteFurnaceID_     = (actx->cacheItemsList).insertItem(pattern->createEmptyCopyOfItemOfTheSameClass()); this->ilmeniteFurnace()->addWorking(count)    ; };
	//void setMagneticalFilterID(dtIdentifier newID)    { magneticalFilterID_    = newID;                                                };
	//void removeMagneticalFilter()                     { setMagneticalFilterID   (NOT_VALID_ID);                                        };
	//void setDeuteriumDecomposerID(dtIdentifier newID) { deuteriumDecomposerID_ = newID;                                                };
	//void removeDeuteriumDecomposer()                  { setDeuteriumDecomposerID(NOT_VALID_ID);                                        };
	//void setZirconiumReactorID(dtIdentifier newID)    { zirconiumReactorID_    = newID;                                                };
	//void removeZirconiumReactor()                     { setZirconiumReactorID   (NOT_VALID_ID);                                        };
	//void setIlmeniteFurnaceID(dtIdentifier newID)     { ilmeniteFurnaceID_     = newID;                                                };
	//void removeIlmeniteFurnace()                      { setIlmeniteFurnaceID    (NOT_VALID_ID);                                        };
	magneticalFilterClass    * magneticalFilter();
	deuteriumDecomposerClass * deuteriumDecomposer();
	zirconiumReactorClass    * zirconiumReactor();
	ilmeniteFurnaceClass     * ilmeniteFurnace();
	bool nullMagneticalFilter()                       { return NOT_VALID_ID == magneticalFilterID_                                   ; };
	bool nullDeuteriumDecomposer()                    { return NOT_VALID_ID == deuteriumDecomposerID_                                ; };
	bool nullZirconiumReactor()                       { return NOT_VALID_ID == zirconiumReactorID_                                   ; };
	bool nullIlmeniteFurnace()                        { return NOT_VALID_ID == ilmeniteFurnaceID_                                    ; };
	bool avalMagneticalFilter()                       { return !nullMagneticalFilter()                                               ; };
	bool avalDeuteriumDecomposer()                    { return !nullDeuteriumDecomposer()                                            ; };
	bool avalZirconiumReactor()                       { return !nullZirconiumReactor()                                               ; };
	bool avalIlmeniteFurnace()                        { return !nullIlmeniteFurnace()                                                ; };
	void annihilate();
	unsigned long long getFactoriesWeight();
	unsigned long long getFactoriesSize();

	unsigned long long repairingAndroidsRequired();
	void androidsDistribution(unsigned long long &mgfPts, unsigned long long &dedPts, unsigned long long &zirPts, unsigned long long &ilfPts, unsigned long androidsPower);
	void repair(fortressClass * owningFortress, unsigned long long seconds);
	unsigned long long secondsToChange(fortressClass * owningFortress, unsigned long long maxSecondsToChange);

	factoriesClass() { magneticalFilterID_ = 0; deuteriumDecomposerID_ = 0; zirconiumReactorID_ = 0; ilmeniteFurnaceID_ = 0; };

    /* !!! DO NOT CALL THIS DIRECTLY, ITERNAL USE ONLY !!! */
	void               __internal_DB_Load       (  IBPP :: Statement& s );
	void               __internal_DB_Save       (  IBPP :: Statement& s ); 
	void               __internal_DB_Insert     (  IBPP :: Statement& s ); 
};

// ################################
// ################################

class conquerResultClass
{
private:
	fortressAddingResult addingResult_;
	bool                 areDetailsAvailable_;
	bool                 isMainframeAble_;
	bool                 isEnergeticAccumulatorAble_;
	bool                 isEnoughEnergy_;
	unsigned long long   energy_;

	friend class fortressClass;
public:
	conquerResultClass() { isMainframeAble_ = 0; isEnergeticAccumulatorAble_ = 0; addingResult_ = FAR_NULL_FORTRESS; areDetailsAvailable_ = 0; isEnoughEnergy_ = 0; energy_ = 0; };

	bool isConquered()                               { return ((this->isFallenPreyButNotAdded()) && (FAR_DONE == this->addingResult_));                     };
	bool isFallenPreyButNotAdded()                   { return ((this->isMainframeAble_) && (this->isEnergeticAccumulatorAble_) && (this->isEnoughEnergy_)); };

	// tato funkce rika, jestli jsou dostupne detaily (temi se mysli mainframeFailure(), energeticAccumulatorFailure() a energyFailure())
	bool areDetailsAvailable()                       { return areDetailsAvailable_;                                                                         };
	// detaily nemusi byt dostupne napriklad v pripade, ze nekdo zkusi obsadit lod, ktera je moc daleko;
	// takovy pokus o obsazeni pochopitelne nemuze dat hraci informace o lodi, protoze je proste pri tom pokusu nezjisti

	bool               mainframeFailure()            { return (!(this->isMainframeAble_));                                                                  };
	bool               energeticAccumulatorFailure() { return (!(this->isEnergeticAccumulatorAble_));                                                       };
	bool               energyFailure()               { return (!(this->isEnoughEnergy_));                                                                   };
	unsigned long long getEnergyInTarget()           { return energy_;                                                                                      };
};

// ################################

enum attackResult
{
	AR_NOT_FIRED = 1,
	AR_MISS = 2,
	AR_FUTILE_HIT = 3,
	AR_HIT = 4,
	AR_CRITICAL_HIT = 5,
	AR_TARGET_ANNIHILATED = 6,
};

// ################################

class attackReportClass
{
private:
	fortressClass * source_;
	fortressClass * target_;

	bool            suppressClientUpdate_;
public:
	attackResult       result;
	bool               disruptiveBreakdown;
	unsigned long long deflectorShieldsEnergyLoss;
	double             deflectorShieldsEnergyLossPerc;
	unsigned long long structuralIntegrityLoss;
	double             structuralIntegrityLossPerc;

	attackReportClass(fortressClass * source, fortressClass * target, bool autosendClientUpdateInDestructor) 
	{
		this->source_ = source; this->target_ = target; suppressClientUpdate_ = !autosendClientUpdateInDestructor;
		result = AR_NOT_FIRED; disruptiveBreakdown = 0;
		deflectorShieldsEnergyLoss = 0; deflectorShieldsEnergyLossPerc = 0;
		structuralIntegrityLoss = 0; structuralIntegrityLossPerc = 0;
	};
	~attackReportClass();

	void            targetAnnihilated() { result = AR_TARGET_ANNIHILATED; this->target_ = NULL; };
	void            readInitialValues(fortressClass * target);
	void            unreadFinalValues(fortressClass * target);

	bool            offensiveReport(fortressClass * reader);
	bool            defensiveReport(fortressClass * reader);
	fortressClass * getAttacker() { return this->source_; };
	fortressClass * getDefender() { return this->target_; };
};

// ################################

enum baseBuildingResult
{
	BBR_SHELL_BUILT = 1,
	BBR_NO_PLANET_IN_RANGE = 2,
	BBR_NOT_ENOUGH_TITANIUM = 3,
	BBR_INVALID_PARAMS = 4,
	BBR_UNKNOWN_FAIL = 5
};

// ################################

enum mountingResult
{
	MR_DONE,
	MR_SLOT_OCCUPIED,
	MR_SLOT_EMPTY,
	MR_NOT_ENOUGH_ANDROIDS,
	MR_NOT_ENOUGH_ENERGY,
	MR_NOT_ENOUGH_STORAGE_SPACE,
	MR_BAD_FORTRESS_TYPE,
	MR_HANGAR_NOT_EMPTY,
	MR_UNKNOWN_FAIL
};

// ################################

enum tradingResult
{
	TR_DONE,
	TR_NOT_IN_RANGE,
	TR_FIRST_FORTRESS_WEIGHT_LIMIT,
	TR_SECOND_FORTRESS_WEIGHT_LIMIT,
	TR_FIRST_FORTRESS_CAPACITY_LIMIT,
	TR_SECOND_FORTRESS_CAPACITY_LIMIT,
	TR_FIRST_FORTRESS_NOT_STORING_ITEMS,
	TR_SECOND_FORTRESS_NOT_STORING_ITEMS,
	TR_FIRST_FORTRESS_MAGNETICAL_GRIDS_LACK,
	TR_SECOND_FORTRESS_MAGNETICAL_GRIDS_LACK,
	TR_FIRST_FORTRESS_TRANSPORT_CONTAINERS_LACK,
	TR_SECOND_FORTRESS_TRANSPORT_CONTAINERS_LACK,
	TR_FIRST_FORTRESS_ENERGETIC_CELLS_LACK,
	TR_SECOND_FORTRESS_ENERGETIC_CELLS_LACK,
	TR_UNKNOWN_FAIL
};

// ################################

enum dockingResult
{
	DR_OK = 1,
	DR_BAD_SOURCE_FORTRESS_TYPE = 2,
	DR_BAD_TARGET_FORTRESS_TYPE = 3,
	DR_UNCONTROLLABLE_TARGET = 4,
	DR_NOT_YOUR_DOCK = 5,
	DR_OUT_OF_RANGE = 6,
	DR_IMPULS_DRIVE_FAIL = 7,
	DR_NOT_ENOUGH_DEUTERIUM = 8,
	DR_NO_FREE_HANGAR = 9,
	DR_NOT_DOCKING_SHIP = 10,
	DR_UNKNOWN_FAIL = 11
};

// ################################

class fortressClass : public dataListObjectClass
{
#define ATTACK_TYPE_DRONES 0
#define ATTACK_TYPE_LASER  1
#define ATTACK_TYPE_TBEAM  2

#define FORTRESS_MAX_NAME_LENGTH 32

#define DRONE_PRECISION_MULTIPLICATOR 10
#define LASER_PRECISION_MULTIPLICATOR 8
#define TBEAM_PRECISION_MULTIPLICATOR 2

#define TBEAM_BREAKDOWN_MULTIPLICATOR_FOR_BASES 1000
#define TBEAM_BREAKDOWN_SHIELDS_MULTIPLICATOR   32
#define LASER_BREAKDOWN_MULTIPLICATOR_FOR_BASES 100
#define LASER_BREAKDOWN_SHIELDS_MULTIPLICATOR   10

// mezi tema konstantama jsou vazby - sice ne zadratovane , 
// ktere by nemohly byt porusene a ani nijak exaktni , 
// nicmene jejich poruseni vyvola ve hre nesmysly ,
// ac beh serveru to nijak neposkodi ( ze systemoveho hlediska )
#define HULL_DAMAGE_ENERGETIC_SYSTEM_CONDITION     25
#define HULL_DAMAGE_ENERGETIC_SYSTEM_CHANCE         0.50f
#define HULL_DAMAGE_ENERGETIC_SYSTEM_SIGNIFICANCE   8
#define HULL_DAMAGE_MAINFRAME_CONDITION            25
#define HULL_DAMAGE_MAINFRAME_CHANCE                0.50f
#define HULL_DAMAGE_MAINFRAME_SIGNIFICANCE          8
#define HULL_DAMAGE_DEFLECTOR_SHIELDS_CONDITION    50
#define HULL_DAMAGE_DEFLECTOR_SHIELDS_CHANCE        0.20f
#define HULL_DAMAGE_DEFLECTOR_SHIELDS_SIGNIFICANCE 10
#define HULL_DAMAGE_WEAPONS_CONDITION              75
#define HULL_DAMAGE_WEAPONS_CHANCE                  0.15f
#define HULL_DAMAGE_WEAPONS_SIGNIFICANCE           18
#define HULL_DAMAGE_TRANSPORT_BEAM_CONDITION       90
#define HULL_DAMAGE_TRANSPORT_BEAM_CHANCE           0.15f
#define HULL_DAMAGE_TRANSPORT_BEAM_SIGNIFICANCE    20
#define HULL_DAMAGE_ANDROIDS_CONDITION             60
#define HULL_DAMAGE_ANDROIDS_CHANCE                 0.10f
#define HULL_DAMAGE_ANDROIDS_SIGNIFICANCE          20
#define HULL_DAMAGE_CREW_CONDITION                 70
#define HULL_DAMAGE_CREW_CHANCE                     0.10f
#define HULL_DAMAGE_CREW_SIGNIFICANCE              30
#define HULL_DAMAGE_MINING_DEVICES_CONDITION       80
#define HULL_DAMAGE_MINING_DEVICES_CHANCE           0.20f
#define HULL_DAMAGE_MINING_DEVICES_SIGNIFICANCE    15
#define HULL_DAMAGE_SENSORS_CONDITION              10
#define HULL_DAMAGE_SENSORS_CHANCE                  0.50f
#define HULL_DAMAGE_SENSORS_SIGNIFICANCE           40
#define HULL_DAMAGE_PROBES_CONDITION               80
#define HULL_DAMAGE_PROBES_CHANCE                   0.20f
#define HULL_DAMAGE_PROBES_SIGNIFICANCE            15
#define HULL_DAMAGE_OTHER_EQUIPMENT_CONDITION      85
#define HULL_DAMAGE_OTHER_EQUIPMENT_CHANCE          0.15f
#define HULL_DAMAGE_OTHER_EQUIPMENT_SIGNIFICANCE   15
#define HULL_DAMAGE_CLOAKING_DEVICE_CONDITION     100
#define HULL_DAMAGE_CLOAKING_DEVICE_CHANCE          0.10f
#define HULL_DAMAGE_CLOAKING_DEVICE_SIGNIFICANCE   20
#define HULL_DAMAGE_PAYLOAD_CONDITION              99
#define HULL_DAMAGE_PAYLOAD_CHANCE                  0.10f
#define HULL_DAMAGE_PAYLOAD_SIGNIFICANCE           20
#define HULL_DAMAGE_SUBSPACE_DRIVE_CONDITION        5
#define HULL_DAMAGE_SUBSPACE_DRIVE_CHANCE           0.10f
#define HULL_DAMAGE_IMPULS_DRIVE_CONDITION         30
#define HULL_DAMAGE_IMPULS_DRIVE_CHANCE             0.25f
#define HULL_DAMAGE_IMPULS_DRIVE_SIGNIFICANCE      50
#define HULL_DAMAGE_HANGARS_CONDITION              99
#define HULL_DAMAGE_HANGARS_CHANCE                  0.10f
#define HULL_DAMAGE_HANGARS_SIGNIFICANCE           20
#define HULL_DAMAGE_FACTORIES_CONDITION            99
#define HULL_DAMAGE_FACTORIES_CHANCE                0.10f
#define HULL_DAMAGE_FACTORIES_SIGNIFICANCE         20

#define SHELL_DAMAGE_MULTIPLICATOR                  2
protected:
	dtIdentifier       realmID_;
	bool               controllable_;
	string             fortressName_;
	unsigned long long weight_;
	unsigned long long totalStructuralIntegrity_;
	unsigned long long structuralIntegrity_;
	double             length_;
	double             width_;
	double             height_;
	// manoeuvrability bude dopocitana

	double             quarkGluonPlasma_; // v miligramech     //          tezi se a rovnou pouziva
	double             ulrea_;            // pocet			   //          lovi se z plasmy, ale plasma neubyva
	double             heavyWater_;       // v kilogramech	   // -> DT    tezi se a vyrabi se z toho deuterium
	double             deuterium_;        // v kilogramech	   // HW ->    vyrabi se z tezke vody
	double             zirconiumCrystal_; // v kilogramech	   // -> EN    tezi se a vyrabi se z toho energie
	double             energy_;           // v tera joulech	   // ZC ->    vyrabi se ze zirkoniovych krystalu
	double             ilmenite_;         // v kilogramech	   // -> TT    tezi se a vyrabi se z toho titan
	double             titanium_;         // v kilogramech	   // IL ->    vyrabi se z ilmenitu

	double             quarkGluonPlasmaGradient_; // prirustek QGP
	double             ulreaGradient_;            // prirustek ulrei
	double             heavyWaterGradient_;       // prirustek tezke vody
	double             deuteriumGradient_;        // prirustek deuteria
	double             zirconiumCrystalGradient_; // prirustek zirkonovych krystalu
	double             energyGradient_;           // prirustek energie
	double             ilmeniteGradient_;         // prirustek ilmenitu
	double             titaniumGradient_;         // prirustek titanu
	// z gradientu se ani nic nepocita, jsou tam jen informativne pro optimalizaci
	// kdykoliv nekdo pozada o hodnotu nejake suroviny jen pro cteni, cely update je drahy
	// resit to lze tak, ze se aktualni hodnota spocita z gradientu
	// gradienty nastavuji updaty, dokud jsou v poradku, pak funguji gradienty

	dv_time::datetime  quarkGluonPlasmaUpdate_;     // QGP se skladuje v mrizkach, ma specificke vyuziti (warp) i tezbu (z hvezd)
	dv_time::datetime  ulreaUpdate_;                // ulrei se nemusi skladovat v nicem, tezi se nezavisle a nich je prubezne nespotrebovava
	dv_time::datetime  containeredResourcesUpdate_; // tezka voda, deuterium, zirkonove krystaly, ilmenit a titan updatuji spolu, protoze se uskladnuji v kontejnerech
	dv_time::datetime  energyUpdate_;               // energie by se mohla updatovat s containeredResources, ale vyuziva ji moc systemu, proto je to vypocetne nejnarocnejsi update, takze je od containeredResources oddelen
	// Tezka voda, deuterium, zirkoniove krystaly, ilmenit a titan musi mit spolecny update (kvuli spolecnym 
	// kontejnerum); energeticPhase je vypocetne dost narocna, takze pokud containeredResourcesUpdate vyrobi 
	// energii, ta se proste pricte do energy_ a neupravi update, coz je korektni, protoze distributionPhase
	// jen spotrebovava, nemuze ji to pomoci (jen uskodit - coz se resi volanim containeredResourcesUpdate).

	dv_time::datetime  quarkGluonPlasmaTrigger_;
	dv_time::datetime  containeredResourcesTrigger_;
	dv_time::datetime  energyTrigger_;

    dtIdentifier       fortressClassID_; /* index tridy lodi */

    /* indentifikatory poslednich triggeru */
    unsigned long long containeredResourcesTriggerIdentificator_;
    unsigned long long energyDistributionPhaseAndWeaponFireTriggerIdentificator_;
    unsigned long long quarkGluonPlasmaTriggerIdentificator_;


	// tohle obnovit jen pri nacitani dat, neni nutno drzet v db
	dtIdentifierSet    attackersThatLockedOnThis_;

	// vsechny TEMP: neukladat do databaze, ignorovat, nesahat na to
	dv_time::datetime  clientUpdateTEMP_; // WALL TIME, NIKOLIV GAME TIME!!!!
	bool               controllableTEMP_;
	bool               suppressWeaponsLockOnWarningTEMP_;
	fortressClass    * currentAttackerTEMP_;
public:
	structuralIntegrityVoidSectionClass structuralIntegrityVoidSection;

	energeticSystemClass  energeticSystem;
	deflectorShieldsClass deflectorShields;
	weaponsClass          weapons;
	transportBeamClass    transportBeam;
	miningDevicesClass    miningDevices;
	probeDevicesClass     probeDevices;
	sensorsClass          sensors;
	cloakingClass         cloaking;
	crewClass             crew;
	accommodationsClass   accommodations;
	mechanicsClass        mechanics;
	warehouseClass        warehouse;
	otherEquipmentClass   otherEquipment;
	mainframeSystemClass  mainframeSystem;
protected:
	dtIdentifier                     targetOfWeapons_;
	dv_time::datetime                lastTargetAimTime_;
	
	// konstruktor pro uplne novou lod, nablyskanou a zrovna vyrobenou ;o))
	fortressClass(string             fortressName,
				  unsigned long long weight,
				  unsigned long long totalStructuralIntegrity,
				  double             length,
				  double             width,
				  double             height,
				  dtIdentifier       fortressClassID):
	              fortressName_(fortressName),
				  weight_(weight),
				  totalStructuralIntegrity_(totalStructuralIntegrity),
				  length_(length),
				  width_(width),
				  height_(height),
				  fortressClassID_(fortressClassID)
				  {
					  realmID_                                                  = 0;
					  controllable_                                             = 0;
					  structuralIntegrity_                                      = totalStructuralIntegrity;
					  quarkGluonPlasma_                                         = 0;
					  ulrea_                                                    = 0;
					  heavyWater_                                               = 0;
					  deuterium_                                                = 0;
					  zirconiumCrystal_                                         = 0;
					  energy_                                                   = 0;
					  ilmenite_                                                 = 0;
					  titanium_                                                 = 0;
					  quarkGluonPlasmaGradient_                                 = 0;
					  ulreaGradient_                                            = 0;
					  heavyWaterGradient_                                       = 0;
					  deuteriumGradient_                                        = 0;
					  zirconiumCrystalGradient_                                 = 0;
					  energyGradient_                                           = 0;
					  ilmeniteGradient_                                         = 0;
					  titaniumGradient_                                         = 0;
					  quarkGluonPlasmaUpdate_                                   = wt2gt(dv_time::now());
					  ulreaUpdate_                                              = wt2gt(dv_time::now());
					  containeredResourcesUpdate_                               = wt2gt(dv_time::now());
					  energyUpdate_                                             = wt2gt(dv_time::now());
					  quarkGluonPlasmaTrigger_                                  = 0;
					  containeredResourcesTrigger_                              = 0;
					  energyTrigger_                                            = 0;
					  targetOfWeapons_                                          = 0;
					  lastTargetAimTime_                                        = wt2gt(dv_time::now());                                         
					  quarkGluonPlasmaTriggerIdentificator_                     = 0;
					  energyDistributionPhaseAndWeaponFireTriggerIdentificator_ = 0;
					  containeredResourcesTriggerIdentificator_                 = 0; 
					  suppressWeaponsLockOnWarningTEMP_                         = 0;
					  clientUpdateTEMP_                                         = 0;
					  currentAttackerTEMP_                                      = NULL;

					  this->structuralIntegrityVoidSection.setOwningFortress(this);
				  };

	        unsigned short     hullDeflection(unsigned long energyPassedByShields, bool & annihilated);
	        unsigned long      shieldsDeflection(unsigned long energyFromWeaponDamage, bool disruptiveBreakdown);

	                 bool      disruptiveBreakdownRaw(double att, double def);
					 bool      droneDisruptiveBreakdown(fortressClass * targetFortress);
					 bool      laserDisruptiveBreakdown(fortressClass * targetFortress, dtIdentifier laserGunID);
					 bool      tBeamDisruptiveBreakdown(fortressClass * targetFortress);

	                 bool      attackHitRaw(double att, double def);
					 bool      droneAttackHit(fortressClass * targetFortress);
					 bool      laserAttackHit(fortressClass * targetFortress);
					 bool      tBeamAttackHit(fortressClass * targetFortress);
	
	        unsigned long      fireDroneMissile(unsigned long launcherPos);
			unsigned long      fireLaser       (unsigned long laserGunPos);
			unsigned long      fireTBeam       (                         );

	        unsigned short     decStructuralIntegrityAndReturnPercOfDamage(unsigned long structuralIntegrityLoss);

			         void      energeticSystemDamage (unsigned short damagedShardPerc);
					 void      mainframeDamage       (unsigned short damagedShardPerc);
					 void      deflectorShieldsDamage(unsigned short damagedShardPerc);
					 void      weaponsDamage         (unsigned short damagedShardPerc);
					 void      transportBeamDamage   (unsigned short damagedShardPerc); 
					 void      androidsDamage        (unsigned short damagedShardPerc); // mechanics
					 void      crewDamage            (unsigned short damagedShardPerc);
					 void      miningDevicesDamage   (unsigned short damagedShardPerc);			 
					 void      sensorsDamage         (unsigned short damagedShardPerc);
					 void      probesDamage          (unsigned short damagedShardPerc);
					 void      otherEquipmentDamage  (unsigned short damagedShardPerc);
					 void      cloakingDeviceDamage  (unsigned short damagedShardPerc);
					 void      payloadDamage         (unsigned short damagedShardPerc); // vybrane partie warehouse
			 // damage ubykaci chybi a je to tak schvalne

	virtual          void      shipsAndBasesDamage   (unsigned short damagePerc, unsigned short actualStructuralIntegrityPerc, bool & annihilated) = 0;

	        attackResult       attackFortress        (fortressClass * targetFortress, unsigned short attackType, unsigned long launcherPos);

/*	        unsigned long      rawMaterialContainersTransferLimit(unsigned long      containers,
				                                                  unsigned long long targetFreeWeight,
																  unsigned long long targetFreeCapacity,
																  unsigned long long totalMaterialWeight,
																  unsigned long long totalMaterialSize, 
																  unsigned long      materialDensity,
																  unsigned long long otherRawMaterialsCapacity,
																  unsigned long      totalSourceContainers, 
																  unsigned long      workingSourceContainers,
																  unsigned long      containerWeight,
																  unsigned long      containerSize,
																  unsigned long      containerCapacity);*/
			unsigned long long fortressCoreOnlyCargoWeight(bool doNotUpdate, bool ignoreResources, bool softUpdate);
			unsigned long long fortressCoreOnlySizeOfCargoInWarehouse();

	// pomocne metody pro tezeni a tovarneni
	virtual unsigned long      impulsJetEngineConsumption() = 0;

	virtual double             energyProductionByConsumption   (double             consumption) = 0;
	virtual unsigned long long deuteriumProductionByConsumption(unsigned long long consumption) = 0;
	virtual unsigned long long titaniumProductionByConsumption (unsigned long long consumption) = 0;

	virtual double             energyFabricationWeightLoss   (double             consumption) = 0;
	virtual double             energyFabricationSpaceLoss    (double             consumption) = 0;
	virtual double             deuteriumFabriactionWeightLoss(unsigned long long consumption) = 0;
	virtual double             deuteriumFabricationSpaceLoss (unsigned long long consumption) = 0;
	virtual double             titaniumFabricationWeightLoss (unsigned long long consumption) = 0;
	virtual double             titaniumFabricationSpaceLoss  (unsigned long long consumption) = 0;

//	virtual double             zirconiumCrystalConsumptionByDiff(double diff) = 0;
	virtual double             deuteriumConsumptionByDiff       (double diff) = 0;
	virtual double             ilmeniteConsumptionByDiff        (double diff) = 0;

	//.teoreticka rychlost tezby, neomezena kapacitou
	        double             quarkGluonPlasmaQuarryingPotential();
	virtual double             quarkGluonPlasmaConsumptionPotential() = 0;

	virtual double             ulreaFilteringPotential(bool isInWarp) = 0;

	        double             heavyWaterQuarryingPotential();
	virtual double             heavyWaterConsumptionPotential() = 0;

	        double             zirconiumCrystalQuarryingPotential();
	virtual double             zirconiumCrystalConsumptionPotential() = 0;

	        double             ilmeniteQuarryingPotential();
	virtual double             ilmeniteConsumptionPotential() = 0;

	// tezici a spotrebni funkce musi byt nutne velmi silne v tom smyslu, ze musi reflektovat vse, tedy zejmena:
	// 1/ u pokrocilych spotrebnich surovin, zda je lze vyrabet a je na ne dost vytezenych surovin
	// 2/ jestli je misto, kam suroviny davat (pokud neni, lze jich vyrabet jen tolik, kolik nekde ubyva - funkce musi spolupracovat) - TOTO NAKONEC NENI NUTNE, LZE PROSTE PRI KAZDEM UPDATU PREBYTECNE SUROVINY OREZAT
	// spotreba cilove suroviny se ma ukazovat PLNA bez ohledu na cokoliv (v pripade nedostatku update vypne spotrebu), tezebni suroviny se budou automaticky regulovat podle potreb tovaren
	virtual          void      fallOutOfWarpDueToQuarkGluonPlasmaLack() = 0;
	        double             quarkGluonPlasmaQuarryingSpeed();
			double             quarkGluonPlasmaConsumptionSpeed();

	virtual double             ulreaFilteringSpeed() = 0;

	        double             heavyWaterQuarryingSpeed()                                { return heavyWaterQuarryingPotential()                                                                   ; };
			double             heavyWaterConsumptionSpeed()                              { return min(heavyWaterConsumptionPotential(), heavyWater_ + heavyWaterQuarryingSpeed())                  ; };

	virtual          void      switchOffImpulsDueToDeuteriumLack() = 0;
	        double             deuteriumFabricationSpeed(dv_time::datetime * nextChange);
			double             deuteriumConsumptionSpeed();

	        double             zirconiumCrystalQuarryingSpeed()                          { return zirconiumCrystalQuarryingPotential()                                                             ; };
			double             zirconiumCrystalConsumptionSpeed()                        { return min(zirconiumCrystalConsumptionPotential(), zirconiumCrystal_ + zirconiumCrystalQuarryingSpeed()); };

	                 void      switchOffMainframeDueToEnergyLack();
			         void      lifeSupportNarrowDueToEnergyLack(double narrowCharging);
			double             energyHarvestingSpeed(dv_time::datetime * nextChange);

	        double             ilmeniteQuarryingSpeed()                                  { return ilmeniteQuarryingPotential()                                                                     ; };
			double             ilmeniteConsumptionSpeed()                                { return min(ilmeniteConsumptionPotential(), ilmenite_ + ilmeniteQuarryingSpeed())                        ; };

	        double             titaniumFabricationSpeed(dv_time::datetime * nextChange);
	// vsechny tezebni a fabrikacni funkce reaguji na AKTUALNI STAV, jsou tedy bezstavove, netriggeruji, protoze to resi updaty
	// priority mista: zirkonium, tezka voda, ilmenit

			unsigned long long mountingPointsRequiredForItemMounting(commonItemClass * item, unsigned long long count);
			unsigned long long energyRequiredForItemMounting(unsigned long long mountingPointsRequired);
	        dtIdentifier       changeEnergeticAccumulator(dtIdentifier newEAID);
			dtIdentifier       changeMainframe(dtIdentifier newMFID);
	virtual          bool      mountQuarkGluonPlasmaCore(dtIdentifier newQGPC) = 0;
	virtual          bool      mountNavigationComputer(dtIdentifier newNC)     = 0;
	virtual          bool      mountSubspaceBeacon(dtIdentifier newSB)         = 0;
	virtual          bool      mountInertialDampers(dtIdentifier newID)        = 0;
	virtual          bool      mountImpulsJetEngine(dtIdentifier newIJE)       = 0;
	virtual          bool      mountMechanicalDampers(dtIdentifier newMD)      = 0;
					 bool      mountDeflectorShieldsGenerator(dtIdentifier newDSGID);
					 bool      mountWeaponEnergyCircuit(dtIdentifier newWECID);
					 bool      mountDroneMissiles(droneMissilesClass * pattern, unsigned long long count);
					 bool      mountDroneMissileLauncher(dtIdentifier newDMLID);
					 bool      mountLaserGun(dtIdentifier newLGID);
					 bool      mountTransportBeamGenerator(dtIdentifier newTBGID);
					 bool      mountMagneticalCollectorsOfPlasma(magneticalCollectorsOfPlasmaClass * pattern, unsigned long long count);
					 bool      mountSubmersibleFiltrationTanks(submersibleFiltrationTankClass * pattern, unsigned long long count);
					 bool      mountSubmarineMiningMachines(submarineMiningMachineClass * pattern, unsigned long long count);
					 bool      mountUndergroundDrillingMachines(undergroundDrillingMachineClass * pattern, unsigned long long count);
					 bool      mountProbe(dtIdentifier newPID);
					 bool      mountHighResolutionSensors(dtIdentifier newHRSID);
					 bool      mountLongRangeSensors(dtIdentifier newLRSID);
					 bool      mountCloakingDevice(dtIdentifier newCDID);
					 bool      mountAndroids(androidsClass * pattern, unsigned long long count);
					 bool      mountPlasmaFilter(dtIdentifier newPFID);
					 bool      mountScientificLab(dtIdentifier newSLID);
					 bool      mountLifeSupport(dtIdentifier newLSID);
					 bool      mountSubspaceTransmitter(dtIdentifier newSTID);
	virtual          bool      mountHangar(dtIdentifier newH)               = 0;
	virtual          bool      mountMagneticalFilter(magneticalFilterClass * pattern, unsigned long long count)       = 0;
	virtual          bool      mountDeuteriumDecomposer(deuteriumDecomposerClass * pattern, unsigned long long count) = 0;
	virtual          bool      mountZirconiumReactor(zirconiumReactorClass * pattern, unsigned long long count)       = 0;
	virtual          bool      mountIlmeniteFurnace(ilmeniteFurnaceClass * pattern, unsigned long long count)         = 0;
	        mountingResult     unmountItemPrepare(commonItemClass * item, unsigned long long & workingCount, unsigned long long & damagedCount, bool alreadyStoraged);
			mountingResult     unmountItemPrepare(commonItemClass * item, bool alreadyStoraged);

	virtual          bool      isPossibleToQuarryQuarkGluonPlasma(spaceRegularObject ** quarryingPlatform) = 0;
	virtual          bool      isPossibleToQuarryHeavyWater      (spaceRegularObject ** quarryingPlatform) = 0;
	virtual          bool      isPossibleToQuarryZirconiumCrystal(spaceRegularObject ** quarryingPlatform) = 0;
	virtual          bool      isPossibleToQuarryIlmenite        (spaceRegularObject ** quarryingPlatform) = 0;

	virtual unsigned long      getFortressQuarryingModifierMultiplicator() = 0;

	        double             quarkGluonPlasmaActualModifier() {                              if (isPossibleToQuarryQuarkGluonPlasma(NULL   )) return 1;                                                            else return -1; };
			double             heavyWaterActualModifier()       { spaceRegularObject * planet; if (isPossibleToQuarryHeavyWater      (&planet)) return ((spacePlanetObject *)planet)->getHeavyWaterModifier();       else return -1; };
			double             zirconiumCrystalActualModifier() { spaceRegularObject * planet; if (isPossibleToQuarryZirconiumCrystal(&planet)) return ((spacePlanetObject *)planet)->getZirconiumCrystalModifier(); else return -1; };
			double             ilmeniteActualModifier()         { spaceRegularObject * planet; if (isPossibleToQuarryIlmenite        (&planet)) return ((spacePlanetObject *)planet)->getIlmeniteModifier();         else return -1; };

			         bool      getDistanceFrom     (fortressClass * target, dist_t & distance);
					 bool      isTargetInRangeRing0(fortressClass * target); // cil je zadokovany ve zdroji, nebo je zdroj zadokovany v cili
					 bool      isTargetInRangeRing1(fortressClass * target); // maximalni vzdalenost mezi pevnostmi je konstantni (1km)
					 bool      isTargetInRangeRing2(fortressClass * target); // maximalni vzdalenost mezi pevnostmi je vzdalenost zeme-mesic
					 bool      isTargetInRangeRing3(fortressClass * target); // obe pevnosti jsou spolu v oblasti a stredem je planeta
					 bool      isTargetInRangeRing4(fortressClass * target); // maximalni vzdalenost mezi pevnostmi je astronomicka jednotka
					 bool      isTargetInRangeRing5(fortressClass * target); // obe pevnosti jsou spolu v oblasti a stredem je hvezda (nepocitaji se podoblasti)
					 bool      isTargetInRangeRing6(fortressClass * target); // maximalni vzdalenost mezi pevnostmi je svetelny rok
					 bool      isTargetInRangeRing7(fortressClass * target); // maximalne vzdalenost mezi pevnostmi je vzdalenost slunce-alfa centauri

					 void      updateClient(bool authoritative);

    friend class hangarClass;
public:
    /* konstruktor pro databazi */
	fortressClass(void) { suppressWeaponsLockOnWarningTEMP_ = 0; currentAttackerTEMP_ = NULL; clientUpdateTEMP_ = 0; };

    unsigned short             getStructuralIntegrityPerc(void);
    unsigned short             getShieldPerc(void);

	                 void      globalUpdate();
					 void      annihilate();

	                 void      setFortressRealm(dtIdentifier newRealmID) { realmID_ = newRealmID;                                                               };
	dtIdentifier               getFortressRealmID()                      { return realmID_;                                                                     };
    dtIdentifier               getFortressClassID() const                { return fortressClassID_;                                                             };
	realmClass               * getFortressRealm()                        { return actx->cacheRealmsList.getItem<realmClass>(realmID_);                          };
	fortressClassClass       * getFortressClass()                        { return actx->cacheFortressClassesList.getItem<fortressClassClass>(fortressClassID_); };

	                 void      setFortressName(string & newName) { newName.resize(min((size_t)newName.length(), (size_t)FORTRESS_MAX_NAME_LENGTH)); fortressName_.swap(newName);                                                                                                                       };
					 void      addIDBehindName()                 { stringstream buff; buff.str(""); buff << this->fortressName_ << string(".") << this->getID(); buff >> this->fortressName_; this->fortressName_.resize(min((size_t)this->fortressName_.length(), (size_t)FORTRESS_MAX_NAME_LENGTH)); };
	        string             getFortressName() const           { return fortressName_;                                                                                                                                                                                                               };

	virtual fortressesTypes    getFortressType()            = 0;
	virtual          bool      isConstructed(bool readOnly) = 0;
	virtual          bool      isShell(bool readOnly)       = 0;
	                 bool      isControllable() { return this->controllable_;               };
					 void      gainControl()    { controllable_ = 1; controllableTEMP_ = 1; };
					 void      loseControl()    { controllable_ = 0; controllableTEMP_ = 0; };

	                 void      initRepairableSectionsVector        (fortressSectionPVector & sectionVector);
	virtual          void      initRepairableSpecificSectionsVector(fortressSectionPVector & sectionVector) = 0;

	                 bool      getDistanceToTheWeaponsTarget(dist_t & distance);
			unsigned long long getLongestWeaponRange();
			         bool      isProtectedFromAttacksAndScanning();
					 bool      isTargetProtectedFromAttacks();
					 bool      isAttackPrevented();
					 bool      isTargetHiddenForScanning       (fortressClass * target);
					 bool      isTargetHiddenForObserving      (fortressClass * target);
					 bool      isInRangeForConquer             (fortressClass * target);
					 bool      isInRangeForAttack              (fortressClass * target);
					 bool      isInRangeForTrade               (fortressClass * target);
					 bool      isInRangeForScanning            (fortressClass * target);
					 bool      isInRangeForObserving           (fortressClass * target);
					 void      getFortressesInFreeSpaceRange   (dtIdentifierList & bases, dtIdentifierList & ships, unsigned long long range);
					 void      getFortressesInRangeForConquer  (dtIdentifierList * bases, dtIdentifierList * ships);
					 void      getFortressesInRangeForAttack   (dtIdentifierList * bases, dtIdentifierList * ships);
					 void      getFortressesInRangeForTrade    (dtIdentifierList * bases, dtIdentifierList * ships);
					 void      getFortressesInRangeForScanning (dtIdentifierList * bases, dtIdentifierList * ships);
					 void      getFortressesInRangeForObserving(dtIdentifierList * bases, dtIdentifierList * ships);

	        conquerResultClass fallPrey();
		  fortressAddingResult conquerTarget(fortressClass * target, conquerResultClass * conquerResult);
		  
		             bool      isFortressClassAvailable(dtIdentifier classID);
					 void      getAvailableFortressClasses(dtIdentifierList * fortressClasses, dtIdentifierList * basesClasses, dtIdentifierList * shipsClasses);
					 void      getAvailableFortressClasses(dtIdentifierList * fortressClasses                                                                  );
					 void      getAvailableFortressClasses(                                    dtIdentifierList * basesClasses, dtIdentifierList * shipsClasses);

	virtual          bool      isThereSomeAblePlanetToBuildAShell(spacePlanetObject ** buildingPlanet) = 0;
	        unsigned long long requiredTitaniumToBuildAShell     (spacePlanetObject *  buildingPlanet);
			unsigned long long missingTitaniumToBuildAShell      (spacePlanetObject *  buildingPlanet);
			         bool      isEnoughResourcesToBuildAShell    (spacePlanetObject *  buildingPlanet) { return 0 == this->missingTitaniumToBuildAShell(buildingPlanet); };
			baseBuildingResult buildNewBaseShell(dtIdentifier newFortressClassID, unsigned long long buildingTitanium);

			unsigned long long dockingDownCost();
			dockingResult      canDockDown(fortressClass * targetFortress, hangarClass ** dockingHangar);
			dockingResult      canDockDown(fortressClass * targetFortress) { return this->canDockDown(targetFortress, NULL); };
			dockingResult      dockDown(fortressClass * targetFortress);
			unsigned long long unboundingCost();
			dockingResult      canBeUnbounded();
			dockingResult      unboundUp();

			unsigned long long getFortressScientistsEffectivity();
	      
	        dv_time::datetime  quarkGluonPlasmaUpdate(dv_time::datetime updateToATime);
					 void      quarkGluonPlasmaUpdate();
					 void      ulreaUpdate();
			dv_time::datetime  containeredResourcesUpdate(dv_time::datetime updateToATime);
					 void      containeredResourcesUpdate();
			dv_time::datetime  energyDistributionPhaseAndWeaponsFire(dv_time::datetime updateToATime); // muze to byt i stary cas
	                 void      energyDistributionPhaseAndWeaponsFire(bool doubleUpdate = 0);
					 void      resourcesUpdate() { quarkGluonPlasmaUpdate(); ulreaUpdate(); containeredResourcesUpdate(); energyDistributionPhaseAndWeaponsFire(); };

			double             getEnergyGrowthByGradient(double gradient) { return dv_time::secondsBegunBetween(this->energyUpdate_, wt2gt(dv_time::now()), 1) * gradient; };

			unsigned long long actualQGP() { return (unsigned long long)(quarkGluonPlasma_ + dv_time::secondsBegunBetween(quarkGluonPlasmaUpdate_    , wt2gt(dv_time::now()), 1) * quarkGluonPlasmaGradient_); };
			unsigned long long actualUlr() { return (unsigned long long)(ulrea_            + dv_time::secondsBegunBetween(ulreaUpdate_               , wt2gt(dv_time::now()), 1) * ulreaGradient_           ); };
			unsigned long long actualHeW() { return (unsigned long long)(heavyWater_       + dv_time::secondsBegunBetween(containeredResourcesUpdate_, wt2gt(dv_time::now()), 1) * heavyWaterGradient_      ); };
			unsigned long long actualDeu() { return (unsigned long long)(deuterium_        + dv_time::secondsBegunBetween(containeredResourcesUpdate_, wt2gt(dv_time::now()), 1) * deuteriumGradient_       ); };
			unsigned long long actualZrC() { return (unsigned long long)(zirconiumCrystal_ + dv_time::secondsBegunBetween(containeredResourcesUpdate_, wt2gt(dv_time::now()), 1) * zirconiumCrystalGradient_); };
			unsigned long long actualEng() { return (unsigned long long)(energy_           + dv_time::secondsBegunBetween(energyUpdate_              , wt2gt(dv_time::now()), 1) * energyGradient_          ); };
			unsigned long long actualIlm() { return (unsigned long long)(ilmenite_         + dv_time::secondsBegunBetween(containeredResourcesUpdate_, wt2gt(dv_time::now()), 1) * ilmeniteGradient_        ); };
			unsigned long long actualTit() { return (unsigned long long)(titanium_         + dv_time::secondsBegunBetween(containeredResourcesUpdate_, wt2gt(dv_time::now()), 1) * titaniumGradient_        ); };

            double             quarkGluonPlasmaGradient(void)   { return quarkGluonPlasmaGradient_; };   // prirustek QGP
	        double             ulreaGradient(void)              { return ulreaGradient_;            };   // prirustek ulrei
	        double             heavyWaterGradient(void)         { return heavyWaterGradient_;       };   // prirustek tezke vody
	        double             deuteriumGradient(void)          { return deuteriumGradient_;        };   // prirustek deuteria
	        double             zirconiumCrystalGradient(void)   { return zirconiumCrystalGradient_; };   // prirustek zirkonovych krystalu
	        double             energyGradient(void)             { return energyGradient_;           };   // prirustek energie
	        double             ilmeniteGradient(void)           { return ilmeniteGradient_;         };   // prirustek ilmenitu
	        double             titaniumGradient(void)           { return titaniumGradient_;         };   // prirustek titanu           

			unsigned long long updateQGP() { quarkGluonPlasmaUpdate()               ; return (unsigned long long)quarkGluonPlasma_; };
			unsigned long long updateUlr() { ulreaUpdate()                          ; return (unsigned long long)ulrea_           ; };
			unsigned long long updateHeW() { containeredResourcesUpdate()           ; return (unsigned long long)heavyWater_      ; };
			unsigned long long updateDeu() { containeredResourcesUpdate()           ; return (unsigned long long)deuterium_       ; };
			unsigned long long updateZrC() { containeredResourcesUpdate()           ; return (unsigned long long)zirconiumCrystal_; };
			unsigned long long updateEng() { energyDistributionPhaseAndWeaponsFire(); return (unsigned long long)energy_          ; };
			unsigned long long updateIlm() { containeredResourcesUpdate()           ; return (unsigned long long)ilmenite_        ; };
			unsigned long long updateTit() { containeredResourcesUpdate()           ; return (unsigned long long)titanium_        ; };
			         void      updateAll() { quarkGluonPlasmaUpdate(); ulreaUpdate(); containeredResourcesUpdate(); energyDistributionPhaseAndWeaponsFire(); };

			unsigned long long quarkGluonPlasmaInMg(bool readOnly) { if (readOnly) return actualQGP(); else return updateQGP(); };
			unsigned long long ulreiCount          (bool readOnly) { if (readOnly) return actualUlr(); else return updateUlr(); };
			unsigned long long heavyWaterInKg      (bool readOnly) { if (readOnly) return actualHeW(); else return updateHeW(); };
			unsigned long long deuteriumInKg       (bool readOnly) { if (readOnly) return actualDeu(); else return updateDeu(); };
			unsigned long long zirconiumCrystalInKg(bool readOnly) { if (readOnly) return actualZrC(); else return updateZrC(); };
			unsigned long long energyInTJ          (bool readOnly) { if (readOnly) return actualEng(); else return updateEng(); };
			unsigned long long ilmeniteInKg        (bool readOnly) { if (readOnly) return actualIlm(); else return updateIlm(); };
			unsigned long long titaniumInKg        (bool readOnly) { if (readOnly) return actualTit(); else return updateTit(); };

			unsigned long long addQuarkGluonPlasma(unsigned long long &mgs) { mgs = min(mgs, freeSpaceForQuarkGluonPlasmaInMiligrams(0, 0)    ); quarkGluonPlasma_ += mgs; updateAll(); return quarkGluonPlasmaInMg(1); };
			unsigned long long addUlrei           (unsigned long long &cnt) {                                                                  ; ulrea_            += cnt; updateAll(); return ulreiCount(1)          ; };
			unsigned long long addHeavyWater      (unsigned long long &kgs) { kgs = min(kgs, freeSpaceForHeavyWaterInKilograms(0, 0, 0)       ); heavyWater_       += kgs; updateAll(); return heavyWaterInKg(1)      ; };
			unsigned long long addDeuterium       (unsigned long long &kgs) { kgs = min(kgs, freeSpaceForDeuteriumInKilograms(0, 0, 0)        ); deuterium_        += kgs; updateAll(); return deuteriumInKg(1)       ; };
			unsigned long long addZirconiumCrystal(unsigned long long &kgs) { kgs = min(kgs, freeSpaceForZirconiumCrystalsInKilograms(0, 0, 0)); zirconiumCrystal_ += kgs; updateAll(); return zirconiumCrystalInKg(1); };
			unsigned long long addEnergy          (unsigned long long &tjs) { tjs = min(tjs, freeSpaceForEnergyInTeraJoules(0, 0)             ); energy_           += tjs; updateAll(); return energyInTJ(1)          ; };
			unsigned long long addIlmenite        (unsigned long long &kgs) { kgs = min(kgs, freeSpaceForIlmeniteInKilograms(0, 0, 0)         ); ilmenite_         += kgs; updateAll(); return ilmeniteInKg(1)        ; };
			unsigned long long addTitanium        (unsigned long long &kgs) { kgs = min(kgs, freeSpaceForTitaniumInKilograms(0, 0, 0)         ); titanium_         += kgs; updateAll(); return titaniumInKg(1)        ; };

			unsigned long long subQuarkGluonPlasma(unsigned long long &mgs) { mgs = min(mgs, quarkGluonPlasmaInMg(0)                          ); quarkGluonPlasma_ -= mgs; updateAll(); return quarkGluonPlasmaInMg(1); };
			unsigned long long subUlrei           (unsigned long long &cnt) { cnt = min(cnt, ulreiCount(0)                                    ); ulrea_            -= cnt; updateAll(); return ulreiCount(1)          ; };
			unsigned long long subHeavyWater      (unsigned long long &kgs) { kgs = min(kgs, heavyWaterInKg(0)                                ); heavyWater_       -= kgs; updateAll(); return heavyWaterInKg(1)      ; };
			unsigned long long subDeuterium       (unsigned long long &kgs) { kgs = min(kgs, deuteriumInKg(0)                                 ); deuterium_        -= kgs; updateAll(); return deuteriumInKg(1)       ; };
			unsigned long long subZirconiumCrystal(unsigned long long &kgs) { kgs = min(kgs, zirconiumCrystalInKg(0)                          ); zirconiumCrystal_ -= kgs; updateAll(); return zirconiumCrystalInKg(1); };
			unsigned long long subEnergy          (unsigned long long &tjs) { tjs = min(tjs, energyInTJ(0)                                    ); energy_           -= tjs; updateAll(); return energyInTJ(1)          ; };
			unsigned long long subIlmenite        (unsigned long long &kgs) { kgs = min(kgs, ilmeniteInKg(0)                                  ); ilmenite_         -= kgs; updateAll(); return ilmeniteInKg(1)        ; };
			unsigned long long subTitanium        (unsigned long long &kgs) { kgs = min(kgs, titaniumInKg(0)                                  ); titanium_         -= kgs; updateAll(); return titaniumInKg(1)        ; };

			         void      addAllResources(unsigned long long   QGP,
						                       unsigned long long   ulr,
											   unsigned long long   HeW,
											   unsigned long long   deu,
											   unsigned long long   ZrC,
											   unsigned long long   eng,
											   unsigned long long   ilm,
											   unsigned long long   tit);
					 void      subAllResources(unsigned long long & QGP,
						                       unsigned long long & ulr,
											   unsigned long long & HeW,
											   unsigned long long & deu,
											   unsigned long long & ZrC,
											   unsigned long long & eng,
											   unsigned long long & ilm,
											   unsigned long long & tit);

			unsigned long long addTitaniumDirectlyToTheShell(unsigned long long & kgs);

			unsigned long long heavyWaterSize      (bool readOnly) { return ullUpRoundDiv(heavyWaterInKg(readOnly)      , HEAVY_WATER_DENSITY      ); };
			unsigned long long deuteriumSize       (bool readOnly) { return ullUpRoundDiv(deuteriumInKg(readOnly)       , DEUTERIUM_DENSITY        ); };
			unsigned long long zirconiumCrystalSize(bool readOnly) { return ullUpRoundDiv(zirconiumCrystalInKg(readOnly), ZIRCONIUM_CRYSTAL_DENSITY); };
			unsigned long long ilmeniteSize        (bool readOnly) { return ullUpRoundDiv(ilmeniteInKg(readOnly)        , ILMENITE_DENSITY         ); };
			unsigned long long titaniumSize        (bool readOnly) { return ullUpRoundDiv(titaniumInKg(readOnly)        , TITANIUM_DENSITY         ); };

			unsigned long long containeredResourcesInKg(bool softUpdate) { if (softUpdate) return actualHeW() + actualDeu() + actualZrC() + actualIlm() + actualTit(); containeredResourcesUpdate(); return ullUpRound(heavyWater_ + deuterium_ + zirconiumCrystal_ + ilmenite_ + titanium_); };

			         void      thisFortressHasBeenAnnihilated (fortressClass     * enemy );
					 void      weaponsTargetHasBeenAnnihilated(fortressClass     * enemy );
					 void      enemyWeaponsLockedOnWarning    (fortressClass     * enemy );
					 void      enemyWeaponsUnlocked           (fortressClass     * enemy );
					 void      ourWeaponsLockedOnEnemy        (fortressClass     * enemy );
					 void      ourWeaponsUnlocked             (fortressClass     * enemy );
					 void      sendAttackReport               (attackReportClass * report);

					 void      aimNewTarget(dtIdentifier newTargetID, bool suppressEnergyPhase)                                                                                                                                                           ;
					 void      aimNewTarget(fortressClass * newTarget, bool suppressEnergyPhase) { if (newTarget) this->aimNewTarget(newTarget->getID(), suppressEnergyPhase); else this->aimNewTarget((dtIdentifier)NOT_VALID_ID, suppressEnergyPhase); };
					 void      lockWeaponsOnNewTarget(dtIdentifier newTargetID)                  { this->aimNewTarget(newTargetID, 0);                                                                                                                   };
					 void      unlockWeapons()                                                   { this->aimNewTarget((dtIdentifier)NOT_VALID_ID, 0);                                                                                                    };
					 void      targetAnnihilated()                                                                                                                                                                                                        ;
					 void      targetOutOfRange(bool suppressEnergyPhase)                                                                                                                                                                                 ;
			fortressClass *    getWeaponsTarget()                                                { return actx->cacheFortressesList.getItem<fortressClass>(targetOfWeapons_);                                                                            };
	        dtIdentifier       getWeaponsTargetID() const                                        { return targetOfWeapons_;                                                                                                                              };
	        dv_time::datetime  getLastTargetsAimTime() const                                     { return lastTargetAimTime_;                                                                                                                            };
			         void      chargeWeaponsAndFireIfItIsToBe(unsigned long long moreEnergy, unsigned long long seconds);
			unsigned long long getTotalWeaponsEnergyDiffToTheFire();

			double             actualStructuralIntegrityGradient()                 { return this->structuralIntegrityVoidSection.getGradient();                                                                                                        };
			unsigned long long actualStructuralIntegrity()                         { return structuralIntegrity_ + (unsigned long long)(actualStructuralIntegrityGradient() * dv_time::secondsBetween(this->energyUpdate_, wt2gt(dv_time::now()), 1)); };
            unsigned long long totalStructuralIntegrity()                          { return totalStructuralIntegrity_;                                                                                                                                 };
			         void      repairStructualIntegrity(unsigned long long points) { this->structuralIntegrity_ += points;                                                                                                                             };
			unsigned long long missingStructuralIntegrity()                        { return this->totalStructuralIntegrity_ - this->structuralIntegrity_;                                                                                              };
//			         void      setStructuralIntegrity(unsigned long long newStructuralIntegrity) { structuralIntegrity_ = newStructuralIntegrity; };			

			unsigned long      getBioNodesCount() { return this->mainframeSystem.mainframe()->actualBioNodes(); };

	virtual unsigned long      getManoeuvrability()           = 0; // TODO manevrovatelnost velkych lodi by mohla byt signitikantne mensi

	        unsigned long long getWeight() { return weight_;                    };
			double             getLength() { return length_;                    };
	        double             getWidth()  { return width_;                     };
			double             getHeight() { return height_;                    };
			double             getSize()   { return length_ * width_ * height_; };

	virtual unsigned long long loadingWeightLimit()                                                            = 0;
	virtual unsigned long long loadingCapacityLimit()                                                          = 0;
	virtual unsigned long long actualTotalCargoWeight(bool doNotUpdate, bool ignoreResources, bool softUpdate) = 0;
	virtual unsigned long long actualSizeOfCargoInWarehouse()                                                  = 0;
	virtual unsigned long long freeWeight(bool doNotUpdate, bool ignoreResources, bool softUpdate)             = 0;
	virtual unsigned long long freeCapacity()                                                                  = 0;
	        unsigned long long fortressTotalCargoWeight(bool doNotUpdate, bool softUpdate)       { return this->actualTotalCargoWeight(doNotUpdate, 0, softUpdate);                    };
			unsigned long long fortressSizeOfCargoInWarehouse()                                  { return this->actualSizeOfCargoInWarehouse();                                        };
			unsigned long long fortressTotalWeightWithPayload(bool doNotUpdate, bool softUpdate) { return this->getWeight() + this->fortressTotalCargoWeight(doNotUpdate, softUpdate); };

	        unsigned long long getBuildingAndroidsCountForHangar(dtIdentifier hangarID);	
			         
                     bool      isSomethingQuarrying();
			double             getQGPQuarrying()            { return this->quarkGluonPlasmaQuarryingSpeed();         };
			double             getHeWQuarrying()            { return this->heavyWaterQuarryingSpeed();               };
			double             getZrCQuarrying()            { return this->zirconiumCrystalQuarryingSpeed();         };
			double             getIlmQuarrying()            { return this->ilmeniteQuarryingSpeed();                 };
					 bool      isPossibleToQuarryQGP()      { return isPossibleToQuarryQuarkGluonPlasma(NULL);       };
					 bool      isPossibleToQuarryHeW()      { return isPossibleToQuarryHeavyWater(NULL);             };
					 bool      isPossibleToQuarryZrC()      { return isPossibleToQuarryZirconiumCrystal(NULL);       };
					 bool      isPossibleToQuarryIlm()      { return isPossibleToQuarryIlmenite(NULL);               };
			double             startQuarryQuarkGluonPlasma();
			double             startQuarryHeavyWater();
			double             startQuarryZirconiumCrystal();
			double             startQuarryIlmenite();
			         void      stopQuarryQuarkGluonPlasma();
					 void      stopQuarryHeavyWater();
					 void      stopQuarryZirconiumCrystal();
					 void      stopQuarryIlmenite();
					 void      stopAllQuarrying();
                     void      stopAllQuarryingIfQuarryingSomething();

			mountingResult     mountStoragedItem(dtIdentifierList::iterator warehouseItem, unsigned long long workingCount);
			mountingResult     mountStoragedItem(dtIdentifierList::iterator warehouseItem);
	virtual mountingResult     unmountQuarkGluonCore()     = 0;
	virtual mountingResult     unmountNavigationComputer() = 0;
	virtual mountingResult     unmountSubspaceBeacon()     = 0;
	virtual mountingResult     unmountInertialDampers()    = 0;
	virtual mountingResult     unmountImpulsJetEngine()    = 0;
	virtual mountingResult     unmountMechanicalDampers()  = 0;
			mountingResult     unmountDeflectorShieldsGenerator();
			mountingResult     unmountWeaponEnergyCircuit();
			mountingResult     unmountDroneMissiles(unsigned long long & working, unsigned long long & damaged);
			mountingResult     unmountDroneMissileLauncher(dtIdentifier DMLID);
			mountingResult     unmountLaserGun(dtIdentifier LGID);
			mountingResult     unmountTransportBeamGenerator();
			mountingResult     unmountMagneticalCollectorsOfPlasma(unsigned long long & working, unsigned long long & damaged);
			mountingResult     unmountSubmersibleFiltrationTanks(unsigned long long & working, unsigned long long & damaged);
			mountingResult     unmountSubmarineMiningMachines(unsigned long long & working, unsigned long long & damaged);
			mountingResult     unmountUndergroundDrillingMachines(unsigned long long & working, unsigned long long & damaged);
			mountingResult     unmountProbe(dtIdentifier PID);
			mountingResult     unmountHighResolutionSensors();
			mountingResult     unmountLongRangeSensors();
			mountingResult     unmountCloakingDevice();
			mountingResult     unmountAndroids(unsigned long long & working, unsigned long long & damaged);
			mountingResult     unmountPlasmaFilter();
			mountingResult     unmountScientificLab();
			mountingResult     unmountLifeSupport();
			mountingResult     unmountSubspaceTransmitter();
	virtual mountingResult     unmountHangar(dtIdentifier HID)                                                         = 0;
	virtual mountingResult     unmountMagneticalFilters(unsigned long long & working, unsigned long long & damaged)    = 0;
	virtual mountingResult     unmountDeuteriumDecomposers(unsigned long long & working, unsigned long long & damaged) = 0;
	virtual mountingResult     unmountZirconiumReactors(unsigned long long & working, unsigned long long & damaged)    = 0;
	virtual mountingResult     unmountIlmeniteFurnaces(unsigned long long & working, unsigned long long & damaged)     = 0;

	static  tradingResult      commitTrade(fortressClass * firstFortress, tradeBundleClass * firstOffer, fortressClass * secondFortress, tradeBundleClass * secondOffer);
	        tradingResult      throwSomeStuffIntoTheSpace(tradeBundleClass * someStuff);

			unsigned long long quarkGluonPlasmaLimitInMiligrams();
			unsigned long long commonRawMaterialCapacityLimit();
			unsigned long long energyLimitInTeraJoules();

			unsigned long long heavyWaterCapacity(bool doNotUpdate, bool softUpdate);
			unsigned long long deuteriumCapacity(bool doNotUpdate, bool softUpdate);
			unsigned long long zirconiumCrystalsCapacity(bool doNotUpdate, bool softUpdate);
			unsigned long long ilmeniteCapacity(bool doNotUpdate, bool softUpdate);
			unsigned long long titaniumCapacity(bool doNotUpdate, bool softUpdate);
			unsigned long long commonRawMaterialCapacity(bool doNotUpdate, bool softUpdate);
			unsigned long long freeTransportContainersCapacity(bool doNotUpdate, bool softUpdate);

			unsigned long long freeSpaceForQuarkGluonPlasmaInMiligrams(bool doNotUpdate, bool softUpdate);
			unsigned long long freeSpaceForHeavyWaterInKilograms(bool doNotUpdate, bool ignoreWeightOverload, bool softUpdate);
			unsigned long long freeSpaceForDeuteriumInKilograms(bool doNotUpdate, bool ignoreWeightOverload, bool softUpdate);
			unsigned long long freeSpaceForZirconiumCrystalsInKilograms(bool doNotUpdate, bool ignoreWeightOverload, bool softUpdate);
			unsigned long long freeSpaceForIlmeniteInKilograms(bool doNotUpdate, bool ignoreWeightOverload, bool softUpdate);
			unsigned long long freeSpaceForTitaniumInKilograms(bool doNotUpdate, bool ignoreWeightOverload, bool softUpdate);
			unsigned long long freeSpaceForEnergyInTeraJoules(bool doNotUpdate, bool softUpdate);

			         void      addAttackerThatLockedOnThis(dtIdentifier attackerID);
					 void      subAttackerThatLockedOnThis(dtIdentifier attackerID);
					 void      unlockOutAllAttackersDueToAnnihilation();

					 void      startReadingForClient() { startReadOnlyRequest(); };
					 void      stopReadingForClient()  { stopReadOnlyRequest() ; };

	virtual          void      MovementUpdateShipMovementStatus() = 0;

			/*
			unsigned long      transferStorageItemToAnotherFortress             (fortressClass * targetFortress, dtIdentifier itemID, unsigned long working, unsigned long damaged);			
			unsigned long      transferEmptyMagneticalGridsToAnotherFortress    (fortressClass * targetFortress, unsigned long working, unsigned long damaged);
			unsigned long      transferEmptyEnergeticCellsToAnotherFortress     (fortressClass * targetFortress, unsigned long working, unsigned long damaged);
			unsigned long      transferEmptyTransportContainersToAnotherFortress(fortressClass * targetFortress, unsigned long working, unsigned long damaged);
			unsigned long      transferPackedQuarkGluonPlasmaToAnotherFortress  (fortressClass * targetFortress, unsigned long      grids     );
			unsigned long      transferPackedHeavyWaterToAnotherFortress        (fortressClass * targetFortress, unsigned long      containers);
			unsigned long      transferPackedDeuteriumToAnotherFortress         (fortressClass * targetFortress, unsigned long      containers);
			unsigned long      transferPackedZirconiumCrystalsToAnotherFortress (fortressClass * targetFortress, unsigned long      containers);
			unsigned long      transferPackedEnergyToAnotherFortress            (fortressClass * targetFortress, unsigned long      cells     );
			unsigned long      transferPackedIlmeniteToAnotherFortress          (fortressClass * targetFortress, unsigned long      containers);
			unsigned long      transferPackedTitaniumToAnotherFortress          (fortressClass * targetFortress, unsigned long      containers);
			unsigned long long transferQuarkGluonPlasmaToAnotherFortress        (fortressClass * targetFortress, unsigned long long miligrams );
			unsigned long long transferUlreaToAnotherFortress                   (fortressClass * targetFortress, unsigned long long count     );
			unsigned long long transferHeavyWaterToAnotherFortress              (fortressClass * targetFortress, unsigned long long kilograms );
			unsigned long long transferDeuteriumToAnotherFotress                (fortressClass * targetFortress, unsigned long long kilograms );
			unsigned long long transferZirconiumCrystalsToAnotherFortress       (fortressClass * targetFortress, unsigned long long kilograms );
			unsigned long long transferEnergyToAnotherFortress                  (fortressClass * targetFortress, unsigned long long terajoules);
			unsigned long long transferIlmeniteToAnotherFortress                (fortressClass * targetFortress, unsigned long long kilograms );
			unsigned long long transferTitaniumToAnotherFortress                (fortressClass * targetFortress, unsigned long long kilograms );

			unsigned long      throwStorageItemToTheSpace        (dtIdentifier itemID, unsigned long working, unsigned long damaged);
			unsigned long      throwMagneticalGridsToTheSpace    (                     unsigned long working, unsigned long damaged);
			unsigned long      throwEnergeticCellsToTheSpace     (                     unsigned long working, unsigned long damaged);
			unsigned long      throwTransportContainersToTheSpace(                     unsigned long working, unsigned long damaged);			

			unsigned long long throwQuarkGluonPlasmaToTheSpace (unsigned long long miligrams );
			unsigned long long throwUlreaToTheSpace            (unsigned long long count     );
			unsigned long long throwHeavyWaterToTheSpace       (unsigned long long kilograms );
			unsigned long long throwDeuteriumToTheSpace        (unsigned long long kilograms );
			unsigned long long throwZirconiumCrystalsToTheSpace(unsigned long long kilograms );
			unsigned long long throwEnergyToTheSpace           (unsigned long long terajoules);
			unsigned long long throwIlmeniteToTheSpace         (unsigned long long kilograms );
			unsigned long long throwTitaniumToTheSpace         (unsigned long long kilograms );
			*/

    virtual void               UpdateEvents          (                                  ); 

	virtual void               DB_Load       (  unsigned long ID                );
	virtual void               DB_Save       (  unsigned long ID                );
	virtual void               DB_Insert     (  unsigned long ID                );

	unsigned long long         LRSensorsRange(void); /* km */
	unsigned long long         HRSensorsRange(void); /* km */

    virtual dist_t             getDistanceFromSpaceObject(dtIdentifier spaceObjectID) = 0;
    virtual bool               getActualPosition(vector_dist_t& result) = 0;

    static void                getFortressesByPosition(const vector_dist_t position, const dist_t radius,
                                    list<dtIdentifier>& ships, list<dtIdentifier>& bases);
    static bool                getFortressesByPositionAndSpaceObject(const vector_dist_t position, const dtIdentifier spObjectIndex,
                                    const dist_t radius, list<dtIdentifier>& ships, list<dtIdentifier>& bases, const bool add = false);
    static bool                getFortressesByPositionEx(const vector_dist_t position, const dist_t radius,
                                    list<dtIdentifier>& ships, list<dtIdentifier>& bases);

    static bool                distanceBetweenTwoFortresses(fortressClass* a, fortressClass* b, dist_t& result);
    static bool                distanceBetweenTwoFortresses(dtIdentifier a, dtIdentifier b, dist_t& result);

	const dtIdentifierSet & getAttackersThatLockedOnThis() const { return attackersThatLockedOnThis_; }

    virtual void               beforeDelete() = 0;

	virtual                   ~fortressClass() {};
};

// ################################

enum shipMoveAction
{
    SMA_SPACE_STOP,
    SMA_SPACE_NOTHING,
    SMA_SPACE_ACCELERATE,

    SMA_SPACE_OBJECT_STOP,
    SMA_SPACE_OBJECT_NOTHING,
    SMA_SPACE_OBJECT_ACCELERATE,
    SMA_SPACE_OBJECT_ORBIT
};

// ################################

enum shipMoveTarget
{
    SMT_MOVE_TO_SPACE_OBJECT,
    SMT_MOVE_TO_POSITION,
    SMT_ORBIT,
    SMT_NONE,
    SMT_MOVE_TO_SHIP,
    SMT_STOP
};

// ################################

enum shipMovementState
{
    SMS_REGULAR   = 1,
    SMS_STOPPED   = 2,
    SMS_WARP      = 4,
    SMS_ORBITING  = 8
};

// ################################

#define MINIMAL_SPEED  10

#define MOVEMENT_TIME_LIMIT_FACTOR    10
#define MOVEMENT_POS_LIMIT          1000

class shipClass : public fortressClass
{
public:
	subspaceDriveClass subspaceDrive;
	impulsDriveClass   impulsDrive;
private:
	void               subspaceDriveDamage   (bool & annihilated             );
	void               impulsDriveDamage     (unsigned short damagedShardPerc);	

	void               shipsAndBasesDamage   (unsigned short damagePerc, unsigned short actualStructuralIntegrityPerc, bool & annihilated);

	bool               mountQuarkGluonPlasmaCore(dtIdentifier newQGPC);
	bool               mountNavigationComputer(dtIdentifier newNC);
	bool               mountSubspaceBeacon(dtIdentifier newSB);
	bool               mountInertialDampers(dtIdentifier newID);
	bool               mountImpulsJetEngine(dtIdentifier newIJE);
	bool               mountMechanicalDampers(dtIdentifier newMD);

	bool               mountHangar(dtIdentifier newH)                                                         { return 0; };
	bool               mountMagneticalFilter(magneticalFilterClass * pattern, unsigned long long count)       { return 0; };
	bool               mountDeuteriumDecomposer(deuteriumDecomposerClass * pattern, unsigned long long count) { return 0; };
	bool               mountZirconiumReactor(zirconiumReactorClass * pattern, unsigned long long count)       { return 0; };
	bool               mountIlmeniteFurnace(ilmeniteFurnaceClass * pattern, unsigned long long ocunt)         { return 0; };

	mountingResult     unmountQuarkGluonCore();
	mountingResult     unmountNavigationComputer();
	mountingResult     unmountSubspaceBeacon();
	mountingResult     unmountInertialDampers();
	mountingResult     unmountImpulsJetEngine();
	mountingResult     unmountMechanicalDampers();

	mountingResult     unmountHangar(dtIdentifier HID)                                                         { return MR_BAD_FORTRESS_TYPE; };
	mountingResult     unmountMagneticalFilters(unsigned long long & working, unsigned long long & damaged)    { return MR_BAD_FORTRESS_TYPE; };
	mountingResult     unmountDeuteriumDecomposers(unsigned long long & working, unsigned long long & damaged) { return MR_BAD_FORTRESS_TYPE; };
	mountingResult     unmountZirconiumReactors(unsigned long long & working, unsigned long long & damaged)    { return MR_BAD_FORTRESS_TYPE; };
	mountingResult     unmountIlmeniteFurnaces(unsigned long long & working, unsigned long long & damaged)     { return MR_BAD_FORTRESS_TYPE; };
    
    /* polozky vztahujici se k pohybu lodi */
    vector_dist_t      position;     /* (km, km) */
    vector_dbl_t       course;       /* vector - only course */
    dist_t             speedNorm;    /* m/sec */
    dist_t             acceleration; /* m/sec */
    dist_t             gravitationSpeedNorm; /* m/sec */
    dtIdentifier       spaceObjectActuallyIn;  /* 0 - whole space */
    dtIdentifier       nearestStar;  /* nejblizsi hvezda */
    bool               wantEnterSpaceObject; /* jestlize chce vstoupit do objektu */
    shipMovementState  movementState_; /* stav pohybu lodi */
    vector_dist_t      warpTarget_; /* cil warp pohonu */
    dv_time:: datetime warpStart_; /* cas startu warp pohonu */
    dv_time:: datetime engineLimit_; /* limit enginu */

    /* polozky cile lodi */
    dtIdentifier       targetSpaceObject;
    dtIdentifier       targetShip;
    vector_dist_t      targetPosition;

    dv_time:: datetime lastActualization;

    shipMoveAction     moveAction;
    shipMoveTarget     moveTarget;

	bool          isOrbitingStar()     { spaceObject * center = getShipsAreaCenter(); return (center) && (SOT_STAR   == center->getType()); };
	bool          isOrbitingPlanet()   { spaceObject * center = getShipsAreaCenter(); return (center) && (SOT_PLANET == center->getType()); };

    unsigned long long shipMovementTriggerIdentificator_;

    bool          isMovementUpdatedTEMP_;
protected:
	unsigned long impulsJetEngineConsumption() { return this->impulsDrive.actualConsumption(); };

	bool isPossibleToQuarryQuarkGluonPlasma(spaceRegularObject ** quarryingPlatform);
	bool isPossibleToQuarryHeavyWater      (spaceRegularObject ** quarryingPlatform);
	bool isPossibleToQuarryZirconiumCrystal(spaceRegularObject ** quarryingPlatform);
	bool isPossibleToQuarryIlmenite        (spaceRegularObject ** quarryingPlatform);

	double             energyProductionByConsumption   (double             consumption) { return 0; };
	unsigned long long deuteriumProductionByConsumption(unsigned long long consumption) { return 0; };
	unsigned long long titaniumProductionByConsumption (unsigned long long consumption) { return 0; };

    double energyFabricationWeightLoss   (double             consumption) { return 0; };
	double energyFabricationSpaceLoss    (double             consumption) { return 0; };
	double deuteriumFabriactionWeightLoss(unsigned long long consumption) { return 0; };
	double deuteriumFabricationSpaceLoss (unsigned long long consumption) { return 0; };
	double titaniumFabricationWeightLoss (unsigned long long consumption) { return 0; };
	double titaniumFabricationSpaceLoss  (unsigned long long consumption) { return 0; };

//	double zirconiumCrystalConsumptionByDiff(double diff) { return 0; };
	double deuteriumConsumptionByDiff       (double diff) { return 0; };
	double ilmeniteConsumptionByDiff        (double diff) { return 0; };

	double ulreaFilteringPotential(bool isInWarp) { return this->otherEquipment.plasmaFilter()->actualTotalFilteringSpeed(this->getFortressRealmID(), isInWarp); };

	double quarkGluonPlasmaConsumptionPotential() { return this->subspaceDrive.actualConsumption(); };
	double heavyWaterConsumptionPotential()       { return 0;                                       };
	double zirconiumCrystalConsumptionPotential() { return 0;                                       };
	double ilmeniteConsumptionPotential()         { return 0;                                       };

	double ulreaFilteringSpeed() { if (this->MovementIsInWarp()) return this->ulreaFilteringPotential(1); else return 0; };

	unsigned long getFortressQuarryingModifierMultiplicator() { return SHIP_QUARRYING_MODIFIER_MULTIPLICATOR; };
public:
	// konstruktor pro prave postavenou lod
	shipClass (string             fortressName,
		       unsigned long long weight,
			   unsigned long long totalStructuralIntegrity,
			   double             length,
			   double             width,
			   double             height,
			   dtIdentifier       fortressClassID) :
			   fortressClass(fortressName, weight, totalStructuralIntegrity, length, width, height, fortressClassID)
	           {
                   lastActualization                    = wt2gt(dv_time:: now());
                   course                               = vector_dbl_t(1.0, 0.0);
                   shipMovementTriggerIdentificator_    = 0;
				   this->mechanics.initRepairingVector(this); // tohle se nesmi inicializovat v konstruktoru pevnosti, protoze to potrebuje kusy bazi a lodi
                   isMovementUpdatedTEMP_                    = 0;
	           };
    
    // konstruktor pro databazi
	shipClass(void) { isMovementUpdatedTEMP_ = 0; gravitationSpeedNorm = 0; suppressWeaponsLockOnWarningTEMP_ = 0; clientUpdateTEMP_ = 0; currentAttackerTEMP_ = NULL; };

	fortressesTypes    getFortressType()            { return FT_SHIP; };
	         bool      isConstructed(bool readOnly) { return 1;       };
			 bool      isShell(bool readOnly)       { return 0;       };

			 bool      isThereSomeAblePlanetToBuildAShell(spacePlanetObject ** buildingPlanet);

	         void      initRepairableSpecificSectionsVector(fortressSectionPVector & sectionVector) { sectionVector.push_back(&(this->subspaceDrive)); sectionVector.push_back(&(this->impulsDrive)); };

	unsigned long      getManoeuvrability();
	unsigned long      getManoeuvrabilityFromMainframe();
	double             getManoeuvrabilityBonusFromPilots();
	double             getManoeuvrabilityBonusFromEngine();

	unsigned long long loadingWeightLimit();
	unsigned long long loadingCapacityLimit();
	unsigned long long actualTotalCargoWeight(bool doNotUpdate, bool ignoreResources, bool softUpdate);
	unsigned long long actualSizeOfCargoInWarehouse();
	unsigned long long freeWeight(bool doNotUpdate, bool ignoreResources, bool softUpdate);
	unsigned long long freeCapacity();

	bool               switchToWarp();
	void               jumpOutOfWarp(bool doNotUpdate);
	void               fallOutOfWarpDueToQuarkGluonPlasmaLack();

	bool               fullIgniteImpulsJetEngine();
	bool               partitialIgniteImpulsJetEngine(unsigned long long force);
	void               fireOutImpulsJetEngine(bool doNotUpdate);
	bool               hangShipToOrbit(unsigned long long actualSpeed, unsigned long long targetSpeed);
	bool               turnShip(unsigned long long speed, unsigned short angle);
	unsigned long long slowShip(unsigned long long actualSpeed, unsigned long long targetSpeed);
	unsigned long long slowShip(unsigned long long actualSpeed, unsigned long long targetSpeed, unsigned long long seconds);
	void               switchOffImpulsDueToDeuteriumLack();

	spaceObject      * getShipsAreaCenter() { return actx->cacheSpaceObjectList.getItem<spaceObject>(spaceObjectActuallyIn); };
	baseClass        * getShipsDockingBase(); 

    /* funkce k pohybu lodi */
    void               MovementFreeSpaceUpdateShipPosition(void);
    void               MovementFreeSpaceCheckRefreshEvents(void);
    bool               MovementFreeSpaceChangeCourse(const vector_dbl_t& vect, bool updatePos = true);
    void               MovementFreeSpaceDoMobilityEvent(void);
    bool               MovementFreeSpaceMustEnterStarSystem(const vector_dist_t& pos, const dist_t speed);
    void               MovementFreeSpaceEnterIntoSolarSystem(dtIdentifier starSystemId);
    void               MovementFreeSpaceUpdateTarget(void);
    void               MovementFreeSpaceUpdateAction(void);
    vector_dist_t      MovementFreeSpaceMovementGetShipPositionAfterTime(const dv_time:: datetime delta);

    void               MovementSetEngineIgnitionLimit(const dv_time:: datetime delta);

    void               MovementSpaceObjectUpdateShipPosition(void);
    bool               MovementSpaceObjectChangeCourse(const vector_dbl_t& vect, bool updatePos = true);
    void               MovementSpaceObjectDoMobilityEvent(void);
    void               MovementSpaceObjectCheckRefreshEvents(void);
    void               MovementSpaceObjectUpdateTarget(void);
    void               MovementSpaceObjectActionStopAccelerating(void);
    void               MovementSpaceObjectActionMoveTo(const vector_dist_t pos);
    void               MovementSpaceObjectActionAccelerate(void);
    void               MovementSpaceObjectActionOrbit(void);
    void               MovementSpaceObjectActionStop(void);
    dist_t             MovementSpaceObjectGetGravitationCircleRadius(dist_t speed);
    void               MovementSpaceObjectUpdateAction(void);
    vector_dist_t      MovementSpaceObjectMovementGetShipPositionAfterTime(const dv_time:: datetime delta);
    bool               MovementSpaceObjectMustEnterOtherObject(const vector_dist_t& pos, 
        const dist_t speed, dtIdentifier& spaceObjectID);
    void               MovementSpaceObjectEnterIntoOtherObject(dtIdentifier spaceObjectID);
    bool               MovementSpaceObjectBeginOrbit(void);
    void               MovementSpaceObjectEndOrbit(void);
    bool               MovementSpaceObjectIsOutsideOfGC(const vector_dist_t pos, const dist_t speed);
    

    vector_dist_t      MovementGetShipAbsolutePosition(void);
    dist_t             MovementGetDistanceFrom(const vector_dist_t& pos);
    dist_t             MovementGetDistanceFrom(dtIdentifier object);
    dist_t             MovementGetMaximalTravelDistanceFrom(const vector_dist_t& pos);
    dist_t             MovementGetMaximalTravelDistanceFrom(dtIdentifier object);
    vector_dbl_t       MovementGetCourse(void) const;
    vector_dist_t      MovementGetShipPosition(bool updatePosition = true);
    bool               MovementIsInWarp(void) const { return movementState_ == SMS_WARP; }
    bool               MovementIsOrbiting(void) const { return movementState_ == SMS_ORBITING; }
    bool               MovementIsDockedInBase(void);
    bool               MovementIsInNormalSpace(void) { return (!MovementIsDockedInBase()) && (!MovementIsInWarp()); }
    void               MovementSetNearestStar(dtIdentifier ns) { nearestStar = ns; };
    dtIdentifier       MovementGetNearestStar          (void)    {   return nearestStar;             }   
    dtIdentifier       MovementGetSpaceObjectActuallyIn(void)    {   return spaceObjectActuallyIn;   }
    bool               MovementGetOrbitingPivot(vector_dist_t& pivot);
    bool               MovementGetAngularSpeed(dist_t& angular_velocity);

    void               MovementUpdateNearestStar(void);
    bool               MovementGetTrackTime(dist_t track, dv_time:: datetime& result);
    void               MovementCheckMobilityEvent(dv_time:: datetime ev);
    void               DoMobilityEvent(void);
    bool               MovementLand(dtIdentifier base);
    bool               MovementTakeOff(void);
    void               MovementUpdateShipMovementStatus(void);

    void               MovementTargetStopShip(void);
    void               MovementTargetMoveTo(const dist_t x, const dist_t y);
    bool               MovementTargetOrbit(void);
    bool               MovementTargetPursuit(unsigned long otherShipID);
    bool               MovementTargetMoveToSpaceObject(unsigned long spaceObject);
    dist_t             MovementEstimationDistance(void) const;
    dv_time:: datetime MovementEstimationTime(const dist_t travel_distance);
    dtIdentifier       MovementGetTargetShip(void) const;
    vector_dist_t      MovementGetTargetPosition(void) const;
    dtIdentifier       MovementGetTargetSpaceObject(void) const;

    bool               MovementTurnEnginesForChangeCourse(double angleRatio); /* 1.0 = 180 stupnu, 0.0 = 0 stupnu */
    bool               MovementTurnEnginesForDecreaseSpeed(dist_t speed);
    dist_t             MovementTurnOnEngine(void); /* zapne motory a vrati akceleraci */
    bool               MovementTurnOnEngineForGravityAnnulating(dist_t g);
    void               MovementTurnOffEngine(void);
    bool               MovementTurnOnWarpEngine(void);
    void               MovementTurnOffWarpEngine(void);
    void               MovementCrashShip(dtIdentifier spaceObjectID) { annihilate(); };
    shipMovementState  MovementGetMovementState(void) const       { return movementState_;            };
    shipMoveTarget     MovementGetMovementTarget(void) const      { return moveTarget;                };
    dist_t             MovementGetCurrentSpeed(void) const        { return speedNorm;                 };
    dist_t             MovementGetCurrentAcceleration(void) const { return acceleration;              };
    vector_dist_t      MovementGetWarpTarget(void) const          { return warpTarget_;               };
    dist_t             MovementGetWarpSpeed(void); /* m/sec */
    void               MovementNotifyOtherPlayers(void);
    vector_dist_t      MovementEstimateWarpPosition(void);

    bool               MovementWarpTravel(const vector_dist_t targetPos);
    void               MovementAfterWarpEmergencyShutdown(void);

    virtual void       UpdateEvents          (                                  ) ; 

	virtual void               DB_Load       (  unsigned long ID                ) sealed;
	virtual void               DB_Save       (  unsigned long ID                ) sealed;
	virtual void               DB_Insert     (  unsigned long ID                ) sealed;

    virtual dist_t             getDistanceFromSpaceObject(dtIdentifier spaceObjectID);
    virtual bool               getActualPosition(vector_dist_t& result);

    virtual void               beforeDelete();

	virtual           ~shipClass() {};
};

// ################################

class baseClass : public fortressClass
{
public:
	hangarsPortClass   hangarsPort;
	factoriesClass     factories;
private:
	dtIdentifier       spaceObjectId_;

	unsigned long long buildingPoints_;

	void               hangarsDamage         (unsigned short damagedShardPerc);
	void               factoriesDamage       (unsigned short damagedShardPerc);

	void               shipsAndBasesDamage   (unsigned short damagePerc, unsigned short actualStructuralIntegrityPerc, bool & annihilated);

	bool               mountQuarkGluonPlasmaCore(dtIdentifier newQGPC) { return 0; };
	bool               mountNavigationComputer(dtIdentifier newNC)     { return 0; };
	bool               mountSubspaceBeacon(dtIdentifier newSB)         { return 0; };
	bool               mountInertialDampers(dtIdentifier newID)        { return 0; };
	bool               mountImpulsJetEngine(dtIdentifier newIJE)       { return 0; };
	bool               mountMechanicalDampers(dtIdentifier newMD)      { return 0; };

	bool               mountHangar(dtIdentifier newH);
	bool               mountMagneticalFilter(magneticalFilterClass * pattern, unsigned long long count);
	bool               mountDeuteriumDecomposer(deuteriumDecomposerClass * pattern, unsigned long long count);
	bool               mountZirconiumReactor(zirconiumReactorClass * pattern, unsigned long long count);
	bool               mountIlmeniteFurnace(ilmeniteFurnaceClass * pattern, unsigned long long count);

	mountingResult     unmountQuarkGluonCore()     { return MR_BAD_FORTRESS_TYPE; };
	mountingResult     unmountNavigationComputer() { return MR_BAD_FORTRESS_TYPE; };
	mountingResult     unmountSubspaceBeacon()     { return MR_BAD_FORTRESS_TYPE; };
	mountingResult     unmountInertialDampers()    { return MR_BAD_FORTRESS_TYPE; };
	mountingResult     unmountImpulsJetEngine()    { return MR_BAD_FORTRESS_TYPE; };
	mountingResult     unmountMechanicalDampers()  { return MR_BAD_FORTRESS_TYPE; };

	mountingResult     unmountHangar(dtIdentifier HID);
	mountingResult     unmountMagneticalFilters(unsigned long long & working, unsigned long long & damaged);
	mountingResult     unmountDeuteriumDecomposers(unsigned long long & working, unsigned long long & damaged);
	mountingResult     unmountZirconiumReactors(unsigned long long & working, unsigned long long & damaged);
	mountingResult     unmountIlmeniteFurnaces(unsigned long long & working, unsigned long long & damaged);
protected:
	void          fallOutOfWarpDueToQuarkGluonPlasmaLack() {};
	void          switchOffImpulsDueToDeuteriumLack()      {};

	unsigned long impulsJetEngineConsumption() { return 0; };

	bool isPossibleToQuarryQuarkGluonPlasma(spaceRegularObject ** quarryingPlatform);
	bool isPossibleToQuarryHeavyWater      (spaceRegularObject ** quarryingPlatform);
	bool isPossibleToQuarryZirconiumCrystal(spaceRegularObject ** quarryingPlatform);
	bool isPossibleToQuarryIlmenite        (spaceRegularObject ** quarryingPlatform);

	double             energyProductionByConsumption   (double             consumption) { return this->factories.zirconiumReactor()->getProductionByConsumption   (this->getFortressRealmID(), consumption); };
	unsigned long long deuteriumProductionByConsumption(unsigned long long consumption) { return this->factories.deuteriumDecomposer()->getProductionByConsumption(this->getFortressRealmID(), consumption); };
	unsigned long long titaniumProductionByConsumption (unsigned long long consumption) { return this->factories.ilmeniteFurnace()->getProductionByConsumption    (this->getFortressRealmID(), consumption); };

	double energyFabricationWeightLoss   (double             consumption) { return (double)this->factories.zirconiumReactor()->getWeightLossByConsumption   (this->getFortressRealmID(), consumption); };
	double energyFabricationSpaceLoss    (double             consumption) { return (double)this->factories.zirconiumReactor()->getSpaceLossByConsumption    (this->getFortressRealmID(), consumption); };
	double deuteriumFabriactionWeightLoss(unsigned long long consumption) { return (double)this->factories.deuteriumDecomposer()->getWeightLossByConsumption(this->getFortressRealmID(), consumption); };
	double deuteriumFabricationSpaceLoss (unsigned long long consumption) { return (double)this->factories.deuteriumDecomposer()->getSpaceLossByConsumption (this->getFortressRealmID(), consumption); };
	double titaniumFabricationWeightLoss (unsigned long long consumption) { return (double)this->factories.ilmeniteFurnace()->getWeightLossByConsumption    (this->getFortressRealmID(), consumption); };
	double titaniumFabricationSpaceLoss  (unsigned long long consumption) { return (double)this->factories.ilmeniteFurnace()->getSpaceLossByConsumption     (this->getFortressRealmID(), consumption); };

//	double zirconiumCrystalConsumptionByDiff(double diff) { return this->factories.zirconiumReactor()->getConsumptionByConProDiff   (this->getFortressRealmID(), diff); };
	double deuteriumConsumptionByDiff       (double diff) { return this->factories.deuteriumDecomposer()->getConsumptionByConProDiff(this->getFortressRealmID(), diff); };
	double ilmeniteConsumptionByDiff        (double diff) { return this->factories.ilmeniteFurnace()->getConsumptionByConProDiff    (this->getFortressRealmID(), diff); };

	double ulreaFilteringPotential(bool isInWarp) { return this->otherEquipment.plasmaFilter()->actualTotalFilteringSpeed(this->getFortressRealmID(), isInWarp) + this->factories.magneticalFilter()->actualTotalProduction(this->getFortressRealmID()); };

	double quarkGluonPlasmaConsumptionPotential() { return (double)0;                                                                                         };
	double heavyWaterConsumptionPotential()       { return (double)this->factories.deuteriumDecomposer()->actualTotalConsumption(this->getFortressRealmID()); };
	double zirconiumCrystalConsumptionPotential() { return (double)this->factories.zirconiumReactor()->actualTotalConsumption(this->getFortressRealmID());    };
	double ilmeniteConsumptionPotential()         { return (double)this->factories.ilmeniteFurnace()->actualTotalConsumption(this->getFortressRealmID());     };

	double ulreaFilteringSpeed() { if ((0 < this->quarkGluonPlasma_) && (this->factories.avalMagneticalFilter())) return this->ulreaFilteringPotential(0); else return 0; };

	unsigned long getFortressQuarryingModifierMultiplicator() { return BASE_QUARRYING_MODIFIER_MULTIPLICATOR; };
public:
    void setSpaceObject(dtIdentifier spoId) { spaceObjectId_ = spoId; };

	// konstruktor pro prave postavenou zakladnu
	baseClass (string             fortressName,
		       unsigned long long weight,
			   unsigned long long totalStructuralIntegrity,
			   double             length,
			   double             width,
			   double             height,
			   dtIdentifier       fortressClassID,
			   bool               skipShellPhase) :
	           fortressClass(fortressName, weight, totalStructuralIntegrity, length, width, height, fortressClassID)
	           {
				   if (skipShellPhase)
				   {
					   buildingPoints_ = weight;
				   }
				   else
				   {
					   buildingPoints_ = 0;
				   }
				   this->mechanics.initRepairingVector(this); // tohle se nesmi inicializovat v konstruktoru pevnosti, protoze to potrebuje kusy bazi a lodi
	           };
    // konstruktor pro databazi
	baseClass(void) { suppressWeaponsLockOnWarningTEMP_ = 0; clientUpdateTEMP_ = 0; currentAttackerTEMP_ = NULL; };

	fortressesTypes    getFortressType()            { return FT_BASE;                            };
	         bool      isConstructed(bool readOnly)                                               ;
			 bool      isShell(bool readOnly)       { return (!(this->isConstructed(readOnly))); };

			 bool      isThereSomeAblePlanetToBuildAShell(spacePlanetObject ** buildingPlanet);

	unsigned long long maxAndroidsShellCanAccept(androidsClass * androids);
	unsigned long long maxEnergeticCellsShellCanAccept(energeticCellClass * cells);
	unsigned long long maxTitaniumShellCanAccept();
	unsigned long long maxEnergyShellCanAccept();
	         void      acceptAndroidsIntoShell(androidsClass * androids, unsigned long long working);
			 void      acceptEnergeticCellsIntoShell(energeticCellClass * cells, unsigned long long working);
			 void      acceptBundleAsShell(tradeBundleClass * bundle);

	         void      initRepairableSpecificSectionsVector(fortressSectionPVector & sectionVector) { sectionVector.push_back(&(this->hangarsPort)); sectionVector.push_back(&(this->factories)); };

	dv_time::datetime  baseConstructingPhase(dv_time::datetime updateToATime);
	unsigned short     shellDeflection(unsigned long energyPassedByShields);

	factoriesClass & getFactories() { return factories; };

    spaceFortressObject * getFortressSpaceObjectHolder(void);
    dtIdentifier          getFortressSpaceObjectHolderId(void) const;
    spacePlanetObject   * getFortressPlanet(void);

	unsigned long long actualBuildingPoints() { this->energyDistributionPhaseAndWeaponsFire(); return buildingPoints_; };
	unsigned long      getManoeuvrability()   { return 0; };

	unsigned long long loadingWeightLimit();
	unsigned long long loadingCapacityLimit();
	unsigned long long actualTotalCargoWeight(bool doNotUpdate, bool ignoreResources, bool softUpdate);
	unsigned long long actualSizeOfCargoInWarehouse();
	unsigned long long freeWeight(bool doNotUpdate, bool ignoreResources, bool softUpdate);
	unsigned long long freeCapacity();

    vector_dist_t      MovementGetBasePosition(void);

	bool               isHangarMounted(dtIdentifier hangarID);

	        void      MovementUpdateShipMovementStatus() { return; };

	virtual void               DB_Load       (  unsigned long ID                ) sealed;
	virtual void               DB_Save       (  unsigned long ID                ) sealed;
	virtual void               DB_Insert     (  unsigned long ID                ) sealed;

    virtual void               UpdateEvents  (                                  ); 
    virtual dist_t             getDistanceFromSpaceObject(dtIdentifier spaceObjectID);
    virtual bool               getActualPosition(vector_dist_t& result);

    virtual void               beforeDelete();

	virtual           ~baseClass() {};
};

// ################################
// ################################

const char* movementStateToStr(const shipMovementState sms);
const char* movementTargetToStr(const shipMoveTarget smt);

// ################################
// ################################

#endif