Advanced Civ

Humm, interesting and odd.
In my savegame, i did not see the ai that had the error under a vassal agreement.
I was able to replicate the issue when i moved all troops out of the city and back in .
Eventually i just had an if statement which makes the change value to 0 if the current military happiness is 0 and the change value passed is -1.
Silly but...
I 9nly saw the military happiness changes on setxy. I have not checked where are all the calls for it.
 
Is the city's military happiness value correct when you load your savegame, i.e. when you set a breakpoint toward the end of CvCity::read and compare that value with the units you see on the map once loading is complete? It could be that the value has already been incorrect for many turns (but above 0 and therefore not causing the assertion to fail). If the value after loading is correct and it only becomes incorrect in between turns and no vassal agreements are being signed/canceled, then there must indeed be another problem. Or if the city owner has obviously never been a vassal and has never had a vassal.
 
im not sure,
i did repeat the action a few times and the numbers are consistent when in and out.
AFAIK its a percentage that's drawn from the units? not the abstract numbers of 10 units = 10 happiness.

ill continue to look. there could be the option that the value was wrong for turns before that.

--
ok->
19 units in the city.
happiness is 13 > 10

when i take all the units out of the city -> the assert pops.
then happiness is: 13 < 19
(by the way - why does the message say in the city hover : : "The military presence make us nervous"
should it say - the city is defenseless / not defended enough?)
19 units total -> ratio of happiness 1:2 -> e.g 9 unhappiness when taking them out of the city and back. the numbers are constant when bringing them back to the city.
very odd, even when i take one unit out of the city -> the assert pops. how can the city unhappiness be 0 if there are 18 units in it?
--
it looks like the m_iMilitaryHappinessUnits is set to 0 in the city while the units are inside.
what could have been executing that made the city ignore all the units in it from the happiness?
i added this one now from youradditions:

if( m_iMilitaryHappinessUnits == 0 && iChange < 0)
updateMilitaryHappinessUnits();

in CvCity::changeMilitaryHappinessUnits(int iChange)
ok that fixed the numbers....now i see that NO Military Happiness was taken from the units.
so this update i added is like a self correction,

i will run a few tests of ai to see if i get to the break point once more.
that will say if some problem still exists.
very puzzling.. a hidden error somewhere that resets the unit count .

--
maybe it was the vassal ->
i found in the uwau400.log : T5(Justinia) is a vassal
(the error was with justinian),
but, then again....more civs has the entry.
 
Last edited:
maybe it was the vassal ->
i found in the uwau400.log : T5(Justinia) is a vassal
(the error was with justinian),
but, then again....more civs has the entry.
Well, a vassal agreement would only affect the happy-unit count if units of the master are in a city of the vassal – or units of the vassal in a city of the master – at the time that the agreement is signed or canceled. So this should be a rare problem. If Justinian peace-vassals and already has OB with the master before that, then a large stack of the master could happen to be in one of Justinian's cities at that time. Those units won't get counted as happy units because the vassal agreement wasn't in place when they entered the city. But, opon leaving, the happy-unit count will be decreased. If Justinian himself has a large garrison, it won't decrease enough to become negative, but, once Justinian moves part of the garrison, the assertion will fail. Something like this could perhaps explain the numbers you were seeing.
(by the way - why does the message say in the city hover : : "The military presence make us nervous"
should it say - the city is defenseless / not defended enough?)
I think Firaxis created that text in case that a mod lets military units cause unhappiness instead of happiness (through Civ4CivicInfos.xml). m_iMilitaryHappinessUnits is never supposed to be negative either way, so no UI support should be needed for this case.
i added this one now from youradditions:

if( m_iMilitaryHappinessUnits == 0 && iChange < 0)
updateMilitaryHappinessUnits();

in CvCity::changeMilitaryHappinessUnits(int iChange)
ok that fixed the numbers....now i see that NO Military Happiness was taken from the units.
so this update i added is like a self correction,
Sure, adding something like this temporarily should repair your savegame. Could also do it once for all cities of all players at the end CvGame:: onAllGameDataRead to ensure that no inconsistencies exist in other cities. (Again, only as a temporary measure for your ongoing game.)
 
Thanks buddy,
After all the changes,i dont see it no more.

@f1rpo
I decided i dont like how no brainer it is for the ai to use the range atrack i added in.
Also its basically similar to vanilla ranged and any other implementation done in the various mods.

I took ai_anyattack content and i want it to provide the score, odds per plot.
I pushed the ranged fn the odds threshold and min stack.

Why do i babble you ask?
I got to this fn, std:min(currstep(), 2) something which requires the "it' from the loop.
Since my loop is external, what does the it means?
I tried pushing plot, &plot, *plot, plot*
But it says that fun is not of cvplot which i know.

