Beta version of 2.7

Am I missing something here or is the above code nonsensical? I don't see any other variables being read in this manner.

That code is garbage; a cluster of memory leaks, buffer overflows and access violations. I would be surprised if that code was not causing crashes.

At a glance - and without actually testing - I suspect the intended meaning is something like this:

Code:
int iJ;
pStream->Read(&iJ);
if (iJ > 0)
{
	m_paiCondemnCivicCount = new int*[iJ];
	for (int iI = 0; iI < iJ; ++iI)
	{
		int iK;
		pStream->Read(&iK);
		if (iK > 0)
		{
			m_paiCondemnCivicCount[iI] = new int[iK];
			pStream->Read(iK, m_paiCondemnCivicCount[iI]);
		}
		else
		{
			m_paiCondemnCivicCount[iI] = NULL;
		}
	}
}
else
{
	m_paiCondemnCivicCount = NULL;
}

I would have to look at the surrounding code to be sure though. However, given the poor quality of that code snippet, I would be wary of any code from the same source.
 
I would be surprised if that code was not causing crashes.

OK. Thanks for the confirmation. I think that I will try to change it to use the same coding format as the forceCivic vote tag

Code:
pStream->Read(GC.getNumCivicInfos(), m_paiForceCivicCount);

If any coders feel like taking a stab at it, feel free to do so! Here is the issue I wrote up for it - https://bitbucket.org/Tholal/more-naval-ai/issues/74/update-condemncivic-code-to-match

Along those same lines, I figured out which vote tags weren't configured to be council specific and wrote up an issue for that as well - https://bitbucket.org/Tholal/more-naval-ai/issues/71/many-vote-tags-do-not-check-for-council
 
About half an hour ago I got a warning from Windows 10 saying that it needed to close Civilization 4 to prevent the loss of data because I was running out of RAM.

I have 8gb of ram on the laptop and thought using all of that up seemed unlikely, so I checked Resource Manager. It did not show much ram associated with the Civ4 program, but showed more than 4gb of memory in the "modified" category ("memory whose contents must be written to disk before ti can be used for another purpose") even after closing Civ4, until I restarted the whole computer.

I'm no expert on the matter, but I think what we had was a serious memory leak.


The save I made just before closing the program again caused a crash, as did all the previous saves from that game.


This was with a test version of my modmod were I had deleted the troublesome fixed borders resolution in hopes that this would solve the problem. (I do like the idea of such a resolution, but not the the current implementation which makes it impossible for cities founded or captured late in the game to expand their culture at all to access resources.)


I just now downloaded the debug DLL to see if it helps identify issues.

The debug DLL seems way slower, so I hope we fix the problems and get a new regular dll soon.

When first opening the program to start a new game I got this message:
Code:
Assert Failed

File:  CvXMLLoadUtilitySet.cpp
Line:  1688
Expression:  bSuccess
Message:

I got this message right after converting religion:

Code:
Assert Failed

File:  CvCity.cpp
Line:  11771
Expression:  getFreeBonus(eIndex) >= 0
Message:  

----------------------------------------------------------

Note that in my modmod, converting religions switches out dummy buildings that add or subtract mana types assocated with or opposed to that faith.

Also note that this is in an advanced start game, before existing advanced start. (I'm playing as the Ljosalfar and chose to convert to FoL through the popup as soon as it was founded. It it weren't my leader's favorite religion it would not get founded until after starting the game so I wouldn't have that option.)

I got this message after accidentally pressing the advanced start Build Improvement (Automated) button:

Code:
Assert Failed

File:  CvInfos.cpp
Line:  6322
Expression:  i > -1
Message:  Index out of bounds

----------------------------------------------------------

At the end of my first turn I get this (3 times):

Code:
Assert Failed

File:  CvCity.cpp
Line:  1510
Expression:  isNoBonus((BonusTypes)iI) || getNumBonuses((BonusTypes)iI) >= ((isConnectedToCapital()) ? (GET_PLAYER(getOwnerINLINE()).getBonusImport((BonusTypes)iI) - GET_PLAYER(getOwnerINLINE()).getBonusExport((BonusTypes)iI)) : 0)
Message:  

----------------------------------------------------------
and then this (too many times to count):
Code:
Assert Failed

File:  CvInfos.cpp
Line:  6322
Expression:  i > -1
Message:  Index out of bounds

----------------------------------------------------------

ad then this (twice):
Code:
Assert Failed

File:  CvPlayerAI.cpp
Line:  8365
Expression:  ePlayer != getID()
Message:  shouldn't call this function on ourselves

----------------------------------------------------------

I've gotten a few of those again, plus these:
Code:
Assert Failed

File:  CvCity.cpp
Line:  7711
Expression:  getBonusGoodHealth() >= 0
Message:  

----------------------------------------------------------
Code:
Assert Failed

File:  CvCity.cpp
Line:  7713
Expression:  getBonusGoodHealth() >= 0
Message:  getBonusGoodHealth is expected to be >= 0

----------------------------------------------------------
Code:
Assert Failed

File:  CvArtFileMgr.cpp
Line:  182
Expression:  false
Message:  get##name##ArtInfo:  was not found

----------------------------------------------------------
Code:
Assert Failed

File:  CvCity.cpp
Line:  8286
Expression:  getBonusGoodHappiness() >= 0
Message:  

----------------------------------------------------------
Code:
Assert Failed

File:  CvCity.cpp
Line:  8298
Expression:  getBonusBadHappiness() <= 0
Message:  

