2012-05-29 13:31:11 +00:00
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
# ifndef NL_SRG_UTILITIES_H
# define NL_SRG_UTILITIES_H
// Misc
# include <nel/misc/types_nl.h>
# include <nel/misc/sstring.h>
# include "nel/misc/path.h"
# include "nel/misc/file.h"
# include "nel/misc/smart_ptr.h"
# include "nel/misc/command.h"
# include "nel/misc/path.h"
# include <nel/misc/diff_tool.h>
# include <nel/misc/random.h>
// Georges
# include "nel/georges/u_form.h"
# include "nel/georges/u_form_elm.h"
# include "nel/georges/u_form_dfn.h"
# include "nel/georges/u_form_loader.h"
# include "nel/georges/u_type.h"
// Georges, bypassing interface
# include "georges/stdgeorges.h"
# include "georges/form.h"
// C
# include <time.h>
# include <conio.h>
// stl
# include <set>
# include <map>
# include <hash_map>
using namespace NLMISC ;
using namespace NLGEORGES ;
using namespace std ;
typedef sint TFaberInterestLevel ;
const TFaberInterestLevel NAInterestLevel = - 1 ;
const uint32 NbNomenclaturedFaberLevel = 5 ; // excluding N/A
const char * sNomenclaturedInterestLevels [ NbNomenclaturedFaberLevel + 1 ] = { " N/A " , " Worst " , " Bad " , " Average " , " Good " , " Best " } ; // from -1 to 5
CRandom RandomGenerator ;
typedef CVectorSString vs ;
typedef map < uint32 , vector < uint32 > > CRulesFilter ;
typedef map < CSString , vector < uint32 > , CUnsensitiveSStringLessPred > CRulesStrFilter ;
typedef map < CSString , vs , CUnsensitiveSStringLessPred > CRulesStr2Filter ;
typedef map < CSString , CSString , CUnsensitiveSStringLessPred > mss ;
typedef vector < uint32 > vu ;
typedef hash_map < string , string , hash < string > > CTitles ; // code -> utf8 title
// Write sheet files, or display to screen only
bool WriteSheetsToDisk = true ;
// Overriden by command-line argument after -n
string ExtractNamesCsv ;
const uint32 NbFaberElements = 26 ;
const uint32 RM_INDEX_FAMILY_CODE = 1 ;
const uint32 NB_FAMILY_CODE_CHARS = 4 ;
const uint32 RM_INDEX_CREATURE_CODE = 5 ;
const uint32 NB_CREATURE_CODE_CHARS = 5 ;
const uint32 RM_INDEX_ECOSYSTEM_CODE = 8 ;
const uint32 NB_ECOSYSTEM_CODE_CHARS = 1 ;
const uint32 RM_INDEX_LEVELZONE_CODE = 9 ;
const uint32 SIZE_RAW_MATERIAL_SHEET_FILENAME = 18 ;
/*const uint32 RM_INDEX_INTEREST_LEVEL = 6;
const uint32 NB_INTEREST_LEVEL_CHARS = 2 ;
const uint32 RM_INDEX_FABERELEMS_CODE = 8 ;
const uint32 NB_FABERELEMS_CODE_CHARS = 6 ; */
const uint32 CR_INDEX_ECOSYSTEM_CODE = 3 ; // in creature code
const uint32 CR_INDEX_LEVELZONE_CODE = 4 ;
const uint32 CR_INDEX_LOCAL_LEVEL_CODE = 5 ;
//const uint32 NB_UNIQUE_LEVELS_PER_ZONE = 4; // not counting the bosses, the fifth equals the first one of next
const uint32 NB_UNIQUE_LEVELZONES_PER_CONTINENT = 5 ;
const uint32 MAX_NB_LOCAL_LEVELS = 8 ;
//const uint32 NB_ZONE_LEVELS = 5; // TEMP for forest ecosystem
//const uint32 NbFaberInterestLevels = (NB_ZONE_LEVELS * NB_UNIQUE_LEVELS_PER_ZONE) + 1; // excluding N/A
string inputSheetPath ;
bool inputSheetPathLoaded = false ;
map < string , string > inputSheetPathContent ; // short filename without ext, full filename with path
string TranslationPath ;
string SystemMPPath ;
// These vectors have the same indices : by family
vs families ;
vs familyCodes , ecosystemCodes , propertyCodes , creatureCodes ;
sint MaxFamilyNum = - 1 ;
enum TColor { Red , Beige , Green , Turquoise , Blue , Violet , White , Black , NbColors , InvalidColor = NbColors } ;
// By ecosystem, color, property, rm group, creature, season
vs ecosystems , colors , properties , groups , creatures , seasons ;
mss adjectives ;
// DtName must be the 1st one
enum TDataCol { DtName , DtTitle , DtRMFamily , DtGroup , DtEcosystem , DtLevelZone , DtStatQuality , DtProp , DtCreature , DtCreaTitle , DtCraftSlotName , DtCraftCivSpec , DtColor , DtAverageEnergy , DtMaxLevel , DtJewelProtectionType , DtCustomizedProperties , DtNbCols } ;
const char * DataColStr [ DtNbCols ] = { " Code " , " Name " , " Family " , " Group " , " Ecosystem " , " LevelZone " , " Stat Quality " , " Properties " , " Creature sheets " , " Creatures " , " Item parts " , " Craft civ spec " , " Color " , " Average energy " , " Max level " , " Jewel protection type " , " Customized " } ;
const uint32 NbPropertyDepths = 5 ;
const char * PropertyDepths [ NbPropertyDepths ] = { " Unknown " , " Slightly " , " Moderately " , " Quite " , " Extremely " } ;
typedef uint32 TGroup ; // index in groups, and value in groups .typ
//enum TLocation { Under, Over, Flora, Creatures, NB_LOCATIONS, NB_DEPOSITS=Flora+1 };
enum TLocation { InDeposits , InCreatures , NB_LOCATIONS } ;
vu DepositFamilyIndices ;
enum TCiv { Fyros , Matis , Tryker , Zorai , AllCiv , NbCiv } ;
const char * CivNames [ NbCiv ] = { " Fyros " , " Matis " , " Tryker " , " Zorai " , " All " } ;
const char * CivEcosystemCodes [ NbCiv ] = { " D " , " F " , " L " , " J " , " X " } ;
enum TEcosystem { CommonEcosystem , Desert , Forest , Lacustre , Jungle , PrimeRoots , NbEcosystems , Goo = NbEcosystems , Invasion , Raid , Event , N , S , T , U , V , W , X , Y , Z , NbEcosystemsPlusExtensions } ;
TCiv EcosystemToCiv [ NbEcosystems ] = { AllCiv , Fyros , Matis , Tryker , Zorai , AllCiv } ;
enum TStatQuality { Basic , Fine , Choice , Excellent , Supreme , NbStatQualities , InvalidStatQuality = NbStatQualities } ;
char * StatQualityStr [ NbStatQualities + 1 ] = { " Basic " , " Fine " , " Choice " , " Excellent " , " Supreme " , " N/A " } ;
TStatQuality CreatureLocalLevelToStatQuality [ MAX_NB_LOCAL_LEVELS ] =
{
Basic , // 1 (index 0)
Fine , // 2
Basic , // 3
Fine , // 4
Excellent , // 5 (named creatures)
InvalidStatQuality , // 6 (mission creatures, their RMs have no craft stats)
Supreme , // 7 (bosses)
Choice // 8 (mini-bosses)
} ;
enum TIndexOfRemarkableStatIndex { RBestA , RBest = RBestA , RWorstA1 , RWorst1 = RWorstA1 , RWorstA2 , RWorst2 = RWorstA2 , RBestB , RWorstB1 , RWorstB2 , NB_REMARKABLE_STAT_INDICES } ;
struct TSkeletonInfo
{
TSkeletonInfo ( ) : IsUsed ( false ) { }
//vs CreaturesOfSke;
CSString Name ;
CSString AbbrevName ;
//CSString SkGroup;
bool IsUsed ; // true if has RM
} ;
typedef map < CSString , TSkeletonInfo , CUnsensitiveSStringLessPred > CSkeletonMap ;
// By skeleton group, by skeleton, bu creature model
CRulesStr2Filter SkgroupToModels ;
CSkeletonMap CreatureModels ;
mss CreatureToModel ;
//vs skeletonGroupColumns;
set < CSString , CUnsensitiveSStringLessPred > CreatureMainModelsWithoutRM ;
// By creature model
CRulesStrFilter RMFamilyIndicesByCreatureModel ;
vu GooCreatureFamilyIndices ;
typedef map < char , vu > CCreatureTypeToFamilyIndices ; // the key is the 2nd char of the creature code (h for herbivore, k for kitin...)
CCreatureTypeToFamilyIndices InvasionRaidCreatureFamilyIndices ;
struct TBool
{
TBool ( ) : Done ( false ) { }
bool Done ;
} ;
typedef map < uint , TBool > CDoneMap ; // indexed by levelzone
map < string , TBool > IsRMSheetGenerated ; // indexed by sheetname
string rawMaterialPath , creaturePath , creatureAssignmentPath , depositPath ;
string dirbase ;
const string oldRmSheetType = " item " ;
const string rmSheetType = " sitem " ;
const string crSheetType = " creature " ;
const string dpSheetType = " deposit " ;
//const uint32 NbPropertySlots = 10; // obsolete
uint32 UndefinedProperty = ~ 0 ;
/*
*
*/
struct CIconInfo
{
CSString IconBackground , Icon , IconOver , IconOver2 ;
} ;
map < CSString , CIconInfo , CUnsensitiveSStringLessPred > Icons ;
/*
*
*/
class CMainStat
{
public :
///
CMainStat ( ) : SumNbFaberElemsFilled ( 0 ) , MaxNbFaberElemsFilled ( 0 ) , MinNbFaberElemsFilled ( ~ 0 ) ,
NbRMByFaberElem ( NbFaberElements , 0 ) { }
/// Call it when families etc. are ready
void init ( )
{
NbRMByFaberElemByFamilyAndCiv . resize ( families . size ( ) ) ;
for ( uint32 i = 0 ; i ! = families . size ( ) ; + + i )
{
NbRMByFaberElemByFamilyAndCiv [ i ] . resize ( NbCiv ) ;
for ( uint32 c = 0 ; c ! = NbCiv ; + + c )
NbRMByFaberElemByFamilyAndCiv [ i ] [ c ] . resize ( NbFaberElements ) ;
}
for ( uint32 iEcosystem = 0 ; iEcosystem ! = ecosystems . size ( ) ; + + iEcosystem )
{
for ( uint32 iLoc = 0 ; iLoc ! = NB_LOCATIONS ; + + iLoc )
{
NbRMHavingProperty [ iLoc ] [ iEcosystem ] . resize ( properties . size ( ) ) ;
NbRMByFaberElemByEcosystem [ iEcosystem ] . resize ( NbFaberElements ) ;
}
}
}
///
bool updateCraftStatistics ( uint32 rFaberElem , uint32 iEcosystem , uint32 iFam , TCiv civ ) ;
///
void updateMainStats ( uint32 nbFaberElemsFilled )
{
SumNbFaberElemsFilled + = nbFaberElemsFilled ;
if ( nbFaberElemsFilled < MinNbFaberElemsFilled )
MinNbFaberElemsFilled = nbFaberElemsFilled ;
if ( nbFaberElemsFilled > MaxNbFaberElemsFilled )
MaxNbFaberElemsFilled = nbFaberElemsFilled ;
}
// By property and by ecosystem and location
vu NbRMHavingProperty [ NB_LOCATIONS ] [ NbEcosystems ] ;
uint32 SumNbFaberElemsFilled ;
uint32 MaxNbFaberElemsFilled ;
uint32 MinNbFaberElemsFilled ;
vector < uint32 > NbRMByFaberElem ; ;
vector < uint32 > NbRMByFaberElemByEcosystem [ NbEcosystems ] ;
vector < vector < vector < uint32 > > > NbRMByFaberElemByFamilyAndCiv ;
} ;
/*
* From georges2csv
*/
void loadSheetPath ( )
{
if ( inputSheetPathLoaded )
return ;
NLMISC : : createDebug ( ) ;
NLMISC : : WarningLog - > addNegativeFilter ( " CPath::insertFileInMap " ) ;
CPath : : addSearchPath ( inputSheetPath , true , false ) ; // for Georges to work properly
vector < string > files ;
CPath : : getPathContent ( inputSheetPath , true , false , true , files ) ;
uint32 i ;
for ( i = 0 ; i < files . size ( ) ; + + i )
{
string filename = files [ i ] ;
string filebase = CFile : : getFilenameWithoutExtension ( filename ) ;
inputSheetPathContent [ filebase ] = filename ;
}
inputSheetPathLoaded = true ;
}
/*
* Get a random value in range [ 0. . nbPossibleValues [
* Precondition : nbPossibleValues < 65536
*/
inline uint32 getRandomValue ( uint32 nbPossibleValues )
{
/*double r = (double) rand();
r / = ( double ) ( RAND_MAX + 1 ) ; // exclude the ceiling value
return ( uint32 ) ( r * nbPossibleValues ) ; */
return RandomGenerator . rand ( ( uint16 ) ( nbPossibleValues - 1 ) ) ;
}
/*
*
*/
struct CDfnFieldInfo
{
CDfnFieldInfo ( ) { }
CDfnFieldInfo ( const vector < string > & values , const vector < string > & labels ) : TypePredefinedValues ( values ) , TypePredefinedLabels ( labels ) { }
vector < string > TypePredefinedValues ;
vector < string > TypePredefinedLabels ;
} ;
/*
*
*/
struct TIconMapping
{
const char * FamilyName ;
const char * IconFilename ;
} ;
/*
*
*/
sint getNomenclaturedInterestLevel ( TFaberInterestLevel level , TFaberInterestLevel nbInterestLevels )
{
return ( level = = NAInterestLevel ) ? 0 : ( level * NbNomenclaturedFaberLevel / nbInterestLevels ) + 1 ;
}
/*
*
*/
//struct CFaberCode
//{
// char Ch[NB_FABERELEMS_CODE_CHARS];
//};
/*
*
*/
//struct CFaberCombination
//{
// CFaberCombination( TFaberInterestLevel firstLevel, const string& code ) : FirstLevel(firstLevel)
// {
// memcpy( Code.Ch, &code[0], NB_FABERELEMS_CODE_CHARS );
// }
//
// TFaberInterestLevel FirstLevel;
// CFaberCode Code;
//};
/*
*
*/
//class CSheetNameRepository
//{
//public:
//
// ///
// void resize( uint32 nbEcosystems, uint32 nbFamilies )
// {
// _Container.resize( nbEcosystems );
// for ( uint32 i=0; i!=nbEcosystems; ++i )
// {
// _Container[i].resize( nbFamilies );
// }
// }
//
// ///
// void insert( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, TFaberInterestLevel level, const string& faberCombinationCode )
// {
// // nlassert( faberCombinationCode.size() == NB_FABERELEMS_CODE_CHARS );
// _Container[iEcosystem][iFamily][iCreature].push_back( CFaberCombination( level, faberCombinationCode ) );
// }
//
// ///
// void getFaberCombinationCodes( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, vector<CFaberCombination> **codes )
// {
// map < uint32, vector< CFaberCombination > >::iterator im;
// /*nldebug( "%u %u -> %u cr (searching for %u)", iEcosystem, iFamily, _Container[iEcosystem][iFamily].size(), iCreature );
// for ( im=_Container[iEcosystem][iFamily].begin(); im!=_Container[iEcosystem][iFamily].end(); ++im )
// nldebug( "cr %u -- %u combinations", (*im).first, (*im).second.size() );*/
// im = _Container[iEcosystem][iFamily].find( iCreature );
// if ( im == _Container[iEcosystem][iFamily].end() )
// *codes = NULL;
// else
// *codes = &((im)->second);
// }
//
//private:
//
// /// Indexs: iEcosystem, iFamily, rCreatureSpecialization, rFaberCombination
// vector< vector < map < uint32, vector< CFaberCombination > > > > _Container;
//};
//void CSheetNameRepository::getFaberCombinationCodes( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, vector<CFaberCombination> **codes )
//CSheetNameRepository RawMaterialRepository;
/**
* Characteristics .
* When adding a new characteristic , ADD IT INTO " v3_source_tables.xls!Item Parts v3 " / " rm_item_parts.csv " and mark compatible item parts
*/
enum TFaberCharacteristic {
Durability , Weight , SapLoad , DMG , Speed , Range ,
DodgeModifier , ParryModifier , AdversaryDodgeModifier , AdversaryParryModifier ,
ProtectionFactor , MaxSlashProtect , MaxBluntProtect , MaxPierceProtect ,
ECTF , EPF ,
OACTF , OAPF ,
HCTP , HPF ,
DACTF , DAPF ,
JewelProtection ,
CraftCivSpec ,
NbCharacs } ;
const char * sCharacs [ NbCharacs ] = {
" Durability " , " Weight " , " SapLoad " , " DMG " , " Speed " , " Range " ,
" DodgeModifier " , " ParryModifier " , " AdversaryDodgeModifier " , " AdversaryParryModifier " ,
" ProtectionFactor " , " MaxSlashingProtection " , " MaxBluntProtection " , " MaxPiercingProtection " ,
" ElementalCastingTimeFactor " , " ElementalPowerFactor " ,
" OffensiveAfflictionCastingTimeFactor " , " OffensiveAfflictionPowerFactor " ,
" HealCastingTimeFactor " , " HealPowerFactor " ,
" DefensiveAfflictionCastingTimeFactor " , " DefensiveAfflictionPowerFactor " ,
" JewelProtectionType " ,
" CraftCivSpec " } ;
//const bool PositiveCharacs [NbCharacs] = { true, false, true, false, true, true };
//const float MinCharacValues [NbCharacs] = { 100, 0.1f, 10, 0.2f, 100, 0 };
//const float MaxCharacValues [NbCharacs] = { 500, 1.5f, 400, 2.0f, 500, 60 };
//const float PeakCharacValues [NbCharacs] = { 2000, 2.5f, 800, 5.0f, 2000, 80 };
bool PositiveCharacs [ NbCharacs ] ;
float MinCharacValues [ NbCharacs ] ;
float MaxCharacValues [ NbCharacs ] ;
float PeakCharacValues [ NbCharacs ] ;
vector < bool > CharacSlotFilter [ NbCharacs ] ; // it's a positive filter
/*
*
*/
struct TFamInfo
{
vs Properties ; // ex: propForA, propForB, propForC
CSString CompatibleCraftParts ; // ex: ABC
vu CraftPartsByProp ; // ex: 0, 1, 2 (indices in ompatibleCraftParts)
vector < TCiv > Civs ; // ex: Fyros, All, All
vu Freqs ; // ex: 1, 2, 2
TGroup Group ;
bool IsActive ; // False if not in rm_fam_prop.csv
bool IsInDeposits ;
bool IsInCreatures ;
CSString SpecialCreatureTag ;
bool GenerateOnly ;
bool IsForMission ;
sint8 RemarkableStatIndex [ NB_REMARKABLE_STAT_INDICES ] ;
sint8 ColorIndex ;
sint8 JewelProtIndex ;
static uint UseGenerateOnly ; // if 0, generate all; otherwise, generate only families that have GenerateOnly set to true
///
TFamInfo ( ) : Group ( ~ 0 ) , IsInDeposits ( false ) , IsActive ( false ) , IsInCreatures ( false ) , SpecialCreatureTag ( ) , GenerateOnly ( false ) , IsForMission ( false ) , ColorIndex ( - 1 ) , JewelProtIndex ( - 1 ) { }
///
uint getCompatibleCraftPart ( uint iCompatibleCP ) const
{
return ( uint ) ( CompatibleCraftParts [ iCompatibleCP ] - ' A ' ) ;
}
/// whichProp: index in Properties
uint getBeginCraftPartForProp ( uint whichProp ) const
{
return CraftPartsByProp [ whichProp ] ;
}
/// whichProp: index in Properties
uint getEndCraftPartForProp ( uint whichProp ) const
{
if ( whichProp = = Properties . size ( ) - 1 )
return CompatibleCraftParts . size ( ) ;
else
return CraftPartsByProp [ whichProp + 1 ] ;
}
/// whichProp: index in Properties
CSString getCraftPartForProp ( uint whichProp ) const
{
uint start = getBeginCraftPartForProp ( whichProp ) ;
return CompatibleCraftParts . substr ( start , getEndCraftPartForProp ( whichProp ) - start ) ;
}
/** With the returned index, you can get elt in Property, CraftPartsByProp, Civs and Freqs.
* Returns ~ 0 if not found .
*/
uint getPropIndexByCraftPart ( char itemPart ) const
{
for ( uint i = 0 ; i ! = CraftPartsByProp . size ( ) ; + + i )
{
char itemPartCode [ 2 ] ;
itemPartCode [ 0 ] = itemPart ;
itemPartCode [ 1 ] = ' \0 ' ;
if ( getCraftPartForProp ( i ) . find ( itemPartCode ) ! = string : : npos )
return i ;
}
return ~ 0 ;
}
///
bool existsInEcosystem ( TEcosystem iEcosystem , TStatQuality statQuality ) const ;
///
static bool mustGenerateFamily ( uint iFamily ) ;
} ;
const uint ITEM_PART_JEWEL_GEM = 17 ; // R
/*
*
*/
struct CFaberCharacteristics
{
/// Default constructor (for reading)
CFaberCharacteristics ( )
: FaberElement ( ~ 0 ) , ActualEnergy ( 0.0f ) , ActualOriginality ( 0.0f )
{
for ( uint32 i = 0 ; i ! = NbCharacs ; + + i )
Values [ i ] = 0.0f ;
}
///
void serial ( NLMISC : : IStream & s )
{
s . serial ( FaberElement ) ;
s . serial ( ActualEnergy ) ;
s . serial ( ActualOriginality ) ;
for ( uint32 c = 0 ; c ! = NbCharacs ; + + c )
s . serial ( Values [ c ] ) ;
}
///
void initFaberElement ( uint32 rFaberElement ) { FaberElement = rFaberElement ; }
/// Returns false if the RM must NOT be generated.
bool randomizeValues ( TFaberInterestLevel interestLevel , TFaberInterestLevel nbInterestLevels , uint iVariant , float widthRatio , float peakOccurRatio , float baseBoost , TEcosystem iEcosystem , uint iFreq , uint iFamily ) ;
/// Returns -1 if the RM must NOT be generated, otherwise return the stat average
sint32 computeValues ( TStatQuality statQuality , const TFamInfo & famInfo , sint remarkableIndicesSetBaseIndex ,
TEcosystem iEcosystem , uint iFreq , uint iFamily ) ;
///
void calcQualitativeValues ( ) ;
/// Index of faber element in "MpParam"
uint32 FaberElement ;
/// Values
float Values [ NbCharacs ] ;
/// Average of the actual interest of the random values between 0 and 1
float ActualEnergy ;
///
float ActualOriginality ;
protected :
// Returns false if the RM must NOT be generated.
//bool randomizeJewelProtection( TStatQuality statQuality, TEcosystem iEcosystem, uint iFreq, uint iFamily );
void computeJewelProtection ( TStatQuality statQuality , TEcosystem iEcosystem , uint iFamily ) ;
} ;
//
void CFaberCharacteristics : : calcQualitativeValues ( )
{
float actualInterests [ NbCharacs ] ;
// Calculate the average of ratio between [0,1]
float sumActualInterest = 0.0f ;
uint nbCharacsUsed = 0 ;
for ( uint r = 0 ; r ! = NbCharacs ; + + r )
{
if ( MaxCharacValues [ r ] = = 0 )
continue ;
if ( ! CharacSlotFilter [ r ] [ FaberElement ] )
continue ;
float interestRatio = ( Values [ r ] / PeakCharacValues [ r ] ) ; // new: Peak is taken as the max => the Energy is in [0..100]
if ( ! PositiveCharacs [ r ] )
interestRatio = 1.0f - interestRatio ; // thus, can be negative
actualInterests [ r ] = interestRatio ;
sumActualInterest + = interestRatio ;
+ + nbCharacsUsed ;
}
if ( nbCharacsUsed = = 0 )
return ;
ActualEnergy = ( sumActualInterest / ( float ) nbCharacsUsed ) ;
if ( ActualEnergy > 1.0f )
ActualEnergy = 1.0f ;
2013-02-12 21:48:37 +00:00
// Calculate the standard deviation (SQRT(SUM((Ai-Aavg)^2)/N))
2012-05-29 13:31:11 +00:00
float varianceSum = 0.0f ;
for ( uint r = 0 ; r ! = NbCharacs ; + + r )
{
if ( MaxCharacValues [ r ] = = 0 )
continue ;
if ( ! CharacSlotFilter [ r ] [ FaberElement ] )
continue ;
varianceSum + = sqr ( actualInterests [ r ] - ActualEnergy ) ;
}
// Don't normalize standard deviation, otherwise low energy materials will be considered more
// original (by average) than high energy materials. They wouldn't be comparable.
//if ( ActualEnergy != 0.0f )
ActualOriginality = ( float ) sqrt ( ( double ) ( varianceSum / ( float ) nbCharacsUsed ) ) ; // / ActualEnergy;
//else
// nlinfo( "Null energy for craft slot %u", FaberElement );
}
/*
* Fill childrenToGet if rootNameForGetChildren is not null
*/
void fillFromDFN ( UFormLoader * formLoader , map < string , CDfnFieldInfo > & dfnFields , UFormDfn * formDfn , const string & rootName , const string & dfnFilename ,
const char * rootNameForGetChildren = NULL , vector < string > & childrenToGet = vector < string > ( ) )
{
uint32 i ;
for ( i = 0 ; i ! = formDfn - > getNumEntry ( ) ; + + i )
{
string entryName , rootBase ;
formDfn - > getEntryName ( i , entryName ) ;
rootBase = rootName . empty ( ) ? " " : ( rootName + " . " ) ;
UFormDfn : : TEntryType entryType ;
bool array ;
formDfn - > getEntryType ( i , entryType , array ) ;
switch ( entryType )
{
case UFormDfn : : EntryVirtualDfn :
{
CSmartPtr < UFormDfn > subFormDfn = formLoader - > loadFormDfn ( ( entryName + " .dfn " ) . c_str ( ) ) ;
if ( ! subFormDfn )
nlwarning ( " Can't load virtual DFN %s " , entryName . c_str ( ) ) ;
else
fillFromDFN ( formLoader , dfnFields , subFormDfn , rootBase + entryName , entryName + " .dfn " , rootNameForGetChildren , childrenToGet ) ; // recurse
break ;
}
case UFormDfn : : EntryDfn : // .dfn
{
UFormDfn * subFormDfn ;
if ( formDfn - > getEntryDfn ( i , & subFormDfn ) )
{
string filename ;
formDfn - > getEntryFilename ( i , filename ) ;
fillFromDFN ( formLoader , dfnFields , subFormDfn , rootBase + entryName , filename , rootNameForGetChildren , childrenToGet ) ; // recurse
}
if ( rootNameForGetChildren & & ( rootName = = rootNameForGetChildren ) )
{
childrenToGet . push_back ( rootBase + entryName ) ;
}
break ;
}
case UFormDfn : : EntryType : // .typ
{
vector < string > values , labels ;
UType * subType ;
if ( formDfn - > getEntryType ( i , & subType ) )
{
uint32 listSize = subType - > getNumDefinition ( ) ;
if ( listSize > 0 )
{
string label , value ;
for ( uint32 j = 0 ; j ! = listSize ; + + j )
{
subType - > getDefinition ( j , label , value ) ;
if ( ( subType - > getIncrement ( ) = = " 1 " ) & & ( subType - > getType ( ) = = UType : : UnsignedInt | | subType - > getType ( ) = = UType : : SignedInt ) )
{
// Fill blank entry for skipped identifier values (to allow indexing by identifier value)
sint num = atoi ( value . c_str ( ) ) ;
while ( num - ( sint ) values . size ( ) > 0 )
{
values . push_back ( " " ) ;
labels . push_back ( " " ) ;
}
}
values . push_back ( value ) ;
labels . push_back ( label ) ;
}
}
}
dfnFields . insert ( make_pair ( rootBase + entryName , CDfnFieldInfo ( values , labels ) ) ) ;
//nlinfo( "DFN entry: %s (in %s)", (rootBase + entryName).c_str(), dfnFilename.c_str() );
break ;
}
}
}
}
/*
*
*/
CForm * loadTemplateForm ( UFormLoader * formLoader , const string & sheetType )
{
CForm * form = ( CForm * ) formLoader - > loadForm ( ( string ( " _empty. " ) + sheetType ) . c_str ( ) ) ;
if ( ! form )
nlerror ( " Can't load sheet _empty.%s " , sheetType . c_str ( ) ) ;
return form ;
}
/*
*
*/
void eraseCarriageReturns ( string & s )
{
const char CR = ' \n ' ;
string : : size_type p = s . find ( CR ) ;
while ( ( p = s . find ( CR ) ) ! = string : : npos )
s . erase ( p , 1 ) ;
}
/*
*
*/
string getNomenclatureCode ( const string & longName , set < string > & usedCodes , uint32 nbLetters )
{
if ( nbLetters > longName . size ( ) )
nlerror ( " Wrong nbLetters for %s " , longName . c_str ( ) ) ;
// Start with beginning of name
string code = strlwr ( longName . substr ( 0 , nbLetters ) ) ;
uint32 i = nbLetters - 1 ;
while ( usedCodes . find ( code ) ! = usedCodes . end ( ) )
{
+ + i ;
if ( i < longName . size ( ) )
{
// Substitute last code char by a char from the name (except ' ')
if ( longName [ i ] ! = ' ' )
code [ nbLetters - 1 ] = tolower ( longName [ i ] ) ;
else
continue ;
}
else
{
// If no char from the name is suitable, increment the last char of the code until suitable
char c = 1 ;
while ( usedCodes . find ( code ) ! = usedCodes . end ( ) )
{
code [ nbLetters - 1 ] = tolower ( longName [ nbLetters - 1 ] ) + c ;
+ + c ;
if ( code [ 1 ] > ' z ' )
nlerror ( " Impossible to make code for %s " , longName . c_str ( ) ) ;
}
}
}
strlwr ( code ) ;
usedCodes . insert ( code ) ;
return code ;
}
/*
* Displays mapping if title not null .
*/
void buildNomenclatureCodes ( const char * title , const vector < string > & longNames , vector < string > & codes , uint32 nbLetters )
{
set < string > usedCodeSet ;
uint32 i ;
for ( i = 0 ; i ! = longNames . size ( ) ; + + i )
{
codes [ i ] = getNomenclatureCode ( longNames [ i ] , usedCodeSet , nbLetters ) ;
if ( title )
nlinfo ( " %s %s -> %s " , title , longNames [ i ] . c_str ( ) , codes [ i ] . c_str ( ) ) ;
//DebugLog->displayRawNL( "%s", longNames[i].c_str() );
}
}
/*
* Set the size of a family code to NB_FAMILY_CODE_CHARS
*/
void normalizeFamilyCode ( std : : string & s )
{
if ( s . size ( ) > NB_FAMILY_CODE_CHARS )
{
nlerror ( " Family codes limited to %u chars (%s) " , NB_FAMILY_CODE_CHARS , s . c_str ( ) ) ;
}
else
{
uint p = s . size ( ) ;
while ( p < NB_FAMILY_CODE_CHARS )
{
s = " 0 " + s ;
+ + p ;
}
}
}
/*
*
*/
void loadNomenclatureCodes ( const char * title , const vector < string > & longNames , vector < string > & codes , const char * filename )
{
if ( longNames . empty ( ) )
{
nlwarning ( " No nomenclature codes to load. %s " , title ? title : " " ) ;
return ;
}
codes . resize ( longNames . size ( ) ) ;
char lineBuffer [ 2048 ] ;
FILE * rulesFile ;
const char * SEPARATOR = " ; " ;
vector < string > args ;
vector < string > : : iterator iarg ;
vector < string > : : const_iterator ivs ;
if ( ( rulesFile = fopen ( filename , " r " ) ) = = NULL )
{
nlwarning ( " Can't find file %s " , filename ) ;
}
else
{
while ( ! feof ( rulesFile ) )
{
// Get from file
fgets ( lineBuffer , 2048 , rulesFile ) ;
explode ( lineBuffer , SEPARATOR , args ) ;
// Get rid of carriage returns!
for ( iarg = args . begin ( ) ; iarg ! = args . end ( ) ; + + iarg )
{
eraseCarriageReturns ( * iarg ) ;
}
// Read
const uint32 MIN_COLS = 6 ;
const uint32 NAME_COL = 4 ;
const uint32 C_COL = 2 ;
const uint32 R_COL = 3 ;
const uint32 NB_CODE_CHARS = 2 ;
if ( ( args . size ( ) > = MIN_COLS ) & & ( ! args [ 0 ] . empty ( ) ) & & ( args [ 0 ] . find ( " name " ) = = string : : npos ) ) // skip blank lines, and lines with blank header or "name" in the first column
{
if ( args [ NAME_COL ] . empty ( ) )
continue ;
ivs = find ( longNames . begin ( ) , longNames . end ( ) , args [ NAME_COL ] ) ;
if ( ivs = = longNames . end ( ) )
nlwarning ( " Name %s is not in the names array " , args [ NAME_COL ] . c_str ( ) ) ;
else
{
string code = args [ C_COL ] + args [ R_COL ] ;
if ( code . size ( ) < NB_CODE_CHARS )
{
nlwarning ( " Invalid partial code for %s: %s " , ( * ivs ) . c_str ( ) , code . c_str ( ) ) ;
continue ;
}
else if ( code . size ( ) > NB_CODE_CHARS )
{
nlinfo ( " Compacting code '%s' for %s " , code . c_str ( ) , ( * ivs ) . c_str ( ) ) ;
string : : size_type p ;
while ( ( p = code . find ( ' ' ) ) ! = string : : npos )
{
code . erase ( p , 1 ) ;
}
}
if ( codes [ ivs - longNames . begin ( ) ] . empty ( ) )
{
if ( title )
nlinfo ( " %s %s -> %s " , title , ( * ivs ) . c_str ( ) , code . c_str ( ) ) ;
codes [ ivs - longNames . begin ( ) ] = code ;
}
else
{
if ( code ! = codes [ ivs - longNames . begin ( ) ] )
nlwarning ( " Invalid nomenclature: (%s and %s for %s: " , codes [ ivs - longNames . begin ( ) ] . c_str ( ) , code . c_str ( ) , ( * ivs ) . c_str ( ) ) ;
}
}
}
}
for ( ivs = codes . begin ( ) ; ivs ! = codes . end ( ) ; + + ivs )
{
if ( ( * ivs ) . empty ( ) )
nlwarning ( " No code found for %s " , ( * ( longNames . begin ( ) + ( ivs - codes . begin ( ) ) ) ) . c_str ( ) ) ;
}
}
}
/*
*
*/
inline sint getLastUsedPropertySlot ( uint32 * iProperties , sint lastPropertySlot , uint32 undefinedProperty )
{
for ( sint r = lastPropertySlot ; r > = 0 ; - - r )
{
if ( iProperties [ r ] ! = undefinedProperty )
return r ;
}
return - 1 ;
}
/*
*
*/
inline bool passNegativeFilter ( const vector < uint32 > & incompatibilityList , uint32 iValue )
{
vector < uint32 > : : const_iterator ip = find ( incompatibilityList . begin ( ) , incompatibilityList . end ( ) , iValue ) ;
return ( ip = = incompatibilityList . end ( ) ) ;
}
/*
*
*/
inline bool passPositiveFilter ( const vector < uint32 > & compatibilityList , uint32 iValue )
{
vector < uint32 > : : const_iterator ip = find ( compatibilityList . begin ( ) , compatibilityList . end ( ) , iValue ) ;
return ( ip ! = compatibilityList . end ( ) ) ;
}
/*
* Reject a prop if it is in the incompatibility list of a family
*/
bool passPropFamilyFilter ( const vector < uint32 > & iFamilyRelatedProperties , uint32 iProp )
{
return passNegativeFilter ( iFamilyRelatedProperties , iProp ) ;
}
/*
* Reject a creature if NOT in the creature list of a family
*/
/*bool passCreatureFilter( const vector<uint32>& iFamilyRelatedCreatures, uint32 iCreature )
{
//nldebug( "%u related creatures, %s", iFamilyRelatedCreatures.size(), passPositiveFilter( iFamilyRelatedCreatures, iCreature ) ? "TRUE": "FALSE" );
return passPositiveFilter ( iFamilyRelatedCreatures , iCreature ) ;
} */
/*
*
*/
class CStrIComparator : public binary_function < string , string , bool >
{
public :
bool operator ( ) ( const string & s1 , const string & s2 ) const
{
return ( nlstricmp ( s1 , s2 ) = = 0 ) ;
}
} ;
/*
*
*/
void displayList ( const vector < string > & v , CLog * log = DebugLog )
{
vector < string > : : const_iterator ist ;
for ( ist = v . begin ( ) ; ist ! = v . end ( ) ; + + ist )
log - > displayRaw ( " %s " , ( * ist ) . c_str ( ) ) ;
log - > displayRawNL ( " " ) ;
}
/*
*
*/
uint32 getIndexFromString ( const string & s , const vector < string > & v , bool displayWarning = true )
{
if ( v . empty ( ) )
{
if ( displayWarning )
nlwarning ( " Can't find '%s' in empty array " , s . c_str ( ) ) ;
return ~ 0 ;
}
else
{
vector < string > : : const_iterator ist = find_if ( v . begin ( ) , v . end ( ) , bind2nd ( CStrIComparator ( ) , s ) ) ;
if ( ist = = v . end ( ) )
{
if ( displayWarning )
{
nlwarning ( " Can't find '%s' in: " , s . c_str ( ) ) ;
displayList ( v , WarningLog ) ;
}
return ~ 0 ;
}
else
return ist - v . begin ( ) ;
}
}
/*
*
*/
uint32 getIndexFromString ( const string & s , const char * * array , uint arraySize , bool displayWarning = true )
{
if ( arraySize = = 0 )
{
if ( displayWarning )
nlwarning ( " Can't find '%s' in empty array " , s . c_str ( ) ) ;
return ~ 0 ;
}
else
{
for ( uint i = 0 ; i ! = arraySize ; + + i )
{
if ( strlwr ( string ( array [ i ] ) ) = = strlwr ( s ) )
return i ;
}
if ( displayWarning )
{
nlwarning ( " Can't find '%s' in: " , s . c_str ( ) ) ;
//displayList( v, WarningLog );
}
return ~ 0 ;
}
}
/*
* Returns the index of the erased element , ~ 0 if not found
*/
uint32 removeEntryFromList ( vector < string > & v , const string & entry )
{
vector < string > : : iterator ivs ;
ivs = find ( v . begin ( ) , v . end ( ) , entry ) ;
uint32 index ;
if ( ivs ! = v . end ( ) )
{
index = ivs - v . begin ( ) ;
v . erase ( ivs ) ;
return index ;
}
else
return ~ 0 ;
}
/*
*
*/
bool removeEntryFromListByIndex ( vector < string > & v , uint32 index )
{
if ( index < v . size ( ) )
{
v . erase ( v . begin ( ) + index ) ;
return true ;
}
else
return false ;
}
typedef void ( * TMapDeliveryCallback ) ( mss & ) ;
typedef void ( * TVectorDeliveryCallback ) ( vs & ) ;
/*
*
*/
void loadCSVFile ( const char * filename , TMapDeliveryCallback deliveryCallback , bool firstColWithoutName = false )
{
char lineBuffer [ 2048 ] ;
FILE * file ;
const char * SEPARATOR = " ; " ;
vector < string > args ;
vector < string > : : iterator iarg ;
if ( ( file = fopen ( filename , " r " ) ) = = NULL )
{
nlwarning ( " Can't find file %s " , filename ) ;
}
else
{
// Read first line as header with column names
lineBuffer [ 0 ] = ' \0 ' ;
fgets ( lineBuffer , 2048 , file ) ;
explode ( lineBuffer , SEPARATOR , args ) ;
// Store column names (and get rid of carriage returns!)
vector < string > columnNames ;
mss valuesByName ;
for ( iarg = args . begin ( ) ; iarg ! = args . end ( ) ; + + iarg )
{
if ( firstColWithoutName & & ( iarg = = args . begin ( ) ) )
{
* iarg = " <> " ; // override column name for the 1st column
}
eraseCarriageReturns ( * iarg ) ;
columnNames . push_back ( * iarg ) ;
valuesByName . insert ( make_pair ( * iarg , string ( " " ) ) ) ;
}
while ( ! feof ( file ) )
{
// Get from file
lineBuffer [ 0 ] = ' \0 ' ;
fgets ( lineBuffer , 2048 , file ) ;
explode ( lineBuffer , SEPARATOR , args ) ;
// Set values (and get rid of carriage returns!)
for ( iarg = args . begin ( ) ; iarg ! = args . end ( ) ; + + iarg )
{
eraseCarriageReturns ( * iarg ) ;
valuesByName [ columnNames [ iarg - args . begin ( ) ] ] = * iarg ;
}
// Deliver the wanted fields
deliveryCallback ( valuesByName ) ;
}
}
}
/*
*
*/
void loadCSVFile ( const char * filename , TVectorDeliveryCallback deliveryCallback )
{
char lineBuffer [ 2048 ] ;
FILE * file ;
const char * SEPARATOR = " ; " ;
vs args ;
vs : : iterator iarg ;
if ( ( file = fopen ( filename , " r " ) ) = = NULL )
{
nlwarning ( " Can't find file %s " , filename ) ;
}
else
{
while ( ! feof ( file ) )
{
// Get from file
lineBuffer [ 0 ] = ' \0 ' ;
fgets ( lineBuffer , 2048 , file ) ;
explode ( lineBuffer , SEPARATOR , args ) ;
// Get rid of carriage returns!
for ( iarg = args . begin ( ) ; iarg ! = args . end ( ) ; + + iarg )
{
eraseCarriageReturns ( * iarg ) ;
}
// Deliver the wanted fields
deliveryCallback ( args ) ;
}
}
}
/*
*
*/
void loadValueFile ( const char * filename , const vector < string > & keyStrings ,
vector < sint > & contents , sint defaultValue )
{
nlassert ( keyStrings . size ( ) = = contents . size ( ) ) ;
char lineBuffer [ 2048 ] ;
FILE * rulesFile ;
const char * SEPARATOR = " ; " ;
vector < string > args ;
vector < string > : : iterator iarg ;
if ( ( rulesFile = fopen ( filename , " r " ) ) = = NULL )
{
nlwarning ( " Can't find file %s " , filename ) ;
}
else
{
while ( ! feof ( rulesFile ) )
{
// Get from file
lineBuffer [ 0 ] = ' \0 ' ;
fgets ( lineBuffer , 2048 , rulesFile ) ;
explode ( lineBuffer , SEPARATOR , args ) ;
// Get rid of carriage returns!
for ( iarg = args . begin ( ) ; iarg ! = args . end ( ) ; + + iarg )
{
eraseCarriageReturns ( * iarg ) ;
}
// Read
if ( ( ! args . empty ( ) ) & & ( ! args [ 0 ] . empty ( ) ) ) // skip blank lines, and lines with blank header
{
sint value = defaultValue ;
for ( uint32 a = 0 ; a ! = args . size ( ) - 1 ; + + a )
{
if ( ! args [ a + 1 ] . empty ( ) ) // skip blank entries
value = atoi ( args [ a + 1 ] . c_str ( ) ) ;
}
uint32 index = getIndexFromString ( args [ 0 ] , keyStrings ) ;
if ( index ! = ~ 0 )
{
contents [ index ] = value ;
}
}
}
fclose ( rulesFile ) ;
}
}
/*
*
*/
void loadRulesFile ( const char * filename , const vector < string > & keyStrings ,
const vector < string > & contentStrings , CRulesFilter & filter ,
const string & matchExtKeyAtFirstColumn = string ( ) )
{
char lineBuffer [ 2048 ] ;
FILE * rulesFile ;
const char * SEPARATOR = " ; " ;
uint32 firstColumn = matchExtKeyAtFirstColumn . empty ( ) ? 0 : 1 ;
vector < string > args ;
vector < string > : : iterator iarg ;
if ( ( rulesFile = fopen ( filename , " r " ) ) = = NULL )
{
nlwarning ( " Can't find file %s " , filename ) ;
}
else
{
while ( ! feof ( rulesFile ) )
{
// Get from file
lineBuffer [ 0 ] = ' \0 ' ;
fgets ( lineBuffer , 2048 , rulesFile ) ;
explode ( lineBuffer , SEPARATOR , args ) ;
// Get rid of carriage returns!
for ( iarg = args . begin ( ) ; iarg ! = args . end ( ) ; + + iarg )
{
eraseCarriageReturns ( * iarg ) ;
}
// Match with ext key string if set
if ( ( ! matchExtKeyAtFirstColumn . empty ( ) ) & & ( args [ 0 ] ! = matchExtKeyAtFirstColumn ) )
continue ;
// Read
if ( ( ! args . empty ( ) ) & & ( ! args [ firstColumn ] . empty ( ) ) ) // skip blank lines, and lines with blank header
{
vector < uint32 > contents ;
for ( uint32 a = firstColumn ; a ! = args . size ( ) - 1 ; + + a )
{
if ( ! args [ a + 1 ] . empty ( ) ) // skip blank entries
contents . push_back ( getIndexFromString ( args [ a + 1 ] , contentStrings ) ) ;
}
filter . insert ( make_pair ( getIndexFromString ( args [ firstColumn ] , keyStrings ) , contents ) ) ;
}
}
fclose ( rulesFile ) ;
}
}
/*
* 1 st column : extKeyStrings ( corresponding to the filters ' vector ' ) ; 2 nd : keyStrings
*/
void loadRulesFileMulti ( const char * filename , const vector < string > & extKeyStrings , const vector < string > & keyStrings , const vector < string > & contentStrings , vector < CRulesFilter > & filters )
{
filters . resize ( extKeyStrings . size ( ) ) ;
for ( uint32 i = 0 ; i ! = filters . size ( ) ; + + i )
{
loadRulesFile ( filename , keyStrings , contentStrings , filters [ i ] , extKeyStrings [ i ] ) ;
/*CRulesFilter::const_iterator irf;
nldebug ( " %s " , extKeyStrings [ i ] . c_str ( ) ) ;
for ( irf = filters [ i ] . begin ( ) ; irf ! = filters [ i ] . end ( ) ; + + irf )
{
nldebug ( " %s " , keyStrings [ ( * irf ) . first ] . c_str ( ) ) ;
vector < uint32 > : : const_iterator ivi ;
for ( ivi = ( * irf ) . second . begin ( ) ; ivi ! = ( * irf ) . second . end ( ) ; + + ivi )
{
nldebug ( " %u " , * ivi ) ;
}
} */
}
}
/*
* Clear the form to reuse it ( and all contents below node )
*/
void clearSheet ( CForm * form , UFormElm * node )
{
( ( CFormElm * ) node ) - > clean ( ) ;
form - > clean ( ) ;
}
/*
* Saves to disk if bool WriteSheetsToDisk is true
*/
void flushSheetToDisk ( const string & fullFilename , UForm * form )
{
if ( WriteSheetsToDisk )
{
COFile output ( fullFilename ) ;
form - > write ( output , false ) ;
}
}
/*
*
*/
string : : size_type findCapital ( const string & s , string : : size_type startPos )
{
string : : size_type p ;
for ( p = startPos ; p ! = s . size ( ) ; + + p )
{
if ( ( s [ p ] > = ' A ' ) & & ( s [ p ] < = ' Z ' ) )
return p ;
}
return string : : npos ;
}
/*
* Transform " MyString " into " My string "
*/
void detachValue ( string & s )
{
if ( s . size ( ) < 2 )
return ;
string : : size_type p ;
while ( ( p = findCapital ( s , 1 ) ) ! = string : : npos )
{
s . insert ( p , " " ) ;
s [ p + 1 ] = tolower ( s [ p + 1 ] ) ;
}
// Rip off any blank at the end
if ( s [ s . size ( ) - 1 ] = = ' ' )
{
s . resize ( s . size ( ) - 1 ) ;
}
}
/*
*
*/
void getTransposedMap ( CRulesFilter & dest , const CRulesFilter & src )
{
CRulesFilter : : const_iterator im ;
for ( im = src . begin ( ) ; im ! = src . end ( ) ; + + im )
{
vector < uint32 > : : const_iterator iv ;
for ( iv = ( * im ) . second . begin ( ) ; iv ! = ( * im ) . second . end ( ) ; + + iv )
{
dest [ * iv ] . push_back ( ( * im ) . first ) ;
}
}
}
/*
*
*/
string makeFaberElementCode ( uint32 iFaberElement , TFaberInterestLevel level , TFaberInterestLevel nbInterestLevels )
{
return toString ( " %c%d " , ' a ' + iFaberElement , getNomenclaturedInterestLevel ( level , nbInterestLevels ) ) ;
}
/*
*
*/
inline bool hasMatchingFaberLevel ( TFaberInterestLevel storedLevel , TFaberInterestLevel submittedLevel )
{
return storedLevel < = submittedLevel ;
}
/*
*
*/
//void keepOnlyHighestLevel( vector<CFaberCombination*>& codes )
//{
// nlassert( ! codes.empty() );
// sint maxLevel = -1;
// uint32 i;
// for ( i=0; i!=codes.size(); ++i )
// {
// if ( codes[i]->FirstLevel > maxLevel )
// {
// maxLevel = codes[i]->FirstLevel;
// }
// }
// vector<CFaberCombination*> remainingCodes;
// for ( i=0; i!=codes.size(); ++i )
// {
// if ( codes[i]->FirstLevel == maxLevel )
// remainingCodes.push_back( codes[i] );
// }
//
// //nldebug( "%u codes, highest level = %u with %u occurences", codes.size(), maxLevel, remainingCodes.size() );
// //nlassert( remainingCodes.size() <= codes.size() );
// codes = remainingCodes;
// nlassert( ! codes.empty() );
//}
/*
*
*/
bool allIncludedIn ( const vu & subset , const vu & bigset )
{
vu : : const_iterator iv ;
for ( iv = subset . begin ( ) ; iv ! = subset . end ( ) ; + + iv )
{
if ( find ( bigset . begin ( ) , bigset . end ( ) , * iv ) = = bigset . end ( ) )
return false ;
}
return true ;
}
/*
*
*/
void loadConfigFlag ( CConfigFile & configFile , const char * varTitle , bool & flag )
{
CConfigFile : : CVar * var = configFile . getVarPtr ( varTitle ) ;
if ( var )
flag = ( var - > asInt ( ) = = 1 ) ;
}
/*
*
*/
string : : size_type getCapitalFromPos ( const string & s , string : : size_type startPos )
{
//nldebug( "%s %u", s.c_str(), startPos );
string : : size_type p ;
for ( p = startPos ; p < s . size ( ) ; + + p )
{
if ( ( s [ p ] > = ' A ' ) & & ( s [ p ] < = ' Z ' ) )
return p ;
}
return string : : npos ;
}
/*
* Also used to make system_mp filenames .
* Converts " My Identifier " or " MyIdentifier " to " my_identifier " ( " My identifier " to " Myidentifier " )
*/
string conventionalDirectory ( const string & dirname )
{
if ( dirname . empty ( ) )
return " " ;
string result = dirname ;
// Remove blanks
string : : size_type p = 0 ;
while ( ( p = result . find ( ' ' ) ) ! = string : : npos )
{
result . erase ( p , 1 ) ;
}
// Convert capitals to underscores
result [ 0 ] = tolower ( result [ 0 ] ) ;
p = 1 ;
while ( ( p = getCapitalFromPos ( result , p ) ) ! = string : : npos )
{
result . insert ( p , " _ " ) ;
+ + p ;
result [ p ] = tolower ( result [ p ] ) ;
}
return result ;
}
mss UniqueRMNamesAndSheetCodeHead ;
/*
*
*/
void readRMNames ( mss & values )
{
string & name = values [ " basics.name " ] ;
if ( ! name . empty ( ) )
{
string radix = values [ " FILE " ] . substr ( 0 , 5 ) ;
UniqueRMNamesAndSheetCodeHead . insert ( make_pair ( name , radix ) ) ;
}
}
/*
*
*/
void loadTitles ( const string & sourceWords , const string & sourceBase , const string & languageCode , CTitles & dest )
{
STRING_MANAGER : : TWorksheet worksheet ;
STRING_MANAGER : : loadExcelSheet ( TranslationPath + sourceBase + " / " + sourceWords + " _words_ " + languageCode + " .txt " , worksheet ) ;
uint cp , cn , nbTitles = 0 ;
if ( worksheet . findCol ( ucstring ( sourceWords + " ID " ) , cp ) & & worksheet . findCol ( ucstring ( " name " ) , cn ) )
{
for ( std : : vector < STRING_MANAGER : : TWorksheet : : TRow > : : iterator ip = worksheet . begin ( ) ; ip ! = worksheet . end ( ) ; + + ip )
{
if ( ip = = worksheet . begin ( ) ) // skip first row
continue ;
STRING_MANAGER : : TWorksheet : : TRow & row = * ip ;
dest . insert ( make_pair ( row [ cp ] . toString ( ) , row [ cn ] . toUtf8 ( ) ) ) ;
+ + nbTitles ;
}
}
else
nlwarning ( " %s ID or name not found " , sourceWords . c_str ( ) ) ;
nlinfo ( " Loaded %u %s titles " , nbTitles , sourceWords . c_str ( ) ) ;
}
/*
*
*/
void extractRawMaterialNames ( )
{
loadCSVFile ( ExtractNamesCsv . c_str ( ) , readRMNames ) ;
FILE * output = fopen ( ( CFile : : getFilenameWithoutExtension ( ExtractNamesCsv ) + " _output.csv " ) . c_str ( ) , " wt " ) ;
fprintf ( output , " Code;Name \n " ) ;
for ( mss : : const_iterator iun = UniqueRMNamesAndSheetCodeHead . begin ( ) ; iun ! = UniqueRMNamesAndSheetCodeHead . end ( ) ; + + iun )
{
const string & codeRadix = ( * iun ) . second ;
const string & name = ( * iun ) . first ;
fprintf ( output , " %s;%s \n " , codeRadix . c_str ( ) , name . c_str ( ) ) ;
}
}
/*
*
*/
void cleanExteriorWhitespace ( vs & line )
{
for ( vs : : iterator it = line . begin ( ) ; it ! = line . end ( ) ; + + it )
{
CSString & s = ( * it ) ;
string : : size_type p ;
for ( p = 0 ; p ! = s . size ( ) ; + + p )
{
if ( s [ p ] ! = ' ' )
break ;
}
if ( ( p ! = 0 ) & & ( p ! = s . size ( ) ) )
s = s . substr ( p ) ;
for ( p = 0 ; p ! = s . size ( ) ; + + p )
{
if ( s [ s . size ( ) - 1 - p ] ! = ' ' )
break ;
}
if ( ( p ! = 0 ) & & ( p ! = s . size ( ) ) )
s = s . rightCrop ( p ) ;
}
}
uint TFamInfo : : UseGenerateOnly = 0 ;
// Only used for deposits; for creature, works with the creature sheets found
/*bool TFamInfo::existsInEcosystem( TEcosystem iEcosystem, TStatQuality statQuality ) const
{
switch ( iEcosystem )
{
case CommonEcosystem : // The Common rm exists if the rm family has a freq=2 (or 0 but only in Supreme)
return ( ( find ( Freqs . begin ( ) , Freqs . end ( ) , 2 ) ! = Freqs . end ( ) )
| | ( ( find ( Freqs . begin ( ) , Freqs . end ( ) , 0 ) ! = Freqs . end ( ) ) & & ( statQuality = = Supreme ) ) ) ;
// was: find_if ... bind2nd( equals<uint>(), 1 )
break ;
case PrimeRoots : // Only freq 1 families exist if the PrimeRoots
return find ( Freqs . begin ( ) , Freqs . end ( ) , 1 ) ! = Freqs . end ( ) ;
break ;
default : // A rm family exists in the ecosystem matching a civ if the corresponding freq is 1 or 3
{
uint iCiv = getIndexFromString ( ecosystemCodes [ iEcosystem ] , CivEcosystemCodes , NbCiv , false ) ;
vector < TCiv > : : const_iterator it = find ( Civs . begin ( ) , Civs . end ( ) , ( TCiv ) iCiv ) ;
if ( it ! = Civs . end ( ) )
return ( Freqs [ it - Civs . begin ( ) ] = = 1 ) | | ( Freqs [ it - Civs . begin ( ) ] = = 3 ) ;
else
return false ;
}
}
} */
// Only used for deposits;
bool TFamInfo : : existsInEcosystem ( TEcosystem iEcosystem , TStatQuality statQuality ) const
{
if ( find ( Freqs . begin ( ) , Freqs . end ( ) , 0 ) ! = Freqs . end ( ) )
{
// Freq 0 => only Common/Supreme
return ( statQuality = = Supreme ) & & ( iEcosystem = = CommonEcosystem ) ;
}
else if ( statQuality < = Fine )
{
// Basic, Fine => Common
return ( iEcosystem = = CommonEcosystem ) ;
}
else
{
// Choice to Supreme => One per ecosystem
return ( iEcosystem ! = CommonEcosystem ) & & ( iEcosystem < NbEcosystems ) ;
}
}
/*
*
*/
struct TCraftPartInfo
{
CSString Name ;
CSString Path ;
uint8 PartIndex ;
bool Enabled ;
} ;
/*
*
*/
class CCraftParts
{
public :
///
CCraftParts ( ) : CraftParts ( NbFaberElements )
{
for ( uint i = 0 ; i ! = NbFaberElements ; + + i )
{
CraftParts [ i ] . PartIndex = i ;
CraftParts [ i ] . Enabled = false ;
}
}
///
void registerPartChars ( const CSString & parts )
{
for ( string : : size_type p = 0 ; p ! = parts . size ( ) ; + + p )
{
uint index = ( uint ) ( parts [ p ] - ' A ' ) ;
CraftParts [ index ] . Enabled = true ;
}
}
///
bool isEnabled ( uint index ) const
{
return CraftParts [ index ] . Enabled ;
}
///
void getNamesAndPaths ( const vector < string > & paths )
{
uint i = 0 ;
vector < string > : : const_iterator ip ;
for ( ip = paths . begin ( ) ; ip ! = paths . end ( ) ; + + ip )
{
if ( i > = CraftParts . size ( ) )
nlerror ( " Mismatch between sitem DFN and constant (nb of craft parts) " ) ;
CraftParts [ i ] . Path = ( * ip ) ;
string : : size_type p = ( * ip ) . rfind ( ' . ' ) + 1 ; // string::npos+1 gives 0
CraftParts [ i ] . Name = ( * ip ) . substr ( p ) ;
nldebug ( " %u: %s " , ip - paths . begin ( ) , CraftParts [ i ] . Name . c_str ( ) ) ;
+ + i ;
}
}
///
TCraftPartInfo & operator [ ] ( uint index ) { return CraftParts [ index ] ; }
vector < TCraftPartInfo > CraftParts ;
} ;
typedef map < CSString , TFamInfo , CUnsensitiveSStringLessPred > CFamMap ;
CFamMap FamSet ;
CCraftParts CraftParts ;
enum TFamAndPropLine {
LFam , LGroup , LCraftParts , LCiv , LFreq , LLoc ,
LIconMain , LIconBk , LIconOv1 , LIconOv2 , LIconSpecial ,
LCraftPlans , LGenerateOnly ,
LBaseOfRemarkableStatIndices ,
LColorIndex = LBaseOfRemarkableStatIndices + NB_REMARKABLE_STAT_INDICES ,
LJewelProtIndex ,
NbFamAndPropCols } ;
// static
bool TFamInfo : : mustGenerateFamily ( uint iFamily )
{
if ( families [ iFamily ] . empty ( ) )
return false ;
else if ( ! TFamInfo : : UseGenerateOnly )
return true ;
else
{
TFamInfo & famInfo = FamSet [ families [ iFamily ] ] ;
return ( famInfo . GenerateOnly ) ;
}
}
/*
*
*/
CSString getShortFaberElemString ( uint rFaberElem )
{
string & longString = CraftParts [ rFaberElem ] . Name ;
return reinterpret_cast < CSString & > ( longString . substr ( longString . find ( " ( " ) + 1 ) ) . rightCrop ( 1 ) ;
}
/*
*
*/
TCiv getCivFromStr ( const CSString & civStr )
{
if ( civStr . empty ( ) )
return AllCiv ;
else
{
for ( uint i = 0 ; i ! = NbCiv ; + + i )
{
if ( civStr = = CSString ( CivNames [ i ] ) )
return ( TCiv ) i ;
}
nlwarning ( " Unknown civ '%s' " , civStr . c_str ( ) ) ;
return AllCiv ;
}
}
/*
*
*/
uint getFreqFromStr ( const CSString & freqStr )
{
uint f = atoi ( freqStr . c_str ( ) ) ;
if ( ( f < 1 ) & & ( f > 5 ) )
nlwarning ( " Unknown freq '%s' " , freqStr . c_str ( ) ) ;
return f ;
}
/*
* Returns ~ 0 if s is empty
*/
TGroup getNewOrExistingGroupFromStr ( const CSString & s )
{
uint i = getIndexFromString ( s , groups , false ) ;
if ( i = = ~ 0 )
{
if ( s . empty ( ) )
return ~ 0 ;
else
{
i = groups . size ( ) ;
groups . push_back ( s ) ;
nlinfo ( " New group: %s (%u) " , s . c_str ( ) , i ) ;
}
}
return i ;
}
/*
*
*/
void deliverFamAndProp ( vs & line )
{
if ( line . size ( ) < NbFamAndPropCols )
line . resize ( NbFamAndPropCols ) ;
cleanExteriorWhitespace ( line ) ;
if ( line [ LFam ] . empty ( ) )
{
// Load special icons
if ( ( line . size ( ) > = LIconSpecial + 1 ) & & ( ! line [ LIconSpecial ] . empty ( ) ) & & ( line [ LIconMain ] . empty ( ) ) )
{
/*if ( line.size() >= LIconMain+1 )
Icons [ line [ LIconSpecial ] ] . Icon = line [ LIconMain ] ; */
if ( line . size ( ) > = LIconBk + 1 )
Icons [ line [ LIconSpecial ] ] . IconBackground = line [ LIconBk ] ;
if ( line . size ( ) > = LIconOv1 + 1 )
Icons [ line [ LIconSpecial ] ] . IconOver = line [ LIconOv1 ] ;
}
return ;
}
// Load icons of families
if ( line . size ( ) > = LIconMain + 1 )
{
Icons [ line [ LFam ] ] . Icon = line [ LIconMain ] ;
if ( ! line [ LGroup ] . empty ( ) )
{
// For group, set icon of first family of group found! (for forage source knowledge)
if ( Icons . find ( line [ LGroup ] ) = = Icons . end ( ) )
{
Icons [ line [ LGroup ] ] . Icon = line [ LIconMain ] ;
}
}
}
if ( line . size ( ) > = LIconBk + 1 )
Icons [ line [ LFam ] ] . IconBackground = line [ LIconBk ] ;
if ( line . size ( ) > = LIconOv1 + 1 )
Icons [ line [ LFam ] ] . IconOver = line [ LIconOv1 ] ;
TFamInfo & famInfo = FamSet [ line [ LFam ] ] ;
famInfo . IsActive = true ;
/*if ( ! line[LCraftParts].empty() )
{
// Store by property (line[LProp])
famInfo . Properties . push_back ( line [ LProp ] ) ;
famInfo . CraftPartsByProp . push_back ( famInfo . CompatibleCraftParts . size ( ) ) ; // beginning of craft parts chars
famInfo . CompatibleCraftParts + = line [ LCraftParts ] ;
CraftParts . registerPartChars ( line [ LCraftParts ] ) ;
famInfo . Civs . push_back ( getCivFromStr ( line [ LCiv ] ) ) ;
famInfo . Freqs . push_back ( getFreqFromStr ( line [ LFreq ] ) ) ;
famInfo . IsInDeposits = line [ LLoc ] . contains ( " D " ) ;
famInfo . IsInCreatures = line [ LLoc ] . contains ( " C " ) ;
if ( ! ( famInfo . IsInDeposits | | famInfo . IsInCreatures ) )
nlwarning ( " Unknown loc for %s " , line [ LFam ] . c_str ( ) ) ;
} */
for ( string : : size_type p = 0 ; p ! = line [ LCraftParts ] . size ( ) ; + + p )
{
// Store by property = craft part (each char of line[LCraftParts])
CSString craftPart = string ( 1 , line [ LCraftParts ] [ p ] ) ;
famInfo . Properties . push_back ( craftPart ) ;
famInfo . CraftPartsByProp . push_back ( famInfo . CompatibleCraftParts . size ( ) ) ;
famInfo . CompatibleCraftParts + = craftPart ;
CraftParts . registerPartChars ( craftPart ) ;
famInfo . Civs . push_back ( getCivFromStr ( line [ LCiv ] ) ) ;
famInfo . Freqs . push_back ( getFreqFromStr ( line [ LFreq ] ) ) ;
}
if ( line [ LCraftParts ] . empty ( ) )
{
famInfo . Freqs . push_back ( getFreqFromStr ( line [ LFreq ] ) ) ; // freq needed for Rarity computation
}
famInfo . Group = getNewOrExistingGroupFromStr ( line [ LGroup ] ) ;
famInfo . IsInDeposits = line [ LLoc ] . contains ( " D " ) ;
famInfo . IsInCreatures = line [ LLoc ] . contains ( " C " ) ;
if ( ! ( famInfo . IsInDeposits | | famInfo . IsInCreatures ) )
{
famInfo . SpecialCreatureTag = line [ LLoc ] ;
if ( ( famInfo . SpecialCreatureTag [ 0 ] ! = ' G ' ) & & ( famInfo . SpecialCreatureTag [ 0 ] ! = ' I ' ) )
nlwarning ( " Unknown loc %s for %s " , line [ LLoc ] . c_str ( ) , line [ LFam ] . c_str ( ) ) ;
}
famInfo . IsForMission = line [ LCraftParts ] . empty ( ) ;
for ( uint i = 0 ; i ! = NB_REMARKABLE_STAT_INDICES ; + + i )
{
if ( line [ LBaseOfRemarkableStatIndices + i ] . empty ( ) & & ( ! line [ LCraftParts ] . empty ( ) ) & & ( line [ LFreq ] ! = " 0 " ) )
nlerror ( " %s has empty stat index %u " , line [ LFam ] . c_str ( ) , i ) ;
famInfo . RemarkableStatIndex [ i ] = atoi ( line [ LBaseOfRemarkableStatIndices + i ] . c_str ( ) ) ;
}
if ( ! line [ LColorIndex ] . empty ( ) )
famInfo . ColorIndex = atoi ( line [ LColorIndex ] . c_str ( ) ) ;
if ( ! line [ LJewelProtIndex ] . empty ( ) )
famInfo . JewelProtIndex = atoi ( line [ LJewelProtIndex ] . c_str ( ) ) ;
bool markedForGeneration = ( line [ LGenerateOnly ] = = " X " ) ;
if ( ( ! markedForGeneration ) & & famInfo . GenerateOnly )
{
nlwarning ( " Found duplicate family line with different GenerateOnly setting " ) ;
}
else
{
famInfo . GenerateOnly = markedForGeneration ;
}
if ( famInfo . GenerateOnly )
+ + TFamInfo : : UseGenerateOnly ;
}
typedef map < TGroup , set < uint32 > > CGroupMap ;
/*
*
*/
void loadFamAndProp ( const string & filename , bool displayAll )
{
loadCSVFile ( filename . c_str ( ) , deliverFamAndProp ) ;
if ( displayAll )
{
set < CSString , CUnsensitiveSStringLessPred > propSet ;
CGroupMap groupMap ;
/// Generate contents of item_mp_family.typ (and fill group map)
nlinfo ( " item_mp_family.typ: " ) ;
InfoLog - > displayRawNL ( " <DEFINITION Label= \" Undefined \" Value= \" 0 \" /> " ) ;
uint i = 1 ;
for ( CFamMap : : iterator iss = FamSet . begin ( ) ; iss ! = FamSet . end ( ) ; + + iss )
{
const CSString & famStr = ( * iss ) . first ;
TFamInfo & famInfo = ( * iss ) . second ;
InfoLog - > displayRawNL ( " <DEFINITION Label= \" %s \" Value= \" %u \" /> " , famStr . c_str ( ) , i ) ;
// Get info about props and group
for ( vs : : iterator ip = famInfo . Properties . begin ( ) ; ip ! = famInfo . Properties . end ( ) ; + + ip )
{
propSet . insert ( * ip ) ;
}
groupMap [ famInfo . Group ] . insert ( i ) ; // ~0 is for "no group" (creature's RMs only)
+ + i ;
}
/*
/// Generate family-specialized forage search bricks (TODO)
nlinfo ( " Family-specialized forage search bricks: " ) ;
i = 1 ;
for ( CGroupMap : : iterator igm = groupMap . begin ( ) ; igm ! = groupMap . end ( ) ; + + igm )
{
CSString skill = toString ( " SHFM%u " , i ) ;
CSString rmgrpBrickCode = toString ( " BHFPMB%02u " , i ) ;
CSString rmfamBrickFamCode = " BHFPMI " + string ( 1 , ( char ) ' A ' + ( ( char ) ( i - 1 ) ) ) ;
uint j = 1 ;
for ( set < uint32 > : : : iterator ifs = ( * igm ) . begin ( ) ; ifs ! = ( * igm ) . end ( ) ; + + ifs )
{
// TODO: modifier of modifier
CSString brickCode = rmfamBrickFamCode + toString ( " %02u " , j ) ;
InfoLog - > displayRawNL ( " %s \t 80 \t %s \t %u \t \t %s \t \t FG_RMFAM_FILT: %u \t " , brickCode . c_str ( ) , rmgrpBrickCode . c_str ( ) , j , skill . c_str ( ) , ( * ifs ) ) ;
+ + j ;
}
}
/// Generate family-specialized forage search phrases (TODO)
nlinfo ( " Family-specialized forage search phrases: " ) ;
i = 1 ;
for ( CFamMap : : iterator iss = FamSet . begin ( ) ; iss ! = FamSet . end ( ) ; + + iss )
{
const CSString & famStr = ( * iss ) . first ;
TFamInfo & famInfo = ( * iss ) . second ;
InfoLog - > displayRawNL ( " <DEFINITION Label= \" %s \" Value= \" %u \" /> " , famStr . c_str ( ) , i ) ;
}
/// Generate family-specialized forage extraction bricks (TODO)
nlinfo ( " Family-specialized forage extraction bricks: " ) ;
i = 1 ;
for ( CFamMap : : iterator iss = FamSet . begin ( ) ; iss ! = FamSet . end ( ) ; + + iss )
{
const CSString & famStr = ( * iss ) . first ;
TFamInfo & famInfo = ( * iss ) . second ;
InfoLog - > displayRawNL ( " <DEFINITION Label= \" %s \" Value= \" %u \" /> " , famStr . c_str ( ) , i ) ;
+ + i ;
}
/// Generate family-specialized forage extraction phrases (TODO)
nlinfo ( " Family-specialized forage extraction phrases: " ) ;
i = 1 ;
for ( CFamMap : : iterator iss = FamSet . begin ( ) ; iss ! = FamSet . end ( ) ; + + iss )
{
const CSString & famStr = ( * iss ) . first ;
TFamInfo & famInfo = ( * iss ) . second ;
InfoLog - > displayRawNL ( " <DEFINITION Label= \" %s \" Value= \" %u \" /> " , famStr . c_str ( ) , i ) ;
+ + i ;
} */
/// Generate item_mp_property.typ
nlinfo ( " Item parts as props: " ) ;
InfoLog - > displayRawNL ( " <DEFINITION Label= \" Undefined \" Value= \" 0 \" /> " ) ;
i = 1 ;
for ( set < CSString , CUnsensitiveSStringLessPred > : : iterator iss = propSet . begin ( ) ; iss ! = propSet . end ( ) ; + + iss )
{
InfoLog - > displayRawNL ( " <DEFINITION Label= \" %s \" Value= \" %u \" /> " , ( * iss ) . c_str ( ) , i ) ;
+ + i ;
}
/// Generate item_mp_group.typ
nlinfo ( " Groups: " ) ;
InfoLog - > displayRawNL ( " <DEFINITION Label= \" Undefined \" Value= \" 0 \" /> " ) ;
i = 1 ;
for ( CGroupMap : : iterator igm = groupMap . begin ( ) ; igm ! = groupMap . end ( ) ; + + igm )
{
if ( ( * igm ) . first ! = ~ 0 )
{
InfoLog - > displayRawNL ( " <DEFINITION Label= \" %s \" Value= \" %u \" /> " , ( groups [ ( * igm ) . first ] ) . c_str ( ) , i ) ;
+ + i ;
}
}
/*
/// Generate group-specialized forage search bricks (TODO)
nlinfo ( " Group-specialized forage search bricks: " ) ;
i = 1 ;
for ( CGroupMap : : iterator igm = groupMap . begin ( ) ; igm ! = groupMap . end ( ) ; + + igm )
{
CSString skill = toString ( " SHFM%u " , i ) ;
CSString rmgrpBrickCode = toString ( " BHFPMB%02u " , i ) ;
+ + i ;
}
/// Generate group-specialized forage search phrases
nlinfo ( " Group-specialized forage search phrases: " ) ;
i = 1 ;
for ( set < CSString , CUnsensitiveSStringLessPred > : : iterator iss = groupSet . begin ( ) ; iss ! = groupSet . end ( ) ; + + iss )
{
if ( ( * iss ) . empty ( ) )
continue ;
InfoLog - > displayRawNL ( " <DEFINITION Label= \" %s \" Value= \" %u \" /> " , ( * iss ) . c_str ( ) , i ) ;
+ + i ;
}
/// Generate group-specialized forage extraction bricks
nlinfo ( " Group-specialized forage extraction bricks: " ) ;
i = 1 ;
for ( set < CSString , CUnsensitiveSStringLessPred > : : iterator iss = groupSet . begin ( ) ; iss ! = groupSet . end ( ) ; + + iss )
{
if ( ( * iss ) . empty ( ) )
continue ;
InfoLog - > displayRawNL ( " <DEFINITION Label= \" %s \" Value= \" %u \" /> " , ( * iss ) . c_str ( ) , i ) ;
+ + i ;
}
/// Generate group-specialized forage extraction phrases
nlinfo ( " Group-specialized forage extraction phrases: " ) ;
i = 1 ;
for ( set < CSString , CUnsensitiveSStringLessPred > : : iterator iss = groupSet . begin ( ) ; iss ! = groupSet . end ( ) ; + + iss )
{
if ( ( * iss ) . empty ( ) )
continue ;
InfoLog - > displayRawNL ( " <DEFINITION Label= \" %s \" Value= \" %u \" /> " , ( * iss ) . c_str ( ) , i ) ;
+ + i ;
} */
nlinfo ( " TODO: Keep old values when adding new entries " ) ;
nlinfo ( " Don't forget to regen craft plans and to map localized texts " ) ;
}
}
/*
* Multi - indexed array .
* NC is the number of columns .
*/
template < uint32 NC >
class CSortableData
{
public :
/// A row is made of fields, usually 1 per column but there may be more than one (each one is a key)
struct TSortableItem
{
std : : vector < std : : string > Fields [ NC ] ;
///
void push ( uint32 column , const std : : string & f , bool allowDuplicates = false )
{
if ( ( allowDuplicates ) | | ( find ( Fields [ column ] . begin ( ) , Fields [ column ] . end ( ) , f ) = = Fields [ column ] . end ( ) ) )
Fields [ column ] . push_back ( f ) ;
}
/**
* Display the item as a row of a HTML table .
* If ( key ! = previousKey ) and ( name = = previousName ) , the row will not be displayed entirely to save space
*
* \ param keyColumn If not ~ 0 , column used for sorting = > this column displays only the field matching the key
* \ param key The key used for sorting ( see keyColumn )
* \ param previousKey Previous key
* \ param nameColumn If not ~ 0 , column used for the unique name ( column must have exaclty one element )
* \ param previousName Previous name
*/
std : : string toHTMLRow ( uint32 keyColumn = ~ 0 , const string & key = string ( ) , const string & previousKey = string ( ) ,
uint32 nameColumn = ~ 0 , const string & previousName = string ( ) ) const
{
std : : string s = " <tr> " ;
bool lightMode = ( nameColumn = = ~ 0 ) ? false : ( ( key ! = previousKey ) & & ( Fields [ nameColumn ] [ 0 ] = = previousName ) ) ;
for ( uint32 c = 0 ; c ! = NC ; + + c )
{
s + = " <td> " ;
if ( c = = keyColumn )
s + = key ; // key should be a substr of toString( c )
else
{
if ( lightMode )
s + = " \" " ;
else
s + = columnToString ( c ) ;
}
s + = " </td> " ;
}
s + = " </tr> \n " ;
return s ;
}
///
std : : string toCSVLine ( char columnSeparator = ' , ' , string internalSeparator = " - " , uint32 keyColumn = ~ 0 , const string & key = string ( ) , const string & previousKey = string ( ) ,
uint32 nameColumn = ~ 0 , const string & previousName = string ( ) ) const
{
std : : string s ;
bool lightMode = ( nameColumn = = ~ 0 ) ? false : ( ( key ! = previousKey ) & & ( Fields [ nameColumn ] [ 0 ] = = previousName ) ) ;
for ( uint32 c = 0 ; c ! = NC ; + + c )
{
if ( c = = keyColumn )
s + = key ; // key should be a substr of columnToString( c )
else
{
if ( lightMode )
s + = " \" " ;
else
s + = columnToString ( c , internalSeparator ) ;
}
s + = columnSeparator ;
}
s + = " \n " ;
return s ;
}
///
std : : string columnToString ( uint32 column , const std : : string & internalSeparator = " , " ) const
{
std : : string s ;
std : : vector < std : : string > : : const_iterator ivs ;
for ( ivs = Fields [ column ] . begin ( ) ; ivs ! = Fields [ column ] . end ( ) ; + + ivs )
{
if ( ivs ! = Fields [ column ] . begin ( ) )
s + = internalSeparator ;
s + = ( * ivs ) ;
}
return s ;
}
} ;
typedef std : : multimap < std : : string , uint32 > CLookup ; // key to index (not pt because reallocation invalidates pointers)
typedef std : : vector < TSortableItem > CItems ;
/// Init
void init ( bool enabled )
{
_Enabled = enabled ;
}
/// Add a row
void addItem ( const TSortableItem & item )
{
if ( ! _Enabled )
return ;
_Items . push_back ( item ) ;
for ( uint32 c = 0 ; c ! = NC ; + + c )
{
for ( std : : vector < std : : string > : : const_iterator ik = item . Fields [ c ] . begin ( ) ; ik ! = item . Fields [ c ] . end ( ) ; + + ik )
{
_Indices [ c ] . insert ( make_pair ( * ik , _Items . size ( ) - 1 ) ) ;
}
}
}
/**
* Update a row ( found by the first column , which must have exactly one element ) .
* Returns true if it existed before , false if it ' s being created .
* If it existed before :
* - Does not remove elements that already exist and are not in the new item
* - Adds the new elements found in the new item at the specified columns , and updates lookup map
*/
bool updateItemAppend ( const TSortableItem & item , uint32 column )
{
if ( ! _Enabled )
return true ; // quiet
uint32 nameColumn = 0 ;
CLookup : : iterator ilk = _Indices [ nameColumn ] . find ( item . Fields [ nameColumn ] [ 0 ] ) ;
if ( ilk ! = _Indices [ nameColumn ] . end ( ) )
{
uint32 & index = ( * ilk ) . second ;
// Update map for the specified column
// and update item column
for ( std : : vector < std : : string > : : const_iterator ivs = item . Fields [ column ] . begin ( ) ; ivs ! = item . Fields [ column ] . end ( ) ; + + ivs )
{
ilk = _Indices [ column ] . find ( * ivs ) ;
if ( ( ilk = = _Indices [ column ] . end ( ) ) | | ( getRow ( ( * ilk ) . second ) . Fields [ nameColumn ] [ 0 ] ! = item . Fields [ nameColumn ] [ 0 ] ) )
{
_Indices [ column ] . insert ( make_pair ( * ivs , index ) ) ;
_Items [ index ] . Fields [ column ] . push_back ( * ivs ) ;
}
}
return true ;
}
else
{
addItem ( item ) ;
return false ;
}
}
/**
* Update a row ( found by the first column , which must have exactly one element ) .
* Returns true if it existed before , false if it ' s being created .
* If it existed before :
* - Does not update lookup maps or item for columns that were already present .
* - Adds entries in lookup maps and updates item for new columns ( fields that were empty ) .
*/
/*bool updateItemAppend( const TSortableItem& item )
{
if ( ! _Enabled )
return true ; // quiet
CLookup : : iterator ilk = _Indices [ 0 ] . find ( item . Fields [ 0 ] [ 0 ] ) ;
if ( ilk ! = _Indices [ 0 ] . end ( ) )
{
uint32 & index = ( * ilk ) . second ;
for ( uint32 c = 1 ; c ! = NC ; + + c )
{
// Update maps for previously empty columns
if ( _Items [ index ] . Fields [ c ] . empty ( ) )
{
for ( std : : vector < std : : string > : : iterator ivs = item . Fields [ c ] . begin ( ) ; ivs ! = item . Fields [ c ] . end ( ) ; + + ivs )
_Indices [ c ] . insert ( make_pair ( * ivs , index ) ) ;
}
// Update item column
_Items [ index ] . Fields [ c ] = item . Fields [ c ] ;
}
return true ;
}
else
{
addItem ( item ) ;
return false ;
}
} */
/// Find or browse by key
CLookup & lookup ( uint32 column )
{
return _Indices [ column ] ;
}
/// Browse by adding order
CItems & items ( )
{
return _Items ;
}
/// Get a row by index
TSortableItem & getRow ( uint32 index )
{
return _Items [ index ] ;
}
private :
CLookup _Indices [ NC ] ;
CItems _Items ;
bool _Enabled ;
} ;
typedef CSortableData < DtNbCols > CRMData ;
typedef CRMData : : TSortableItem TRMItem ;
/**
*
*/
class CProducedDocHtml
{
public :
///
CProducedDocHtml ( ) : _File ( NULL ) , _Enabled ( false ) { }
///
void open ( const std : : string & filename , const std : : string & title , bool enableFlag )
{
_Enabled = enableFlag ;
if ( ! _Enabled )
return ;
_File = fopen ( filename . c_str ( ) , " wt " ) ;
fprintf ( _File , ( " <html><head> \n <meta http-equiv= \" content-type \" content= \" text/html; charset=UTF-8 \" > \n <title> " + title + " </title> \n </head><body> \n " ) . c_str ( ) ) ;
}
///
void write ( const std : : string & htmlCode )
{
if ( ! _Enabled )
return ;
fprintf ( _File , htmlCode . c_str ( ) ) ;
}
///
void writeln ( const std : : string & htmlCode )
{
write ( htmlCode + " \n " ) ;
}
///
void writebln ( const std : : string & htmlCode )
{
write ( htmlCode + " <br> \n " ) ;
}
///
void writepln ( const std : : string & htmlCode )
{
write ( " <p> " + htmlCode + " </p> \n " ) ;
}
///
void save ( )
{
if ( ! _Enabled )
return ;
fprintf ( _File , " </body></html> \n " ) ;
fclose ( _File ) ;
}
private :
FILE * _File ;
bool _Enabled ;
} ;
/**
*
*/
class CProducedDocCSV
{
public :
///
CProducedDocCSV ( ) : _File ( NULL ) , _Enabled ( false ) { }
///
void open ( const std : : string & filename , bool enableFlag )
{
_Enabled = enableFlag ;
if ( ! _Enabled )
return ;
_File = fopen ( filename . c_str ( ) , " wt " ) ;
}
///
void write ( const std : : string & data )
{
if ( ! _Enabled )
return ;
fprintf ( _File , data . c_str ( ) ) ;
}
///
void writeln ( const std : : string & data )
{
write ( data + " \n " ) ;
}
///
void save ( )
{
if ( ! _Enabled )
return ;
fclose ( _File ) ;
}
private :
FILE * _File ;
bool _Enabled ;
} ;
/**
*
*/
class CGenRawMaterial
{
public :
/// Constructor
CGenRawMaterial ( const std : : string & sheetName = std : : string ( ) ) : SheetName ( sheetName ) , ILocation ( ~ 0 ) , IFamily ( ~ 0 ) , IEcosystem ( NbEcosystems ) , StatQuality ( InvalidStatQuality ) , Color ( InvalidColor ) , StatEnergyAvg ( 0 )
{ }
/// Serial
void serial ( NLMISC : : IStream & s )
{
s . serial ( SheetName ) ;
s . serial ( ( uint32 & ) ILocation ) ;
s . serial ( ( uint32 & ) IFamily ) ;
s . serial ( ( uint32 & ) Group ) ;
s . serial ( ( uint32 & ) IEcosystem ) ;
s . serial ( ( uint32 & ) StatQuality ) ;
s . serial ( ( sint32 & ) Color ) ;
//s.serial( (uint32&)SapLoadLevel );
//s.serial( (uint32&)Rarity );
s . serial ( ( sint32 & ) StatEnergyAvg ) ;
s . serial ( ( uint32 & ) MaxLevel ) ;
s . serialCont ( RMProperties ) ;
s . serialCont ( IPropertyDepths ) ;
s . serialCont ( RMCraftCharacs ) ;
}
/// Computes randomly RMCraftCharacs, IPropertyDepths... Returns false if the RM must NOT be generated.
bool computeCraftCharacs ( uint iVariant , const CSString & sheetName ) ;
///
void writeSheet ( CForm * form ) ;
///
void loadSheet ( CForm * form , const std : : string & sheetName , bool full ) ;
///
void collectStats ( TRMItem & item , CMainStat & mainStats ) ;
/// Return average of energies (including max quality as half of the balance)
/*float getEnergyAvg() const
{
if ( RMCraftCharacs . empty ( ) )
return 0.0f ;
else
{
float sum = 0.0f ;
for ( list < CFaberCharacteristics > : : const_iterator ics = RMCraftCharacs . begin ( ) ; ics ! = RMCraftCharacs . end ( ) ; + + ics )
{
sum + = ( * ics ) . ActualEnergy ;
}
//return (sum + (float)MaxQuality / 250.0f) / ((float)RMCraftCharacs.size() + 1);
return ( sum / ( float ) RMCraftCharacs . size ( ) ) ; // now, MaxQuality is not part of the average
}
} */
///
float getOriginalityAvg ( ) const
{
float sum = 0.0f ;
for ( list < CFaberCharacteristics > : : const_iterator ics = RMCraftCharacs . begin ( ) ; ics ! = RMCraftCharacs . end ( ) ; + + ics )
{
sum + = ( * ics ) . ActualOriginality ;
}
return sum / ( float ) RMCraftCharacs . size ( ) ;
}
///
float getOriginalityMax ( ) const
{
float maxOriginality = 0.0f ;
for ( list < CFaberCharacteristics > : : const_iterator ics = RMCraftCharacs . begin ( ) ; ics ! = RMCraftCharacs . end ( ) ; + + ics )
{
if ( ( * ics ) . ActualOriginality > maxOriginality )
maxOriginality = ( * ics ) . ActualOriginality ;
}
return maxOriginality ;
}
///
void fillPropertiesFromFamily ( )
{
vs & props = FamSet [ familyStr ( ) ] . Properties ;
RMProperties . resize ( props . size ( ) ) ;
for ( vs : : iterator ip = props . begin ( ) ; ip ! = props . end ( ) ; + + ip )
{
RMProperties [ ip - props . begin ( ) ] = getIndexFromString ( * ip , properties ) ;
}
}
///
bool hasCraftPart ( uint craftPartIndex )
{
return CraftParts . isEnabled ( craftPartIndex ) & & ( FamSet [ familyStr ( ) ] . CompatibleCraftParts . find ( string ( 1 , ( char ) ' A ' + craftPartIndex ) . c_str ( ) ) ! = string : : npos ) ;
}
///
/*TCiv getCivSpec( uint craftPartIndex, const TFamInfo& famInfo )
{
TCiv civ = NbCiv ;
for ( vector < TCiv > : : const_iterator ivc = famInfo . Civs . begin ( ) ; ivc ! = famInfo . Civs . end ( ) ; + + ivc )
{
// Skip those not matching the current rFaberElem
if ( famInfo . getCraftPartForProp ( ivc - famInfo . Civs . begin ( ) ) . find ( string ( 1 , ( char ) ( ' A ' + craftPartIndex ) ) . c_str ( ) ) ! = string : : npos )
{
if ( ( civ ! = NbCiv ) & & ( ( * ivc ) ! = civ ) )
{
nlwarning ( " Different civ specializations for %s, %s (%s and %s) " , familyStr ( ) . c_str ( ) , getShortFaberElemString ( craftPartIndex ) . c_str ( ) , CivNames [ civ ] , CivNames [ * ivc ] ) ;
return AllCiv ;
}
civ = ( * ivc ) ;
}
}
if ( civ = = NbCiv )
return AllCiv ;
else if ( civ =
return civ ;
} */
///
TCiv getCivSpec ( TEcosystem iEcosystem , TStatQuality statQuality )
{
if ( ( statQuality < = Fine ) | | ( iEcosystem > = NbEcosystems ) )
return AllCiv ;
else
return EcosystemToCiv [ iEcosystem ] ;
}
///
/*TCiv getMainCivSpec( const TFamInfo& famInfo )
{
TCiv civ = NbCiv ;
for ( list < CFaberCharacteristics > : : const_iterator ics = RMCraftCharacs . begin ( ) ; ics ! = RMCraftCharacs . end ( ) ; + + ics )
{
TCiv civOfCraftPart = getCivSpec ( ( * ics ) . FaberElement , famInfo ) ;
if ( ( civ ! = NbCiv ) & & ( civOfCraftPart ! = civ ) )
{
return AllCiv ;
}
civ = civOfCraftPart ;
}
if ( civ = = NbCiv )
return AllCiv ;
else
return civ ;
} */
///
/*const char * getMainEcosystemSpec( const TFamInfo& famInfo )
{
return CivEcosystemCodes [ getMainCivSpec ( famInfo ) ] ;
} */
/// Code
CSString SheetName ;
/// Index in locations
uint32 ILocation ;
/// Index in families
uint32 IFamily ;
///
CSString familyStr ( ) const { return families [ IFamily ] ; }
/// Group number
TGroup Group ;
///
CSString groupStr ( ) const { return Group = = ~ 0 ? " " : groups [ Group ] ; }
/// Index in ecosystems
TEcosystem IEcosystem ;
///
CSString ecosystemStr ( ) const { return ecosystems [ IEcosystem ] ; }
/// From Basic) to Supreme)
TStatQuality StatQuality ;
/// From 'b' (Basic) to 'f' (Supreme)
char levelZoneLChar ( ) const { return ' b ' + ( char ) StatQuality ; }
/// Same
void setStatQuality ( char levelZoneChar ) { StatQuality = ( TStatQuality ) ( levelZoneChar - ' b ' ) ; }
/// For creatures
uint32 ILevelZone ;
/// Index in colors
TColor Color ;
///
CSString colorStr ( ) const { return colors [ Color ] ; }
/// Sap load level
//uint32 SapLoadLevel;
/// Rarity
//uint32 Rarity;
sint32 StatEnergyAvg ;
/// Max quality
uint32 MaxLevel ;
/// Indices in properties
vu RMProperties ;
///
CSString propertyStr ( uint32 p ) const { return properties [ RMProperties [ p ] ] ; }
///
vu IPropertyDepths ;
///
CSString propertyDepthStr ( uint32 p ) const { return PropertyDepths [ IPropertyDepths [ p ] ] ; }
///
CFaberCharacteristics * getCraftSlot ( uint rFaberElem )
{
std : : list < CFaberCharacteristics > : : iterator icl ;
for ( icl = RMCraftCharacs . begin ( ) ; icl ! = RMCraftCharacs . end ( ) ; + + icl )
{
if ( ( * icl ) . FaberElement = = rFaberElem )
return & ( * icl ) ;
}
return NULL ;
}
/// Randomly generated characs
std : : list < CFaberCharacteristics > RMCraftCharacs ;
} ;
/**
*
*/
class COriginalitySorter
{
public :
typedef std : : set < CGenRawMaterial * > CRMSet ;
typedef std : : multimap < uint32 , CGenRawMaterial * , std : : greater < uint32 > > CMultiMapByOriginality ;
///
COriginalitySorter ( ) : RMByOriginalityByCraftSlot ( NbFaberElements ) { }
///
void pushRM ( CGenRawMaterial * rawMaterial )
{
RawMaterials . insert ( rawMaterial ) ;
//InfoLog->displayRawNL( "Inserting RM" );
std : : list < CFaberCharacteristics > : : const_iterator ilc ;
for ( ilc = rawMaterial - > RMCraftCharacs . begin ( ) ; ilc ! = rawMaterial - > RMCraftCharacs . end ( ) ; + + ilc )
{
//InfoLog->displayRawNL( " %u: %s orig=%u", (*ilc).FaberElement, rawMaterial->SheetName.c_str(), (uint32)((*ilc).ActualOriginality*100.0f) );
RMByOriginalityByCraftSlot [ ( * ilc ) . FaberElement ] . insert ( make_pair ( ( uint32 ) ( ( * ilc ) . ActualOriginality * 100.0f ) , rawMaterial ) ) ;
}
}
///
void popAndDeleteRM ( CGenRawMaterial * rawMaterial )
{
delete rawMaterial ;
RawMaterials . erase ( rawMaterial ) ;
}
///
bool alreadyPopped ( CGenRawMaterial * rawMaterial ) const
{
return RawMaterials . find ( rawMaterial ) = = RawMaterials . end ( ) ;
}
/// fromPos and the returned iterator are the pos internal to the COriginalitySorter RM set
/*CRMSet::const_iterator getFirstRMNotInFamilyListFromPos( const set<uint>& familyList, TStatQuality statQuality, CRMSet::const_iterator fromPos ) const
{
CRMSet : : const_iterator irm ;
for ( irm = fromPos ; irm ! = RawMaterials . end ( ) ; + + irm )
{
if ( ( ( * irm ) - > StatQuality = = statQuality ) & &
( familyList . find ( ( * irm ) - > IFamily ) = = familyList . end ( ) ) )
return irm ;
}
return RawMaterials . end ( ) ;
} */
///
CRMSet : : iterator getRMSetBegin ( ) const { return RawMaterials . begin ( ) ; }
///
CRMSet : : iterator getRMSetEnd ( ) const { return RawMaterials . end ( ) ; }
///
void deleteAllRemainingRM ( )
{
CRMSet : : iterator irm ;
for ( irm = RawMaterials . begin ( ) ; irm ! = RawMaterials . end ( ) ; + + irm )
{
delete ( * irm ) ;
}
RawMaterials . clear ( ) ;
// Does not clear the maps by originality
}
std : : vector < CMultiMapByOriginality > RMByOriginalityByCraftSlot ;
private :
CRMSet RawMaterials ;
} ;
# define checkColor( c ) nlassert( colors[c] == #c );
/*
*
*/
void loadDFNs ( UFormLoader * formLoader )
{
map < string , CDfnFieldInfo > dfnFields ;
NLMISC : : CSmartPtr < UFormDfn > formDfn ;
formDfn = formLoader - > loadFormDfn ( ( rmSheetType + " .dfn " ) . c_str ( ) ) ;
if ( ! formDfn )
nlerror ( " Can't find DFN for %s " , rmSheetType . c_str ( ) ) ;
vector < string > craftPartsPaths ;
fillFromDFN ( formLoader , dfnFields , formDfn , " " , rmSheetType , " mp.MpParam " , craftPartsPaths ) ;
// Get craft parts
CraftParts . getNamesAndPaths ( craftPartsPaths ) ;
formDfn = formLoader - > loadFormDfn ( ( crSheetType + " .dfn " ) . c_str ( ) ) ;
if ( ! formDfn )
nlerror ( " Can't find DFN for %s " , crSheetType . c_str ( ) ) ;
fillFromDFN ( formLoader , dfnFields , formDfn , " " , crSheetType ) ;
// Get lists of predefined values from sitem and creature DFN
families = dfnFields [ " mp.Family " ] . TypePredefinedLabels ;
familyCodes = dfnFields [ " mp.Family " ] . TypePredefinedValues ;
groups = dfnFields [ " mp.Group " ] . TypePredefinedLabels ;
//properties = dfnFields["mp.Material property 1"].TypePredefinedLabels;
//nlverify( removeEntryFromList( properties, "Undefined" ) != ~0 );
properties . resize ( craftPartsPaths . size ( ) ) ;
for ( uint i = 0 ; i ! = properties . size ( ) ; + + i ) // now, use properties as item part list
properties [ i ] = string ( 1 , ( char ) ( ' A ' + i ) ) ;
ecosystems = dfnFields [ " mp.Ecosystem " ] . TypePredefinedLabels ,
colors = dfnFields [ " mp.MpColor " ] . TypePredefinedLabels ,
creatures = dfnFields [ " Basics.Race " ] . TypePredefinedLabels ;
seasons . push_back ( " Winter " ) ;
seasons . push_back ( " Spring " ) ;
seasons . push_back ( " Summer " ) ;
seasons . push_back ( " Autumn " ) ;
//removeEntryFromList( families, "Undefined" );
//removeEntryFromList( familyCodes, "0" );
nlverify ( removeEntryFromList ( ecosystems , " unknown " ) ! = ~ 0 ) ;
nlverify ( removeEntryFromList ( ecosystems , " Goo " ) ! = ~ 0 ) ;
nlassert ( ecosystems [ 0 ] = = " Common " ) ;
nlassert ( ecosystems [ 1 ] = = " Desert " ) ; // ensure we match with enum TEcosystem!
nlassert ( ecosystems [ 2 ] = = " Forest " ) ;
nlassert ( ecosystems [ 3 ] = = " Lacustre " ) ;
nlassert ( ecosystems [ 4 ] = = " Jungle " ) ;
nlassert ( ecosystems [ 5 ] = = " PrimeRoots " ) ;
//removeEntryFromList( ecosystems, "Common" ); // TODO
nlassert ( NbEcosystems = = ecosystems . size ( ) ) ;
nlverify ( removeEntryFromList ( colors , " None " ) ! = ~ 0 ) ;
nlverify ( removeEntryFromList ( colors , " UserColor " ) ! = ~ 0 ) ;
nlassert ( colors . size ( ) = = NbColors ) ;
checkColor ( Red ) ;
checkColor ( Beige ) ;
checkColor ( Green ) ;
checkColor ( Turquoise ) ;
checkColor ( Blue ) ;
checkColor ( Violet ) ;
checkColor ( White ) ;
checkColor ( Black ) ;
/*UndefinedProperty = getIndexFromString( "Undefined", properties );
nlassert ( UndefinedProperty ! = ~ 0 ) ; */
}
/*
* Build RMFamilyIndicesByCreatureModel and DepositFamilyIndices
*/
void dispatchFamiliesToLocations ( )
{
for ( CFamMap : : iterator iss = FamSet . begin ( ) ; iss ! = FamSet . end ( ) ; + + iss )
{
const CSString & famStr = ( * iss ) . first ;
TFamInfo & famInfo = ( * iss ) . second ;
uint iFam = getIndexFromString ( famStr , families ) ;
if ( famInfo . IsInDeposits )
{
// Deposits
nlassert ( iFam ! = ~ 0 ) ;
DepositFamilyIndices . push_back ( iFam ) ;
}
if ( famInfo . IsInCreatures )
{
// Extract creature name from left of family name (ASSUMES there's no blank in creature name)
CSString creaNameForRMFamily = famStr . splitTo ( ' ' ) ;
// Dispatch
for ( CSkeletonMap : : iterator icm = CreatureModels . begin ( ) ; icm ! = CreatureModels . end ( ) ; + + icm )
{
const CSString & creaModel = ( * icm ) . first ;
TSkeletonInfo & modelInfo = ( * icm ) . second ;
if ( modelInfo . Name = = creaNameForRMFamily )
{
RMFamilyIndicesByCreatureModel [ creaModel ] . push_back ( iFam ) ;
//nlinfo( "+ %s for %s (now %u models registered)", famStr.c_str(), creaModel.c_str(), RMFamilyIndicesByCreatureModel.size() );
modelInfo . IsUsed = true ; // Name and AbbrevName are set by deliverCreatureModels()
}
}
}
else switch ( famInfo . SpecialCreatureTag [ 0 ] )
{
// Goo & invasion/raid creatures
case ' G ' :
{
GooCreatureFamilyIndices . push_back ( iFam ) ;
nldebug ( " Family %s selected for goo creatures " , famStr . c_str ( ) ) ;
break ;
}
case ' I ' :
{
if ( famInfo . SpecialCreatureTag . size ( ) = = 1 )
{
InvasionRaidCreatureFamilyIndices [ ' * ' ] . push_back ( iFam ) ;
nldebug ( " Family %s selected for all invasion creatures " , famStr . c_str ( ) ) ;
}
else
{
for ( uint c = 1 ; c ! = famInfo . SpecialCreatureTag . size ( ) ; + + c )
{
InvasionRaidCreatureFamilyIndices [ famInfo . SpecialCreatureTag [ c ] ] . push_back ( iFam ) ;
nldebug ( " Family %s selected for invasion creature of type %c " , famStr . c_str ( ) , famInfo . SpecialCreatureTag [ c ] ) ;
}
}
break ;
}
}
}
}
/*
* Returns the number of models used
*/
uint checkSkeletons ( )
{
uint32 nbSkeUsed = 0 ;
for ( CSkeletonMap : : const_iterator isc = CreatureModels . begin ( ) ; isc ! = CreatureModels . end ( ) ; + + isc )
{
const string & skeFilename = ( * isc ) . first ;
const TSkeletonInfo & ske = ( * isc ) . second ;
const bool & used = ( * isc ) . second . IsUsed ;
if ( used )
{
nldebug ( " Model %s (%s) %s " , skeFilename . c_str ( ) , ske . AbbrevName . c_str ( ) , used ? " used " : " NOT USED " ) ;
+ + nbSkeUsed ;
}
else
nlwarning ( " Model %s %s " , skeFilename . c_str ( ) , used ? " " : " NOT USED " ) ;
}
return nbSkeUsed ;
}
/*
*
*/
void createDirectoryStructure ( )
{
// Create the directory structure
if ( WriteSheetsToDisk )
{
for ( uint32 i = 0 ; i ! = ecosystems . size ( ) ; + + i )
{
string dirname = conventionalDirectory ( ecosystems [ i ] ) ;
if ( ! CFile : : isExists ( rawMaterialPath + dirname ) )
{
CFile : : createDirectory ( rawMaterialPath + dirname ) ;
}
else
{
if ( ! CFile : : isDirectory ( rawMaterialPath + dirname ) )
{
nlwarning ( " %s already existing but not a directory! " , ( rawMaterialPath + dirname ) . c_str ( ) ) ;
}
}
}
string dirname = " _parent " ;
if ( ! CFile : : isExists ( rawMaterialPath + dirname ) )
{
CFile : : createDirectory ( rawMaterialPath + dirname ) ;
}
else
{
if ( ! CFile : : isDirectory ( rawMaterialPath + dirname ) )
{
nlwarning ( " %s already existing but not a directory! " , ( rawMaterialPath + dirname ) . c_str ( ) ) ;
}
}
}
}
# endif // NL_SRG_UTILITIES_H
/* End of srg_utilities.h */