Im also thinking about using some of the airstrike plot assesment for score.

Thanks and sorry for the hijack here.
 
I've given the plot iterators some distance functions because an iterator can potentially calculate distances faster with the help of its internal state. But, in the case of step distance, the plot iterators just call the global stepDistance function: PlotRadiusIterator.h#L56'

So, if you have a CvPlot p and a CvUnit u, you'll probably want to call ::stepDistance(p, u.getPot()) or something like that.
 
well thank you buddy,
i did this:
for (SquareIter itInner(pp, std::min(::stepDistance(pp.getX(), pp.getY(), getPlot().getX(), getPlot().getY()),2), false);

had issues with converting const plot and such.

BTW what is the diff between ::stepDistance(p, u.getPot()) to stepDistance(p, u.getPot()) ?
 
That looks like it should work. The issue was more likely rather with pointers vs. references. I use references instead of pointers as much as possible (to make clear that NULL is not a possible value), and I've changed a fair portion of the original code in that style, but the stepDistance function still takes pointer arguments. ::stepDistance(&pp, plot()) should work. Edit: Actually, even stepDistance(CvPlot*, CvPlot*) was only added by K-Mod; BtS had only the clunky stepDistance(int, int, int, int), i.e. based on coordinates.

The :: explicitly says that the called function is in the global namespace. That can be necessary when there is e.g. a member function of the same name. In this case, I only use it for the reader's information; maybe I shouldn't since the function is pretty frequently used across the codebase and the :: adds clutter. I have actually turned stepDistance and plotDistance into members of CvMap, but decided to keep the global functions as wrappers because calling getMap everytime is too cumbersome.
 
Last edited:
cool, now its clearer for me.

ok heres an odd thing,
5 units of the attacker, 4 ranged attacker, enemy defend in a city with horses.
AI_getWeightedOdds calc for a catapult->

iAttackOddsChange = 9
int const iAttackOddsChange = GET_PLAYER(getOwner()).AI_getAttackOddsChange();
iOdds -= iAttackOddsChange;
iOdds = -10
int iAdjustedOdds = pAttacker->AI_opportuneOdds(iOdds, *pDefender);
iAdjustedOdds = -15
iAdjustedOdds += iAttackOddsChange; // advc.114b
return range(-6, 1, 99); >>> return 1.

why does the return is 1 or -6 ?
because the horse has a strength of 12 + in a city and the catapult of 5?

maybe i should enable this for ranged attackers as well?
if (getDomainType() == DOMAIN_SEA && !hasCargo())
{
// I'm sorry about this. I really am. I'll try to make it better one day...
int iDefenders = pAttacker->AI_countEnemyDefenders(*pPlot);
iAdjustedOdds *= 2 + getNumUnits();
iAdjustedOdds /= 3 + std::min(iDefenders / 2, getNumUnits());
}

e.g -> if the ranged attack attacks with a stack, add to it maybe?

what do you think anout using ->
AI_localDefenceStrength
vs
AI_localAttackStrength
for ranged units?
 
Not sure how specific this is to AdvCiv. Well, maybe an assertion of iOdds being nonnegative should be added in AdvCiv. Because it sounds like iOdds was -1 before (temporarily) subtracting iAttackOddsChange, and I don't think that's supposed to happen. Here's the start of the function in question, for reference:
Spoiler :
Code:
int CvSelectionGroupAI::AI_getWeightedOdds(CvPlot const* pPlot, bool bPotentialEnemy)
{
	PROFILE_FUNC();
	int iOdds=-1;
	CvUnitAI const* pAttacker = AI_getBestGroupAttacker(pPlot, bPotentialEnemy, iOdds);
	if (pAttacker == NULL)
		return 0;
Looking at AI_getBestGroupAttacker, I don't see how an attacker can be found and yet no sensible attack odds. I'd suggest investigating how this happens. If it's an issue that only arises from additions related to ranged attacks, then I'd rather discuss that in a private convo. Well, for such technical details, that'll probably be better in any case.
 
I've found a small issue regarding the recent change to combined master-vassal culture garrison strength [change id advc.184].

In a vassal's city, only the master's units seem to contribute to the defense against third party revolts. This is the case for both voluntary and capitulated vassals. For AI vassals to a human player anyway -- I've not checked if the same happens in the AI-AI case. I've also not checked if there are any issues in the reverse situation, i.e in the master's cities.
 
Having only reviewed the code, I think you're correct. Thanks, a difficult thing to spot in the game. It checks
Code:
kCityTeam.getMasterTeam() == getTeam() // city's master team equal to unit's team
|| kCityTeam.getID() == GET_TEAM(getTeam()).getMasterTeam() // or city's team equal to unit's master team
currently. I guess it really has to check
Code:
|| kCityTeam.getID() == getTeam() // or city's team equal to unit's team
additionally. Seems that there should be a simpler way, considering that a nonvassal team is its own master, but I guess three separate clauses are really the only way to stop vassals of the same master from aiding each other as well. Not that no such thing ever happened historically (the suppression of the Prague Spring comes to mind), but, well, probably still more intuitive not to allow that. Edit: Chat AI says my program logic looks legit. So there's that at least.

I've been meaning to post an update (just bugfixes; current Git change history) before the fall, so I'll try to do that by the end of the month.
 
Last edited:
Is it possible to fully revert the Hereditary Rule change, i.e. disable +25% happiness from luxuries?

Also, I've noticed that with the mod, I can't switch from one advisor window to another through function keys anymore (function keys only open their advisor window if another advisor window isn't open). Is this BUG-related, and is there a way to change it?
 
Setting these
Code:
			<!-- advc.912c: No change here, but now interpreted as happiness
				 per every two military units. -->
			<iHappyPerMilitaryUnit>1</iHappyPerMilitaryUnit>
			<!-- advc.912c -->
			<iLuxuryModifier>25</iLuxuryModifier>
in Assets\XML\GameInfo\Civ4CivicInfos.xml to 2 amd 0 respectively should do the trick, in theory.

The function keys work correctly in BULL, so this is probably something I or karadoc, more likely I, have changed inadvertently. Not sure if there's a systematic way to debug this. I'll see what I can do.

Already the end of August ... I'll try the first half of September as my new self-imposed due date for updating the mod.
 
f1rpo
I'm playing your excellent mod again after a break, as I often do. I'm playing deity level again, as I usually do. You know, I was finally able to win on a huge earth map on deity level as the Romans after I built the pyramids a few months ago. But I had to do everything perfect (with a lot of save scumming).
Anyway, I built the pyramids as China on a huge world map today, and as always, was doing just fine. Then, even though my relations with Asoka were excellent, I was attacked by Asoka. Even though I defeated his army, he refused to declare peace. Then Mehmed, who I also had excellent relations with, piled on. Yes, I am much weaker than Asoka, but our relations were excellent. I know that Asoka shares borders with others who are much weaker than me.
Regardless, I would like to ask you this. Are there any hml files from your mod that deal with such matters that I could easily switch out with vanilla files in order to see if I can get different results? My games with AdvCiv on deity have always gone like this for years now, so I would just like to see if I can find any way to make the AI relations slightly more doable at this deity level. But I still want to use all of your other wonder AI improvements. And I remember that we discussed this already not too long ago and that you said that you didn't think these really difficult relations and dogpiling were due to any changes that you had made. But I'd just like to give it a shot and see. So any ideas on file switching out would be much appreciated. Thanks.
 
I only meant to say that I didn't consciously program the AI to have a bias against humans on the highest difficulty levels. I think it's quite likely that the BtS/ K-Mod AI would've acted differently in the examples you've given. Defeating their invading army will usually cause the BtS and K-Mod AI to make peace; K-Mod especially may soon declare war again, however. And BtS/ K-Mod Ashoka should pretty much never declare war when Pleased.

There is the Legacy AI game option, which mostly just affects AI decisions on war and peace. This can even be toggled mid-game (well, not while the game is running; will then need to save, exit, make the XML changes, restart and reload) through UWAI_IN_BACKGROUND or DISABLE_UWAI in GlobalDefines_devel.xml. Though I haven't been testing those XML settings in a while. The game option I have still run a game on AI Auto Play with before the larger of the latest updates, keeping an eye out for egregious behavior. You may also want to set USE_KMOD_AI_NONAGGRESSIVE in GlobalDefines_advc.xml. Short of disabling the AdvCiv war and peace code entirely, it can also be tweaked through AI_Variables-Global_Defines.xml – but one would probably have to look at some log files (REPORT_INTERVAL, UWAI_REPORT_THRESH in GlobalDefines_devel.xml) to be able to make effective adjustments.

Managed to fix this btw:
I can't switch from one advisor window to another through function keys anymore [...]
Will be included in AdvCiv 1.11 ... soon.
 
OK, I fibbed. Asoka wasn't actually Pleased with me when he declared war. He was three positive with one negative, which means he was Cautious.

Thanks. I'll try using both of your suggestions above.

It seems pretty clear and I think I understand, but to be sure: the Legacy AI is the more aggressive KMod and uses the KMod war and peace modifiers. The KMod AI Non-Aggressive in Global Defines is less aggressive KMod and uses KMod war and peace modifiers. Yet neither of the these two methods disables the AdvCiv war and peace modifiers entirely.

If you can confirm that I am correct in my understanding, I would appreciate it. If so, both methods sound great to me, and over time I will try them both. I will get back to you eventually and let you know what I discovered. Thanks again!
 
Back
Top Bottom