----------------------------------------------------------

selecting a unit in worldbuilder results in this:
Code:
Assert Failed

File:  CvSelectionGroup.cpp
Line:  1050
Expression:  false
Message:  

----------------------------------------------------------
 
I'm no expert on the matter, but I think what we had was a serious memory leak.

I think that is tied to the Condemn Civic code which is also the source of the save game corruption.

The debug DLL seems way slower, so I hope we fix the problems and get a new regular dll soon.

It is much slower. I'm planning on releasing a new beta version once I get the savegame issues sorted.

When first opening the program to start a new game I got this message:
Code:
Assert Failed

File:  CvXMLLoadUtilitySet.cpp
Line:  1688
Expression:  bSuccess
Message:

This one is specific to your mod. My guess would be that you have some comments in the XML somewhere that the engine doesn't like

I got this message right after converting religion:
Code:
Assert Failed

File:  CvCity.cpp
Line:  11771
Expression:  getFreeBonus(eIndex) >= 0
Message:

Note that in my modmod, converting religions switches out dummy buildings that add or subtract mana types assocated with or opposed to that faith.

This also seems to be mod-specific. Most likely related to your mana buildings. Looks like you are setting the FreeBonus to a negative value which is not expected.


I got this message after accidentally pressing the advanced start Build Improvement (Automated) button:

Code:
Assert Failed

File:  CvInfos.cpp
Line:  6322
Expression:  i > -1
Message:  Index out of bounds

I'll have to check on this. That assert error is happening in getFreePromotions() which doesnt make much sense from the context.


Code:
Assert Failed

File:  CvCity.cpp
Line:  1510
Expression:  isNoBonus((BonusTypes)iI) || getNumBonuses((BonusTypes)iI) >= ((isConnectedToCapital()) ? (GET_PLAYER(getOwnerINLINE()).getBonusImport((BonusTypes)iI) - GET_PLAYER(getOwnerINLINE()).getBonusExport((BonusTypes)iI)) : 0)
Message:

Specific to your mod as well. Again, likely due to those mana buildings. If you want to post the python code related to these I can take a look at it.

and then this (too many times to count):
Code:
Assert Failed

File:  CvInfos.cpp
Line:  6322
Expression:  i > -1
Message:  Index out of bounds

This is the getFreePromotions() code again. Are you making calls to this function from python?

ad then this (twice):
Code:
Assert Failed

File:  CvPlayerAI.cpp
Line:  8365
Expression:  ePlayer != getID()
Message:  shouldn't call this function on ourselves

I've seen this one. Related to new Advanced Diplomacy code. I'll sort this out.

I've gotten a few of those again, plus these:
Code:
Assert Failed

File:  CvCity.cpp
Line:  7711
Expression:  getBonusGoodHealth() >= 0
Message:
Code:
Assert Failed

File:  CvCity.cpp
Line:  7713
Expression:  getBonusGoodHealth() >= 0
Message:  getBonusGoodHealth is expected to be >= 0

Code:
Assert Failed

File:  CvCity.cpp
Line:  8286
Expression:  getBonusGoodHappiness() >= 0
Message:
Code:
Assert Failed

File:  CvCity.cpp
Line:  8298
Expression:  getBonusBadHappiness() <= 0
Message:

I've seen these before but never been able to track down the root cause of how this city bonuses get out of sync. It's in my bug list

Code:
Assert Failed

File:  CvArtFileMgr.cpp
Line:  182
Expression:  false
Message:  get##name##ArtInfo:  was not found

Haven't seen this one. Likely related to something new in your mod.

selecting a unit in worldbuilder results in this:
Code:
Assert Failed

File:  CvSelectionGroup.cpp
Line:  1050
Expression:  false
Message:

That error is in the canStartMission() function. I wasn't able to replicate. What exactly do you mean by "selecting a unit in worldbuilder"? Are you trying to edit a unit?

Thanks for the reports!
 
This one is specific to your mod. My guess would be that you have some comments in the XML somewhere that the engine doesn't like

I do use comments to help organize some xml files. I guess I could delete them if necessary.
This also seems to be mod-specific. Most likely related to your mana buildings. Looks like you are setting the FreeBonus to a negative value which is not expected.

Each religion has 2 dummy buildings. One adds +1 of the associated mana. The other 'adds' -2 of the opposite sphere.

I would prefer to make it only -1, but the code still treats that as equivalent to +3.

