Unofficial Patch for 3.19

Commending out the call means the function won't be profiled (timed) during Debug builds. It doesn't affect gameplay, only speed when debugging. It may have been disabled because the function runs too quickly to matter, but I haven't looked at the code.
 
Yeah, what EF said. I try to keep the debug profiling/timing setup consistent between this and BBAI so that they're easier to compare, I've commented out the tracking of a couple functions and added new ones to better understand where computation time is being spent.

No gameplay effect what so ever, in a Final_Release build PROFILE_FUNC() is completely ignored.
 
It looks like there's a bug if you enable the canFoundCitiesOnWater Python callback. The function checks first for various things that would allow you to found on a plot. At the end it checks if the callback is enabled. However, it checks the result outside of the test to see if the callback is enabled, using the result from the cannotFound callback above. Also, it ignores whether or not the plot is water if the callback says, "Yes, you can found on water." This means you can found on non-water invalid plots if your mod allows founding on water.

This part of the code is really, really messed up. Here's the fixed code:

Code:
	if (!bValid)
	{
		if (GC.getTerrainInfo(pPlot->getTerrainType()).isFoundFreshWater())
		{
			if (pPlot->isFreshWater())
			{
				bValid = true;
			}
		}
	}

[B]// BUG - Unofficial Patch - start
	// EF: canFoundCitiesOnWater callback handling was incorrect and ignored isWater() if it returned true
	if (!bValid && pPlot->isWater())
	{
		if(GC.getUSE_CAN_FOUND_CITIES_ON_WATER_CALLBACK())
		{
			CyArgsList argsList2;
			argsList2.add(iX);
			argsList2.add(iY);
			lResult=0;
			gDLL->getPythonIFace()->callFunction(PYGameModule, "canFoundCitiesOnWater", argsList2.makeFunctionArgs(), &lResult);

			if (lResult == 1)
			{
				bValid = true;
			}
		}
	}
// BUG - Unofficial Patch - start[/B]

	if (!bValid)
	{
		return false;
	}

If the initial checks before isWater() determine that the plot is valid, this code will not override that. I assume the checks above only pass if the plot is not water. However, if that's not the case it can be rewritten slightly:

Code:
// BUG - Unofficial Patch - start
	// EF: canFoundCitiesOnWater callback handling was incorrect and ignored isWater() if it returned true
	[B]if (pPlot->isWater())[/B]
	{
		[B]bValid = false;[/B]
		
		if(GC.getUSE_CAN_FOUND_CITIES_ON_WATER_CALLBACK())
		{
			CyArgsList argsList2;
			argsList2.add(iX);
			argsList2.add(iY);
			lResult=0;
			gDLL->getPythonIFace()->callFunction(PYGameModule, "canFoundCitiesOnWater", argsList2.makeFunctionArgs(), &lResult);

			if (lResult == 1)
			{
				bValid = true;
			}
		}
	}
// BUG - Unofficial Patch - start

This is probably safer.
 
CvPlot::doFeature()
CvPlot::doImprovement

It seems that forest growing probability doesn't be affected by game speed (At least, I can't find such codes).
Discovering new resource is too.

How do you think about this?
 
CvCity.cpp

Code:
/*************************************************************************************************/
/** UNOFFICIAL_PATCH                       09/17/09                  davidlallen & jdog5000      */
/**                                                                                              */
/** Bugfix				                                                                         */
/*************************************************************************************************/
/* original bts code
			if (GET_PLAYER(getOwnerINLINE()).isBuildingClassMaxedOut(((BuildingClassTypes)(GC.getBuildingInfo(eConstructBuilding).getBuildingClassType())), 1))
*/
			if (GET_PLAYER(getOwnerINLINE()).isBuildingClassMaxedOut(((BuildingClassTypes)(GC.getBuildingInfo(eConstructBuilding).getBuildingClassType())), 0))
/*************************************************************************************************/
/** UNOFFICIAL_PATCH                        END                                                  */
/*************************************************************************************************/


That change is a mistake,like build "palace",it can't remove original capital's "palace"。
 
CvPlot::doFeature()
CvPlot::doImprovement

It seems that forest growing probability doesn't be affected by game speed (At least, I can't find such codes).
Discovering new resource is too.

How do you think about this?

You are correct, there is no game speed modification for forest/jungle growth. But what modifier would make sense? Using any of the existing ones in GameSpeedInfo would be using something "off label" (not what it was intended for), so is it worth creating a new tag for this?
 
I see two that stand out to me:

  • getFeatureProductionPercent() - Forest chop :hammers:?
  • getImprovementPercent() - Improvement build speed (amount of work to build it)?
To determine whether or not a new percent value is required, one option is to equalize the :hammers:/time where time of course varies with game speed.

I play Epic exclusively, but let's pull some numbers out of the air. Marathon has three times as many turns as Normal. And a chop on Marathon produces 60 :hammers: compared to Normal's 20 :hammers:. Assuming a Forest growth chance of 1% per turn for both speeds, that gives

20 :hammers: x 1% x 3 Normal-turns/Marathon-turn = 0.6 :hammers:/Marathon-turn​

and

60 :hammers: x 1% = 0.6 :hammers:/Marathon-turn​

