Heya dear civ4 modders,
lately i have been developing a new-old civic dependency system.
f1rpo0 has been helping me and directing me, but i have decided to put it here to get more help/opinions.
maybe vene some modders would like to use this as well later on.
key description of my system:
a civic can have children civics, aka Dependent civics
here there are 2 civics to choose from in one civic option that are both children civics for the Parent civic (civic option 0).
ill talk about AI logic, as the human is easier.
AI will "
check if a civic is a parent ->
evaluate the parent value + evaluate all the dependencies that belong to it.from the 4 dependent civics above , it will take one civic from the 2 civic options.
meaning the total value of the tested civic will be :
parent + child 1 or 2 + child 3 or 4.
after that, it will choose the best parent out of all the parents in the civic 0 option.
once the code reaches to perform revolution,
another function will take the list of civics the ai picked,
and for the parent that is in that list - the code will force replace the children civic options 1 + 2 --> to the best children civics that are dependent on this parent.
it will replace the civics that got picked for civic option 1+2 in the normal per civic evaluation in vanilla code.
here are the functions i wrote:
CvPlayerAI::AI_civicValue (original function was renamed to AI_civicValue_original
CivicMap CvPlayerAI::forceChildCivics --> very similar code to the civicvalue, with different return
CvPlayer::getCivicParent
CvPlayerAI::CvPlayerAI(
CvPlayerAI::AI_uninit()
CvPlayerAI::AI_reset
CvPlayerAI::AI_doCivics()
I would love to hear ways to improve this code and make it better.
my logic is probably not well design in terms of code.
so please help out with any ideas or code changes
this is the civic screen i did to display the civic 0 (goverment ) and its 2 civic options dependents.
lately i have been developing a new-old civic dependency system.
f1rpo0 has been helping me and directing me, but i have decided to put it here to get more help/opinions.
maybe vene some modders would like to use this as well later on.
key description of my system:
a civic can have children civics, aka Dependent civics
Code:
<CivicChild>
<CivicTypes>CIVIC_R1</CivicTypes> (civic option 1)
<CivicTypes>CIVIC_R2</CivicTypes> (civic option 1)
<CivicTypes>CIVIC_ANARCHIZEM</CivicTypes> (civic option 2)
<CivicTypes>CIVIC_TRADITIONAL</CivicTypes> (civic option 2)
</CivicChild>
here there are 2 civics to choose from in one civic option that are both children civics for the Parent civic (civic option 0).
ill talk about AI logic, as the human is easier.
AI will "
check if a civic is a parent ->
evaluate the parent value + evaluate all the dependencies that belong to it.from the 4 dependent civics above , it will take one civic from the 2 civic options.
meaning the total value of the tested civic will be :
parent + child 1 or 2 + child 3 or 4.
after that, it will choose the best parent out of all the parents in the civic 0 option.
once the code reaches to perform revolution,
another function will take the list of civics the ai picked,
and for the parent that is in that list - the code will force replace the children civic options 1 + 2 --> to the best children civics that are dependent on this parent.
it will replace the civics that got picked for civic option 1+2 in the normal per civic evaluation in vanilla code.
here are the functions i wrote:
CvPlayerAI::AI_civicValue (original function was renamed to AI_civicValue_original
Spoiler :
Code:
/* doto Civics Dependency (Asaf) - start )
hi jack of AI_civicValue original fn.
this will value a parent civic with its best children dependant civics.
if its not a parent civic, normal value will be returned e,g AI_civicValue AI_civicValueParent
*/
int CvPlayerAI::AI_civicValue(CivicTypes eCivic) const
{
PROFILE_FUNC();
CivicTypes eParent = getCivicParent(eCivic);
int eBestChild = 0;
if (eParent != NO_CIVIC)
{
CvCivicInfo kCivic = GC.getCivicInfo(eParent);
int childrenCivics = kCivic.getNumParentCivicsChildren();
int eTotalCivicChildrenValue = 0; //should be one per civ option
if (childrenCivics > 0) //gotta be above 0 cause of getCivicParent call above
{
//evaluate all childcivics and save their values
//this should save some loops below.
int* m_atemp = new int[childrenCivics];
for (int i = 0; i < childrenCivics; i++)
{
m_atemp[i] = AI_civicValue_original(kCivic.getParentCivicsChildren(i));
}
int eTotalValueOfChildrenBestCivics = 0; //total dependant children 1, per civic option for a parent civic.
///this should be saved in the playerai cache so it will know
//to which dependant civics the revolution should take place
//once a parent was deemed worthi for revolution.
//placed here for now for codde example
//ArrayEnumMap<CivicOptionTypes,CivicTypes> m_aChildCivicsToAutoSwitch; // advc.130w
//for every civicoption - lets find the best child civic with the better value
for (int i = 0; i < GC.getNumCivicOptionInfos(); i++)
{
int eTempBestCivicChildOption = 0;
for (int J = 0; J < childrenCivics; J++)
{
CivicTypes childCivicType = kCivic.getParentCivicsChildren(J);
if (GC.getInfo(childCivicType).getCivicOptionType() == (CivicOptionTypes)i)
{
//if another civic child belongs to the same civic option
if (m_atemp[J] > eTempBestCivicChildOption)
{
// save the value -> if there is more childs to this civic option
eTempBestCivicChildOption = m_atemp[J];
//m_aChildCivicsToAutoSwitch.set((CivicOptionTypes)i, childCivicType); // see above comment
m_aChildCivicsToAutoSwitch[(CivicOptionTypes)i] = childCivicType;
}
}
}
// the best civic's value that was found for a civic option
eTotalValueOfChildrenBestCivics += eTempBestCivicChildOption;
}
SAFE_DELETE_ARRAY(m_atemp);
return AI_civicValue_original(eParent) + eTotalValueOfChildrenBestCivics;
}
}
return AI_civicValue_original(eCivic); //normal civic value calc.
}
/* doto Civics Dependency (Asaf) - end ) */
CivicMap CvPlayerAI::forceChildCivics --> very similar code to the civicvalue, with different return
Spoiler :
Code:
CivicMap CvPlayerAI::forceChildCivics(CivicMap ePreRevolutionMap) const;
{
PROFILE_FUNC();
FOR_EACH_ENUM(CivicOption)
{
CivicTypes eCivicePreRevolutionMap.get(eLoopCivicOption) //get the civic for the itered c option
CivicTypes eParent = getCivicParent(eCivic); //check if the civic is a parent
int eBestChild = 0;
if (eParent != NO_CIVIC)
{
//since this is a parent civic
//the code below, will find its children
// best children for each civic option that the children belongs to
// and it will update the ePreRevolutionMap with the best children.
//this will ensure that if a parent civic was chosen, it will force select its
// dependant children, and will switch from current none dependant children
CvCivicInfo kCivic = GC.getCivicInfo(eParent);
int childrenCivics = kCivic.getNumParentCivicsChildren();
if (childrenCivics > 0) //gotta be above 0 cause of getCivicParent call above
{
//evaluate all childcivics and save their values
//this should save some loops below.
int* m_atemp = new int[childrenCivics];
for (int i = 0; i < childrenCivics; i++)
{
m_atemp[i] = AI_civicValue_original(kCivic.getParentCivicsChildren(i));
}
//for every civicoption - lets find the best child civic with the better value
for (int i = 0; i < GC.getNumCivicOptionInfos(); i++)
{
int eTempBestCivicChildOption = 0;
for (int J = 0; J < childrenCivics; J++)
{
CivicTypes childCivicType = kCivic.getParentCivicsChildren(J);
if (GC.getInfo(childCivicType).getCivicOptionType() == (CivicOptionTypes)i)
{
//if another civic child belongs to the same civic option
if (m_atemp[J] > eTempBestCivicChildOption)
{
// save the value -> if there is more childs to this civic option
eTempBestCivicChildOption = m_atemp[J];
ePreRevolutionMap.set((CivicOptionTypes)i, childCivicType);
}
}
}
}
}
}
}
return ePreRevolutionMap;
}
CvPlayer::getCivicParent
Spoiler :
Code:
/* Civics Dependency (Asaf) - start */
CivicTypes CvPlayer::getCivicParent(CivicTypes eCivic) const
{
if (GC.getCivicInfo(eCivic).getNumParentCivicsChildren() > 0)
return eCivic; // if the same civic is a parent
for (int iI = 0; iI < GC.getNumCivicInfos(); ++iI)
{
int childrenCivics = GC.getCivicInfo((CivicTypes)iI).getNumParentCivicsChildren();
if (childrenCivics > 0)
{
for (int J = 0; J < childrenCivics; J++)
{
if ((CivicTypes)J == eCivic)
return (CivicTypes)iI; //return the parent of the child civic
}
}
}
return NO_CIVIC; //the civic is not a parent nor a child
}
/* Civics Dependency (Asaf) - End */
CvPlayerAI::CvPlayerAI(
Spoiler :
Code:
/* doto Civics Dependency (Asaf) - Start */
m_aChildCivicsToAutoSwitch = new int[GC.getNumCivicOptionInfos()];;
for (int i = 0; i < GC.getNumCivicOptionInfos(); i++)
{
m_aChildCivicsToAutoSwitch[i] = -1;
}
/* doto Civics Dependency (Asaf) - end */
CvPlayerAI::AI_uninit()
Spoiler :
Code:
/* doto Civics Dependency (Asaf) - Start */
SAFE_DELETE_ARRAY(m_aChildCivicsToAutoSwitch);
/* doto Civics Dependency (Asaf) - end */
CvPlayerAI::AI_reset
Spoiler :
Code:
/* doto Civics Dependency (Asaf) - Start */
//FAssert(m_aChildCivicsToAutoSwitch == NULL);
m_aChildCivicsToAutoSwitch = new int[GC.getNumCivicOptionInfos()];
for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
{
m_aChildCivicsToAutoSwitch[iI] = -1;
}
/* doto Civics Dependency (Asaf) - end */
CvPlayerAI::AI_doCivics()
Spoiler :
Code:
/* doto Civics Dependency (Asaf) - Start */
// get the civics with forced children
aeBestCivic_updated = forceChildCivics(aeBestCivic);
/* doto Civics Dependency (Asaf) - end */
I would love to hear ways to improve this code and make it better.
my logic is probably not well design in terms of code.
so please help out with any ideas or code changes
this is the civic screen i did to display the civic 0 (goverment ) and its 2 civic options dependents.