(I'd really like it if a single building could add or subtract different numbers of different resources.)

Specific to your mod as well. Again, likely due to those mana buildings. If you want to post the python code related to these I can take a look at it.

Spoiler :
Code:
	def onPlayerChangeStateReligion(self, argsList):
	## Platy Builder ##
		if CyGame().GetWorldBuilderMode() and not CvPlatyBuilderScreen.bPython: return
	## Platy Builder ##
		'Player changes his state religion'
		iPlayer, iNewReligion, iOldReligion = argsList
		if iNewReligion != iOldReligion:
			pPlayer = gc.getPlayer(iPlayer)
			iOrder = gc.getInfoTypeForString('RELIGION_THE_ORDER')
			iEmpyrean = gc.getInfoTypeForString('RELIGION_THE_EMPYREAN')
			iRunes = gc.getInfoTypeForString('RELIGION_RUNES_OF_KILMORPH')
			iLeaves = gc.getInfoTypeForString('RELIGION_FELLOWSHIP_OF_LEAVES')
			iOverlords = gc.getInfoTypeForString('RELIGION_OCTOPUS_OVERLORDS')
			iEsus = gc.getInfoTypeForString('RELIGION_COUNCIL_OF_ESUS')
			iVeil = gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL')
			iDragonCult = gc.getInfoTypeForString('RELIGION_CULT_OF_THE_DRAGON')
			iHand = gc.getInfoTypeForString('RELIGION_WHITE_HAND')
			iOne = gc.getInfoTypeForString('RELIGION_CHILDREN_OF_THE_ONE')
			if iNewReligion != -1:
				iLeader = pPlayer.getLeaderType()
				iCiv = pPlayer.getCivilizationType()
				if gc.getLeaderHeadInfo(iLeader).getReligionWeightModifier(iNewReligion) < -99:
					pPlayer.setLastStateReligion(iOldReligion)
					iNewReligion = iOldReligion
					pPlayer.changeAnarchyTurns(-pPlayer.getAnarchyTurns())
				if iCiv == gc.getInfoTypeForString('CIVILIZATION_GRIGORI'):
					pPlayer.setAlignment(gc.getInfoTypeForString('ALIGNMENT_NEUTRAL'))
					pPlayer.setLastStateReligion(-1)
					iNewReligion = -1
					pPlayer.changeAnarchyTurns(-pPlayer.getAnarchyTurns())
				elif iNewReligion == iDragonCult:
					if not pPlayer.isBarbarian():
						pPlayer.setLastStateReligion(iOldReligion)
						iNewReligion = iOldReligion
						pPlayer.changeAnarchyTurns(-pPlayer.getAnarchyTurns())
				elif iNewReligion == iOne:
					pPlayer.setLastStateReligion(iOldReligion)
					iNewReligion = iOldReligion
					pPlayer.changeAnarchyTurns(-1)
				elif iNewReligion == iEmpyrean:
					if iCiv == gc.getInfoTypeForString('CIVILIZATION_CALABIM') or iLeader in [gc.getInfoTypeForString('LEADER_ALEXIS'), gc.getInfoTypeForString('LEADER_FLAUROS'), gc.getInfoTypeForString('LEADER_MAHON')]:
						pPlayer.setLastStateReligion(iOldReligion)
						iNewReligion = iOldReligion
						pPlayer.changeAnarchyTurns(-pPlayer.getAnarchyTurns())


				if iNewReligion != iHand and iLeader in [gc.getInfoTypeForString('LEADER_AURIC'), gc.getInfoTypeForString('LEADER_ANAGANTIOS'), gc.getInfoTypeForString('LEADER_DUMANNIOS'), gc.getInfoTypeForString('LEADER_RIUROS')]:
					pPlayer.setLastStateReligion(-1)
					iNewReligion = -1

				if gc.getGame().getProjectCreatedCount(gc.getInfoTypeForString('PROJECT_THE_DRAW')) > 0:
					iAuricPlayer = cf.getLeader(gc.getInfoTypeForString('LEADER_AURIC'))
					if iAuricPlayer != -1:
						pAuricPlayer = gc.getPlayer(iAuricPlayer)
						if pAuricPlayer.getUnitClassCount(gc.getInfoTypeForString('UNITCLASS_AURIC')) > 0:
							iAuricTeam = pAuricPlayer.getTeam()

							if iNewReligion == iHand:
								eAuricTeam = gc.getTeam(iAuricTeam)
								iTeam = pPlayer.getTeam()
								if eAuricTeam.isAtWar(iTeam):
									pPlayer.setLastStateReligion(iOldReligion)
									pPlayer.changeAnarchyTurns(-pPlayer.getAnarchyTurns())

							elif gc.getTeam(pPlayer.getTeam()).isVassal(iAuricTeam):
								pPlayer.setLastStateReligion(iHand)
								iNewReligion = iHand

			if iNewReligion != iOldReligion:
				pCapital = pPlayer.getCapitalCity()
				if not pCapital.isNone():
					listReligiousMana = [	(gc.getInfoTypeForString('RELIGION_THE_ORDER'),
								gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_ORDER'),
				 				gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_ORDER')),

								(gc.getInfoTypeForString('RELIGION_THE_EMPYREAN'),
								gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_EMPYREAN'),
								gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_EMPYREAN')),

								(gc.getInfoTypeForString('RELIGION_RUNES_OF_KILMORPH'),
								gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_KILMORPH'),
								gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_KILMORPH')),

								(gc.getInfoTypeForString('RELIGION_FELLOWSHIP_OF_LEAVES'),
								gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_LEAVES'),
								gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_LEAVES')),

								(gc.getInfoTypeForString('RELIGION_OCTOPUS_OVERLORDS'),
								gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_OVERLORDS'),
								gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_OVERLORDS')),

								(gc.getInfoTypeForString('RELIGION_COUNCIL_OF_ESUS'),
								gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_ESUS'),
								gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_ESUS')),

								(gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'),
								gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_ASHEN'),
								gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_ASHEN')),

								(gc.getInfoTypeForString('RELIGION_WHITE_HAND'),
								gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_HAND'),
								gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_HAND'))
						]
					for iReligion, iManaPlus, iManaMinus in listReligiousMana:
						pCapital.setNumRealBuilding(iManaPlus, iNewReligion == iReligion)
						pCapital.setNumRealBuilding(iManaMinus, iNewReligion == iReligion)

			if iNewReligion == -1:
				iCurrentEra = pPlayer.getCurrentEra()
				iEra = iCurrentEra
				if iCurrentEra in [gc.getInfoTypeForString('ERA_ANCIENT'), gc.getInfoTypeForString('ERA_CLASSICAL'), gc.getInfoTypeForString('ERA_MEDIEVAL')]:
					iEra = gc.getGame().getStartEra()
					pPlayer.setCurrentEra(iEra)
			elif iNewReligion == iOrder:
				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_ORDE'))
				pPlayer.setAlignment(gc.getInfoTypeForString('ALIGNMENT_GOOD'))
			elif iNewReligion == iEmpyrean:
				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_EMPY'))
			elif iNewReligion == iRunes:
				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_RUNE'))
			elif iNewReligion == iLeaves:
				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_LEAF'))
			elif iNewReligion == iOverlords:
				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_OCTO'))
			elif iNewReligion == iEsus:
				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_COUN'))
			elif iNewReligion == iVeil:
				pPlayer.setCurrentEra(gc.getInfoTypeForString('ERA_VEIL'))
				pPlayer.setAlignment(gc.getInfoTypeForString('ALIGNMENT_EVIL'))
Code:
	def onCityBuilt(self, argsList):
		'City Built'
		city = argsList[0]
		pPlot = city.plot()
		iPlayer = city.getOwner()
		pPlayer = gc.getPlayer(iPlayer)
		iCiv = pPlayer.getCivilizationType()

		if city.isCapital():
			iStateReligion = pPlayer.getStateReligion()
			if iStateReligion != -1:
				listReligiousMana = [	(gc.getInfoTypeForString('RELIGION_THE_ORDER'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_ORDER'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_ORDER')),

							(gc.getInfoTypeForString('RELIGION_THE_EMPYREAN'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_EMPYREAN'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_EMPYREAN')),

							(gc.getInfoTypeForString('RELIGION_RUNES_OF_KILMORPH'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_KILMORPH'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_KILMORPH')),

							(gc.getInfoTypeForString('RELIGION_FELLOWSHIP_OF_LEAVES'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_LEAVES'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_LEAVES')),

							(gc.getInfoTypeForString('RELIGION_OCTOPUS_OVERLORDS'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_OVERLORDS'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_OVERLORDS')),

							(gc.getInfoTypeForString('RELIGION_COUNCIL_OF_ESUS'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_ESUS'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_ESUS')),

							(gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_ASHEN'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_ASHEN')),

							(gc.getInfoTypeForString('RELIGION_WHITE_HAND'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_HAND'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_HAND'))

							]

				for iReligion, iManaPlus, iManaMinus in listReligiousMana:
					city.setNumRealBuilding(iManaPlus, iStateReligion == iReligion)
					city.setNumRealBuilding(iManaMinus, iStateReligion == iReligion)

Code:
	def onCityAcquired(self, argsList):
	## Platy Builder ##
		if CyGame().GetWorldBuilderMode() and not CvPlatyBuilderScreen.bPython: return
	## Platy Builder ##
		'City Acquired'
		iPreviousOwner,iNewOwner,pCity,bConquest,bTrade = argsList
		pPlayer = gc.getPlayer(iNewOwner)
		pPrevious = gc.getPlayer(iPreviousOwner)
		pOriginal = gc.getPlayer(pCity.getOriginalOwner())

		iCiv = pPlayer.getCivilizationType()
		iInfernal = gc.getInfoTypeForString('CIVILIZATION_INFERNAL')
		iMercurians = gc.getInfoTypeForString('CIVILIZATION_MERCURIANS')
		iVeil = gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL')
		iOverlords = gc.getInfoTypeForString('RELIGION_OCTOPUS_OVERLORDS')
		if iCiv == iInfernal:
			cf.removeReligion(gc.getInfoTypeForString('RELIGION_THE_ORDER'), pCity)
			cf.removeReligion(gc.getInfoTypeForString('RELIGION_THE_EMPYREAN'), pCity)
			pCity.setHasReligion(gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'), True, True, True)
			pCity.setNumRealBuilding(gc.getInfoTypeForString('BUILDING_DEMONIC_CITIZENS'), 1)

			if pCity.getCivilizationType() == iMercurians:
				pCity.setCivilizationType(iInfernal)
				CyInterface().setDirty(InterfaceDirtyBits.CityInfo_DIRTY_BIT, True)

		else:
			pCity.setNumRealBuilding(gc.getInfoTypeForString('BUILDING_DEMONIC_CITIZENS'), 0)
			if iCiv == iMercurians:
				cf.removeReligion(iVeil, pCity)
				cf.removeReligion(iOverlords, pCity)
				if pCity.getCivilizationType() == iInfernal:
					pCity.setCivilizationType(iMercurians)
					CyInterface().setDirty(InterfaceDirtyBits.CityInfo_DIRTY_BIT, True)

			elif iCiv == gc.getInfoTypeForString('CIVILIZATION_KHAZAD'):
				pCity.setNumRealBuilding(gc.getInfoTypeForString('BUILDING_DWARVEN_VAULT'), 1)
				cf.doTurnKhazad(iNewOwner)

		if pCity.isCapital():
			iStateReligion = pPlayer.getStateReligion()
			if iStateReligion != -1:
				listReligiousMana = [	(gc.getInfoTypeForString('RELIGION_THE_ORDER'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_ORDER'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_ORDER')),

							(gc.getInfoTypeForString('RELIGION_THE_EMPYREAN'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_EMPYREAN'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_EMPYREAN')),

							(gc.getInfoTypeForString('RELIGION_RUNES_OF_KILMORPH'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_KILMORPH'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_KILMORPH')),

							(gc.getInfoTypeForString('RELIGION_FELLOWSHIP_OF_LEAVES'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_LEAVES'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_LEAVES')),

							(gc.getInfoTypeForString('RELIGION_OCTOPUS_OVERLORDS'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_OVERLORDS'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_OVERLORDS')),

							(gc.getInfoTypeForString('RELIGION_COUNCIL_OF_ESUS'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_ESUS'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_ESUS')),

							(gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_ASHEN'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_ASHEN')),

							(gc.getInfoTypeForString('RELIGION_WHITE_HAND'),
							gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_HAND'),
							gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_HAND'))

							]
				for iReligion, iManaPlus, iManaMinus in listReligiousMana:
					pCity.setNumRealBuilding(iManaPlus, iStateReligion == iReligion)
					pCity.setNumRealBuilding(iManaMinus, iStateReligion == iReligion)

Code:
	def onGameStart(self, argsList):
		'Called at the start of the game'

		if CyGame().getWBMapScript():
			sf.gameStart()
		else:
			introMovie = CvIntroMovieScreen.CvIntroMovieScreen()
			introMovie.interfaceScreen()

		if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_THAW):
# Enhanced End of Winter - Adpated from FlavourMod

			FLAT_WORLDS = ["ErebusWrap", "Erebus"]			# map scripts with wrapping but no equator
			MAX_EOW_PERCENTAGE = 0.25 						# percentage of EoW on total game turns
			THAW_DELAY_PERCENTAGE = 0.05 					# don't start thawing for x percent of EoW

			# forest varieties
			DECIDUOUS_FOREST = 0
			CONIFEROUS_FOREST = 1
			SNOWY_CONIFEROUS_FOREST = 2

			dice = gc.getGame().getSorenRand()

			iDesert = gc.getInfoTypeForString('TERRAIN_DESERT')
			iGrass = gc.getInfoTypeForString('TERRAIN_GRASS')
			iMarsh = gc.getInfoTypeForString('TERRAIN_MARSH')
			iPlains = gc.getInfoTypeForString('TERRAIN_PLAINS')
			iSnow = gc.getInfoTypeForString('TERRAIN_SNOW')
			iTundra = gc.getInfoTypeForString('TERRAIN_TUNDRA')
			iIce = gc.getInfoTypeForString('FEATURE_ICE')
			iForest = gc.getInfoTypeForString('FEATURE_FOREST')
			iJungle = gc.getInfoTypeForString('FEATURE_JUNGLE')
			iBlizzard = gc.getInfoTypeForString('FEATURE_BLIZZARD')

			iMana = gc.getInfoTypeForString('BONUSCLASS_MANA')#Magister
			iRawMana = gc.getInfoTypeForString('BONUSCLASS_RAWMANA')#Magister
			iFloodPlains = gc.getInfoTypeForString('FEATURE_FLOOD_PLAINS')#Magister

#			iTotalGameTurns = gc.getGameSpeedInfo(CyGame().getGameSpeedType()).getGameTurnInfo(0).iNumGameTurnsPerIncrement
#			iMaxEOWTurns = max(1, int(iTotalGameTurns * MAX_EOW_PERCENTAGE))
#			iThawDelayTurns = max(1, int(iMaxEOWTurns * THAW_DELAY_PERCENTAGE))

			iMaxLatitude = max(CyMap().getTopLatitude(), abs(CyMap().getBottomLatitude()))
			bIsFlatWorld = not (CyMap().isWrapX() or CyMap().isWrapY()) or CyMap().getMapScriptName() in FLAT_WORLDS

			for i in xrange (CyMap().numPlots()):
				pPlot = CyMap().plotByIndex(i)
				eTerrain = pPlot.getTerrainType()
				eFeature = pPlot.getFeatureType()
				iVariety = pPlot.getFeatureVariety()
				eBonus = pPlot.getBonusType(TeamTypes.NO_TEAM)

				iTurns = dice.get(110, "Thaw") + 40
				iTurns = (iTurns * gc.getGameSpeedInfo(CyGame().getGameSpeedType()).getVictoryDelayPercent()) / 100
				if not bIsFlatWorld:
					iLatitude = abs(pPlot.getLatitude())
					iTurns = int(iTurns * ((float(iLatitude) / iMaxLatitude) ** 0.4))
#				iTurns += iThawDelayTurns

				# cover erebus' oceans and lakes in ice
				if pPlot.isWater():
					if bIsFlatWorld:
						if dice.get(100, "Flat World Ice") < 90:
							pPlot.setTempFeatureType(iIce, 0, iTurns)
					elif iLatitude + 10 > dice.get(50, "Ice"):
						pPlot.setTempFeatureType(iIce, 0, iTurns)

				# change terrains to colder climate versions
				if eTerrain == iTundra:
					if dice.get(100, "Tundra to Snow") < 90:
						pPlot.setTempTerrainType(iSnow, iTurns)
				elif eTerrain == iGrass:
					if eFeature != iJungle:
						if dice.get(100, "Grass to Snow or Tundra") < 60:
							pPlot.setTempTerrainType(iSnow, iTurns)
						else:
							pPlot.setTempTerrainType(iTundra, iTurns)
				elif eTerrain == iPlains:
					if dice.get(100, "Plains to Snow or Tundra") < 30:
						pPlot.setTempTerrainType(iSnow, iTurns)
					else:
						pPlot.setTempTerrainType(iTundra, iTurns)
				elif eTerrain == iDesert:
					if dice.get(100, "Desert to Tundra or Plains") < 50:
						pPlot.setTempTerrainType(iTundra, iTurns)
					else:
						pPlot.setTempTerrainType(iPlains, iTurns)
				elif eTerrain == iMarsh:
					pPlot.setTempTerrainType(iGrass, iTurns)

				# change forests to colder climate versions
				if eFeature == iForest:
					if iVariety == DECIDUOUS_FOREST:
						pPlot.setTempFeatureType(iForest, CONIFEROUS_FOREST, iTurns)
					elif iVariety == CONIFEROUS_FOREST:
						pPlot.setTempFeatureType(iForest, SNOWY_CONIFEROUS_FOREST, iTurns)
				elif eFeature == iJungle:
					pPlot.setTempFeatureType(iForest, DECIDUOUS_FOREST, iTurns)
				elif eFeature == iFloodPlains:
					pPlot.setTempFeatureType(FeatureTypes.NO_FEATURE, -1, iTurns)
				elif eFeature == FeatureTypes.NO_FEATURE:
					if dice.get(100, "Spawn Blizzard") < 5:
						pPlot.setFeatureType(iBlizzard, -1)

				# temporarily remove invalid bonuses or replace them (if food) with a valid surrogate
				if eBonus != BonusTypes.NO_BONUS and not gc.getBonusInfo(eBonus).isMana():
					pPlot.setBonusType(BonusTypes.NO_BONUS)
					if not pPlot.canHaveBonus(eBonus, True):
						if gc.getBonusInfo(eBonus).getYieldChange(YieldTypes.YIELD_FOOD) > 0:
							iPossibleTempFoodBonuses = []
							for iLoopBonus in xrange(gc.getNumBonusInfos()):
								if gc.getBonusInfo(iLoopBonus).getYieldChange(YieldTypes.YIELD_FOOD) > 0:
									if pPlot.canHaveBonus(iLoopBonus, True):
										iPossibleTempFoodBonuses.append(iLoopBonus)
							pPlot.setBonusType(eBonus)
							if len(iPossibleTempFoodBonuses) > 0:
								pPlot.setTempBonusType(iPossibleTempFoodBonuses[dice.get(len(iPossibleTempFoodBonuses), "Temp Food Bonus")], iTurns)
							else:
								pPlot.setTempBonusType(BonusTypes.NO_BONUS, iTurns)
						else:
							pPlot.setBonusType(eBonus)
							pPlot.setTempBonusType(BonusTypes.NO_BONUS, iTurns)
					else:
						pPlot.setBonusType(eBonus)
			Blizzards.doBlizzardTurn()
# End Enhanced End of Winter



		pNetherworld = CyMap().plot(0,0)
		pNetherworld.setTerrainType(gc.getInfoTypeForString('TERRAIN_SHALLOWS'), True, True)
		pNetherworld.setFeatureType(-1, -1)
		pNetherworld.setImprovementType(-1)
		pNetherworld.setBonusType(-1)
		pNetherworld.setMoveDisabledAI(True)
		pNetherworld.setMoveDisabledHuman(True)


		iElohim = gc.getInfoTypeForString('CIVILIZATION_ELOHIM')
		iLjosalfar = gc.getInfoTypeForString('CIVILIZATION_LJOSALFAR')
		iSvartalfar = gc.getInfoTypeForString('CIVILIZATION_SVARTALFAR')
		iBannor = gc.getInfoTypeForString('CIVILIZATION_BANNOR')
		iClan = gc.getInfoTypeForString('CIVILIZATION_CLAN_OF_EMBERS')
		iKhazad = gc.getInfoTypeForString('CIVILIZATION_KHAZAD')
		iHippus = gc.getInfoTypeForString('CIVILIZATION_HIPPUS')
		iMalakim = gc.getInfoTypeForString('CIVILIZATION_MALAKIM')
		iCalabim = gc.getInfoTypeForString('CIVILIZATION_CALABIM')
		iInfernal = gc.getInfoTypeForString('CIVILIZATION_INFERNAL')
		iMercurian = gc.getInfoTypeForString('CIVILIZATION_MERCURIANS')

		iHannah = gc.getInfoTypeForString('LEADER_HANNAH')

		iOrdersFromHeaven = gc.getInfoTypeForString('TECH_ORDERS_FROM_HEAVEN')
		iWayOfEarthmother = gc.getInfoTypeForString('TECH_WAY_OF_THE_EARTHMOTHER')
		iWayOfForest = gc.getInfoTypeForString('TECH_WAY_OF_THE_FORESTS')
		iMessageFromDeep = gc.getInfoTypeForString('TECH_MESSAGE_FROM_THE_DEEP')
		iDeception = gc.getInfoTypeForString('TECH_DECEPTION')

		iEvil = gc.getInfoTypeForString('ALIGNMENT_EVIL')
		iNeutral = gc.getInfoTypeForString('ALIGNMENT_NEUTRAL')
		iGood = gc.getInfoTypeForString('ALIGNMENT_GOOD')

		iOrder = gc.getInfoTypeForString('RELIGION_THE_ORDER')
		iEmpyrean = gc.getInfoTypeForString('RELIGION_THE_EMPYREAN')
		iRunes = gc.getInfoTypeForString('RELIGION_RUNES_OF_KILMORPH')
		iLeaves = gc.getInfoTypeForString('RELIGION_FELLOWSHIP_OF_LEAVES')
		iOverlords = gc.getInfoTypeForString('RELIGION_OCTOPUS_OVERLORDS')
		iEsus = gc.getInfoTypeForString('RELIGION_COUNCIL_OF_ESUS')
		iVeil = gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL')
		iDragon = gc.getInfoTypeForString('RELIGION_CULT_OF_THE_DRAGON')
		iHand = gc.getInfoTypeForString('RELIGION_WHITE_HAND')
		iOne = gc.getInfoTypeForString('RELIGION_CHILDREN_OF_THE_ONE')

		listReligiousMana = [	(iOrder,
					gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_ORDER'),
					gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_ORDER')),

					(iEmpyrean,
					gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_EMPYREAN'),
					gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_EMPYREAN')),

					(iRunes,
					gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_KILMORPH'),
					gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_KILMORPH')),

					(iLeaves,
					gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_LEAVES'),
					gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_LEAVES')),

					(iOverlords,
					gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_OVERLORDS'),
					gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_OVERLORDS')),

					(iEsus,
					gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_ESUS'),
					gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_ESUS')),

					(iVeil,
					gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_ASHEN'),
					gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_ASHEN')),

					(iHand,
					gc.getInfoTypeForString('BUILDING_FREE_MANA_STATE_RELIGION_THE_HAND'),
					gc.getInfoTypeForString('BUILDING_LOST_MANA_STATE_RELIGION_THE_HAND'))

					]

		for iPlayer in xrange(gc.getMAX_PLAYERS()):
			player = gc.getPlayer(iPlayer)
			if player.isAlive():

				iRel = player.getStateReligion()
				if iRel != -1:
					if iRel == iOrder:
						player.setCurrentEra(gc.getInfoTypeForString('ERA_ORDE'))
						player.setAlignment(iGood)
					elif iRel == iEmpyrean:
						player.setCurrentEra(gc.getInfoTypeForString('ERA_EMPY'))
						if player.getAlignment() == iEvil:
							player.setAlignment(iNeutral)
					elif iRel == iRunes:
						player.setCurrentEra(gc.getInfoTypeForString('ERA_RUNE'))
						if player.getAlignment() == iEvil:
							player.setAlignment(iNeutral)
					elif iRel == iLeaves:
						player.setCurrentEra(gc.getInfoTypeForString('ERA_LEAF'))
					elif iRel == iOverlords:
						player.setCurrentEra(gc.getInfoTypeForString('ERA_OCTO'))
						if player.getAlignment() == iGood:
							player.setAlignment(iNeutral)
					elif iRel == iEsus:
						player.setCurrentEra(gc.getInfoTypeForString('ERA_COUN'))
						if player.getAlignment() == iGood:
							player.setAlignment(iNeutral)
					elif iRel == iVeil:
						player.setAlignment(iEvil)
					elif iRel == iHand:
						player.setCurrentEra(gc.getInfoTypeForString('ERA_VEIL'))
						player.setAlignment(iEvil)

					pCapital = player.getCapitalCity()
					if not pCapital.isNone():
						for iReligion, iManaPlus, iManaMinus in listReligiousMana:
							pCapital.setNumRealBuilding(iManaPlus, iRel == iReligion)
							pCapital.setNumRealBuilding(iManaMinus, iRel == iReligion)


I'll have to check on this. That assert error is happening in getFreePromotions() which doesnt make much sense from the context.
Note that the Build Improvement (Automated) button in Advanced Start is not just about improvements. It lets the AI make all sorts of decisisons about what to purchase, including units, technologies, buildings, cities, etc.
This is the getFreePromotions() code again. Are you making calls to this function from python?

I call it once in CvEventManager.py under def onUnitCreated(self, argsList): in a snippet of code that prevents heroes that start with equipment from generating extra copies of that equipment when they are resurrected (or duplicated by the Black Mirror or Hall if Mirrors). It is within the conditional if isWorldUnitClass(iUnitClass):, so it shouldn't be running except for world units.

I call it 9 times in CvSpellInterface.py:

Once under def atRangeNecrototem(pCaster, pPlot):, to prevent newly initialized units from running in fear before being granted starting promotions that would make them immune to fear.
Once under def onMoveBlizzard(pCaster, pPlot): to stop units starting with Winterborn from being hurt when initialized on tiles with Blizzards.
Once in helpRecruitMercenaryType to determine whether to list promotion perks.
Twice in def reqRecruitMercenaryType(pCaster, eSpell, sUnitClass): to prevent undead mercenaries from being recruited by players for whom death mana is banned or demons for players who are neither Infernal nor Ashen Veil.
Twice in def spellRecruitMercenaryType(pCaster, eSpell, sUnitClass): when assigning the correct racial promotions to the mercenaires.
Once in def reqTakeEquipmentPromotion(pCaster, unit, eSpell=-1): to prevent Barnaxus himself from loosing his pieces (and thus golem-teaching ability)
Once in def helpShowSummonDetails(lpUnits, eSpell, sUnit, iNum = 1): to prevent listing summon perks which would already be listed in the unit help details already included.



I call it twice in CvGameUtils.py:
Once to make the Ban Death Mana resolution also block the construction of undead units (like Pyre Zombies) and
Once under def applyBuildEffects(self, argsList): when determining whether to grant racial promotions to units of Tolerant civs in cities of other cultures.

I call it 4 times in CustomFunctions.py:
Once is in the Sluagh generating code to let it know to use the Alternate Type for Werewolves and
Three times in the giftUnit code to allow water walking or flying units to appear on water.

I call it once in WBUnitScreen.py, in a section of code I commented out for your version. (This is not really necessary, but it makes it more convenient to quickly resurrect dead heroes from their sluaghs.)


It is called twice in the BUG ReligionUtil.py, to determine what units qualify as priests. That is not something I changed. (I should though, as priests in my version don't have Channeling 2.)

It is used 3 times in both CvPediaUnit.py and SevoPediaUnit.py under def placePromotions(self): when dealing with whether to display the various spell sphere promotions. (I did not touch this code either. Perhaps I should amend it to take into account those spell spheres that Vampirism or Unholy Taint may also make accessible.)


Haven't seen this one. Likely related to something new in your mod.
Maybe, but I'm not sure what.

This message first appeared when I used a wolf to construct a wolf pen.

I have added some new building art, but not for that.
That error is in the canStartMission() function. I wasn't able to replicate. What exactly do you mean by "selecting a unit in worldbuilder"? Are you trying to edit a unit?

Thanks for the reports!

It happened when I tried to enter Edit Unit Mode.

That function is used Platyping's more recent changes to WBUnitScreen.py, to generate the list of missions which you can force a unit to perform.

I the updated MNAI worldbuilder with that function was released before this Beta but not yet merged into it.

(I still have not gotten around to identifying all the newly exposed python functions to update worldbuilder to use them yet.)


I forgot to copy the exact error, but I also got one when I used worldbuilder to reduce a unit's level to zero, saying the number should be greater than zero. It shouldn't be too hard to edit the python code to make 1 instead of 0 the floor here.

edit: I just got these during another player's turn:
Code:
Assert Failed

File:  CvUnit.cpp
Line:  12000
Expression:  !at(iX, iY)
Message:  

----------------------------------------------------------
Code:
Assert Failed

File:  CvUnit.cpp
Line:  12593
Expression:  pOldPlot != pNewPlot
Message:  

----------------------------------------------------------
 
I do use comments to help organize some xml files. I guess I could delete them if necessary.

The game is picky about XML comments. Sometimes they are fine. Other times they throw these errors. I'm not sure what criteria it uses to decide which comments are acceptable. If you check the PythonDbg log right when that error pops up you might be able to trace it to a specific XML file.

Each religion has 2 dummy buildings. One adds +1 of the associated mana. The other 'adds' -2 of the opposite sphere.

I would prefer to make it only -1, but the code still treats that as equivalent to +3.

As long as the game is working as expected I guess this isn't a problem. -1 is often used in the code to signify a NULL field. Passing a -1 to a function that isnt expecting it can result in strangeness.

Note that the Build Improvement (Automated) button in Advanced Start is not just about improvements. It lets the AI make all sorts of decisisons about what to purchase, including units, technologies, buildings, cities, etc.

I did not know that. Thanks for the info!

re: getFreePromotions calls - make sure you are passing valid promotion IDs.


This message first appeared when I used a wolf to construct a wolf pen.

OK. I can check that on my build.

It happened when I tried to enter Edit Unit Mode.

That function is used Platyping's more recent changes to WBUnitScreen.py, to generate the list of missions which you can force a unit to perform.

I the updated MNAI worldbuilder with that function was released before this Beta but not yet merged into it.

Ah yes. I forgot that I wasn't on the same Worldbuilder as you. I'll try to do a merge soon.


edit: I just got these during another player's turn:
Code:
Assert Failed

File:  CvUnit.cpp
Line:  12000
Expression:  !at(iX, iY)
Message:  

----------------------------------------------------------
Code:
Assert Failed

File:  CvUnit.cpp
Line:  12593
Expression:  pOldPlot != pNewPlot
Message:  

----------------------------------------------------------

That's in the setXY code. Looks like there is a log output right before it hits this assert (not BBAlog -- one of the others). If you see this again, try and find the log entry which will tell us what plots the unit is moving from and to.
 
The game is picky about XML comments. Sometimes they are fine. Other times they throw these errors. I'm not sure what criteria it uses to decide which comments are acceptable. If you check the PythonDbg log right when that error pops up you might be able to trace it to a specific XML file.

IIRC the problem are comments in list elements, because it messes up the way civ iterates over the contents of these.
 
re: Magister

The CvSelectionGroup error is related to Worldbuilder 4.17. You're calling canStartMission with a mission value of 41 which doesn't correspond to anything in FFH

Also, I don't see the CvArtFileMgr error when building a wolf pen in MNAI.

Hope to have version beta2 out later today.
 
Blue Marble can cause that problem. Do you have it installed?
Ah, yes, that must be it then. Is there a fix? (Besides just not using Blue Marble and the grid in combination with each other, I mean. That's more of a workaround, if anything.)

It's part of Advanced Diplomacy which is placed under Advanced Tactics in this mod. Non-agression pact doesn't enforce peace like a peace treaty does. Instead it is a gentleman's agreement. If one side breaks the pact, they should get a diplomatic penalty for doing so.
Huh, so it just increases the diplomatic penalty for declaring war?

Those are options in the diplomacy screen. They may be gated by some prerequisites. Not sure on that. Diplomacy code is not an area am I very familiar with (which is why I'm trying to merge someone else's code who has worked on that facet of the game).
Er, no, not as such. I can request a declaration of war, embargo, change of civic(s), change of religion, etc. from the AI, but I can't offer any of those things to the AI, and in my experience the AI never offers anything for them. You only ever get the chance to suck up in hopes of future favors, rather than any immediate tangible benefit.

Unless there actually are techs or something that let you offer those things to the AI in trade, but I doubt it.
 
Top Bottom