Ah, so decreasing the growth chance for slower game speeds would result in fewer :hammers:/turn at those speeds. This of course doesn't factor in Jungles, and it means that Forests are seen as "larger" at slower speeds. They require the same number of normalized-turns to chop yet yield more :hammers.

As well, since the growth chance is checked each turn the growth rate will actually be higher (once normalized) at slower speeds. The chance that a forest doesn't grow in a 3 turn period (equivalent to 1 turn at Normal) is 99% x 99% x 99% which is less than 99%, the chance a Forest doesn't grow at Normal speed.

I would almost prefer to have seen faster regrowth with the same :hammers: output at slower speeds, but that would be far to aggressive a change at this stage.

Again, all my numbers are from memory or imagination. If they differ from reality, please correct my calculations.
 
If you're going to take a look at forest growth and game speed, I think it would be a good idea to revisit the AI's random decisions and gamespeed as well. Because of the AI's use of the RNG for deciding if it goes to war, and when to bother the human for requests, the diplomacy of different game speeds is drastically different. These RNG based decisions should also scale with gamespeed for consistency.
 
I think my equations were backwards. The higher number of turns at slower speeds combines with the higher :hammers: output at those same speeds to significantly increase the :hammers:/year at slower speeds. This assumes that at Marathon you get more :hammers:/chop.

To equalize the :hammers:/year you'd need to decrease the growth rate at slower speeds. Now that I reread your post, jdog5000, it looks like that's what your equation does.
 
But what modifier would make sense? Using any of the existing ones in GameSpeedInfo would be using something "off label" (not what it was intended for), so is it worth creating a new tag for this?

Hmmmm.
I had not reached that difficult problem when posting.

I believe that growing probability at 1 normal-turn should be as same as 3 Marathon-turns.
(3 is Marathon-FeatureProductionPercent / 100)

Given that 1 Marathon-turn growing probability is a, 1 Marathon-turn NOT growing probability is (1-a).
Then 3 Marathon-turns NOT growing probability is (1-a)^3.
If my belief is true, 1 normal-turn NOT growing probability should be (1-a)^3 too.

For example, given 1 normal-turn growing probability is 20%, 1 Marathon-turn growing probability is...

1 - 0.2 = 0.8

(1-a)^3 = 0.8
(1-a) = 0.8 ^ (1/3)
(1-a) = 0.92831776672255577848201527018396...
a = 1 - 0.92831776672255577848201527018396...
a = 0.071682233277444221517984729816042...

About 7.168%.

Is this true probability?
I fell into confusion.:sad:

EDIT: This logic doesn't work when normal-growing probability is 100%, sorry.
 
The AI evaluates Civic penalties to health (and I assume happiness as well) as bonuses. To test change the <iExtraHealth> tag of a civic, load up a game and in debug mode press ctrl to see the AI's weight for that civic. You'll see that the AI evaluates a 2 the same as a -2, and thus making a civic produce unhealthiness causes an AI preference to switch to that civic.

This bug was found in RevolutionDCM, but I assume this is a BtS issue, and thus requires a UP fix.
 
While trying to help Afforess with some building happiness/health features I noticed a couple bugs in CvCity. The first half of the function is fine; all you need to notice is the name of the function:

Code:
void CvCity::setBuilding[B]Health[/B]Change(BuildingClassTypes eBuildingClass, int iChange)
{
	for (BuildingChangeArray::iterator it = m_aBuildingHealthChange.begin(); it != m_aBuildingHealthChange.end(); ++it)
	{
		if ((*it).first == eBuildingClass)
		{
			if ((*it).second != iChange)
			{
				if ((*it).second > 0)
				{
					changeBuildingGoodHealth(-(*it).second);
				}
				else if ((*it).second < 0)
				{
					changeBuildingBadHealth((*it).second);
				}

				if (iChange == 0)
				{
					m_aBuildingHealthChange.erase(it);
				}
				else
				{
					(*it).second = iChange;
				}

				if (iChange > 0)
				{
					changeBuildingGoodHealth(iChange);
				}
				else if (iChange < 0)
				{
					changeBuildingBadHealth(-iChange);
				}
			}

			return;
		}
	}

But if the building isn't found in the list yet, it is appended to it. That's fine, but check out the two function calls after that's done:

Code:
	if (0 != iChange)
	{
		m_aBuildingHealthChange.push_back(std::make_pair(eBuildingClass, iChange));

		if (iChange > 0)
		{
			changeBuildingGood[B]Happiness[/B](iChange);
		}
		else if (iChange < 0)
		{
			changeBuildingGood[B]Happiness[/B](-iChange);
		}
	}
}

Um, WTF? :lol: I believe these should be changed to match the code just above:

Code:
		if (iChange > 0)
		{
			changeBuildingGood[B]Health[/B](iChange);
		}
		else if (iChange < 0)
		{
			changeBuilding[B]BadHealth[/B](-iChange);
		}

Now that I take in the full function, I think the first part is broken, too, along with the happiness version. This function sets the extra health for a given building class, but it calls changeBuildingGood/BadHealth() without first checking if the city even has the building class.

As it's only called in applyEvent() and acquireCity(), it works unless the building that received the extra health from an event is destroyed during conquest.
 
It's there any way you guys can make the AI not building so many caravels...?
 
It's there any way you guys can make the AI not building so many caravels...?

Unless this behavior is caused by a bug, I think a fix like this is more appropriate for Better BTS AI.
 
Top Bottom