BuildingTypeName

OrionVeteran

Deity
Joined
Dec 25, 2003
Messages
2,443
Location
Newport News VA
I have been fighting with Python all day. I need to get the Building Type Name not the number, when I loop through all the buildingInfos. Problem is there is no getBuildingType() function to reference. I desperately need to find a way to return the building Type name. :wallbash: It's probably something really easy I overlooked.

Respectfully,

Orion Veteran :cool:
 
I did not try this code, but the information you want is on the CvBuildingInfo:

pBuilding = gc.getBuildingInfo(iBuilding)
sName = pBuilding.getText()
 
Assuming you have buildingInfo the .getType() call will return the building type as a string.

Always check the PythonAPI. Specifically here you want to look in the BuildingInfo section of CvInfoBase:
http://civ4bug.sourceforge.net/PythonAPI/index.html
 
I did not try this code, but the information you want is on the CvBuildingInfo:

pBuilding = gc.getBuildingInfo(iBuilding)
sName = pBuilding.getText()

Here is the final code that works! :)
Spoiler :

Code:
def getReligionShrine(iStateReligion):
	# Orion's Inquisition Mod
	# Part of the Religious Victory Check
	# Returns the Shrine Name for the given Player's State Religion
		
	for iBuilding in range(gc.getNumBuildingInfos()):
		iBuildingClass = gc.getBuildingInfo(iBuilding).getBuildingClassType()
		if gc.getBuildingClassInfo(iBuildingClass).getMaxGlobalInstances() == 1:
			kBuilding = gc.getBuildingInfo(gc.getBuildingClassInfo(iBuildingClass).getDefaultBuildingIndex())
			
			if kBuilding.getGlobalReligionCommerce() == iStateReligion:
				if kBuilding.getHolyCity() == iStateReligion:
					# Get the Shrine Name
					MyShrineName = gc.getBuildingInfo(iBuilding).getType()						
					#CyInterface().addImmediateMessage(str(MyShrineName), "")
					return MyShrineName
					break
 
I've been messing with this building and unit stuff for a while, fixing various exceptions thrown by RevDCM and BUG. You're going to need to pass in the Player and loop over BuildingClassInfos and then use getCivilizationBuildings(iBuildingClass) on the player to get the building type for the player. This is important because some mods may have UBs set up for shrines and if this is the case the dll will complain. In general you should avoid looping over BuildingInfos and UnitInfos and instead loop over the classes and get the actual type by player.
 
I've been messing with this building and unit stuff for a while, fixing various exceptions thrown by RevDCM and BUG. You're going to need to pass in the Player and loop over BuildingClassInfos and then use getCivilizationBuildings(iBuildingClass) on the player to get the building type for the player. This is important because some mods may have UBs set up for shrines and if this is the case the dll will complain. In general you should avoid looping over BuildingInfos and UnitInfos and instead loop over the classes and get the actual type by player.

Forgive me, but what is a UB?

The above function works in conjunction with this:
Spoiler :

Code:
def hasStateReligionShrine(iPlayer):
	# Orion's Inquisition Mod
	# Part of the Religious Victory Check
	# True if the player has the state Religion Shrine
	# False if the player does not have the state Religion Shrine
	pPlayer = gc.getPlayer(iPlayer)
	iStateReligion = pPlayer.getStateReligion()
	FoundStateShrine = False
	
	if iStateReligion:
		MyShrine = getReligionShrine(iStateReligion)
		#CyInterface().addImmediateMessage(str(MyShrine), "")
		
		for iCity in range(pPlayer.getNumCities()):
			pCity = pPlayer.getCity(iCity)
			if pCity.isHasBuilding(gc.getInfoTypeForString(MyShrine)):
				FoundStateShrine = True
				break
					
	return FoundStateShrine
 
I had a general idea, yeah. But that doesn't solve the issue. I bring this up becuase I've had to fix about a half dozen asserts over the last couple of days caused by exactly this type of function. Here is what i mean in C++ (python is very similar):

Wrong way:
Code:
Void foo(CvCity& city)
{
	for (int i = 0; i < GC.getNumBuildingInfos(); i++)
	{
		if (city.canConstruct((BuildingTypes)i, false, true, false))
		{
...do stuff

Right way
Code:
Void foo(CvCity& city)
{
	CvCivilizationInfo& kCivilization = GC.getCivilizationInfo((GET_PLAYER(city.getOwnerINLINE())).getCivilizationType());

	int iI;

	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		BuildingTypes eLoopBuilding = (BuildingTypes)kCivilization.getCivilizationBuildings((BuildingClassTypes)iI);
		if (eLoopBuilding == NO_BUILDING)
		{
			continue;
		}
		if (city.canConstruct(eLoopBuilding, false, true, false))
		{
...do stuff
 
I had a general idea, yeah. But that doesn't solve the issue. I bring this up becuase I've had to fix about a half dozen asserts over the last couple of days caused by exactly this type of function. Here is what i mean in C++ (python is very similar):
Spoiler :

Wrong way:
Code:
Void foo(CvCity& city)
{
	for (int i = 0; i < GC.getNumBuildingInfos(); i++)
	{
		if (city.canConstruct((BuildingTypes)i, false, true, false))
		{
...do stuff

Right way
Code:
Void foo(CvCity& city)
{
	CvCivilizationInfo& kCivilization = GC.getCivilizationInfo((GET_PLAYER(city.getOwnerINLINE())).getCivilizationType());

	int iI;

	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		BuildingTypes eLoopBuilding = (BuildingTypes)kCivilization.getCivilizationBuildings((BuildingClassTypes)iI);
		if (eLoopBuilding == NO_BUILDING)
		{
			continue;
		}
		if (city.canConstruct(eLoopBuilding, false, true, false))
		{
...do stuff

I'm running my code with your DLL now and I get no errors. Call me thick headed, but I fail to see how a function that works, is going to mess up the SDK later. :confused:
 
Forgive me, but what is a UB?

UB = unique building ;).

I'm running my code with your DLL now and I get no errors. Call me thick headed, but I fail to see how a function that works, is going to mess up the SDK later. :confused:

Because like phungus said: Your code doesn't catch the option that a civ could have an UB for a shrine.




And you should additionally take a look at this post.
 
UB = unique building ;).

Because like phungus said: Your code doesn't catch the option that a civ could have an UB for a shrine.

And you should additionally take a look at this post.

Picky, Picky, Picky...

OK, here are the converted functions:

Spoiler :

Code:
def getReligionShrine(iPlayer, iStateReligion):
	# Orion's Inquisition Mod
	# Part of the Religious Victory Check
	# Returns the Shrine Name for the given Player's State Religion
	pPlayer = gc.getPlayer(iPlayer)
	
	for iBuildingClass in range(gc.getNumBuildingClassInfos()):
		if gc.getBuildingClassInfo(iBuildingClass).getMaxGlobalInstances() == 1:
			kBuilding = gc.getBuildingInfo(gc.getBuildingClassInfo(iBuildingClass).getDefaultBuildingIndex())
			
			if kBuilding.getGlobalReligionCommerce() == iStateReligion:
				if kBuilding.getHolyCity() == iStateReligion:
					# Get the Shrine Name
					iBuilding = gc.getCivilizationInfo(pPlayer.getCivilizationType()).getCivilizationBuildings(iBuildingClass)
					MyShrineName = gc.getBuildingInfo(iBuilding).getType()
					#CyInterface().addImmediateMessage(str(MyShrineName), "")
					return MyShrineName
					break


Which works with this:

Spoiler :

Code:
def hasStateReligionShrine(iPlayer):
	# Orion's Inquisition Mod
	# Part of the Religious Victory Check
	# True if the player has the state Religion Shrine
	# False if the player does not have the state Religion Shrine
	pPlayer = gc.getPlayer(iPlayer)
	iStateReligion = pPlayer.getStateReligion()
	FoundStateShrine = False
	
	if iStateReligion:
		MyShrine = getReligionShrine(iPlayer, iStateReligion)
		CyInterface().addImmediateMessage(str(MyShrine), "")
		
		for iCity in range(pPlayer.getNumCities()):
			pCity = pPlayer.getCity(iCity)
			if pCity.isHasBuilding(gc.getInfoTypeForString(MyShrine)):
				FoundStateShrine = True
				break
					
	return FoundStateShrine


This is a huge break through for the Inquisition mod, as there will be no need to add any data to a python dictionary. It will be all done automagically. :) I will post an update with these changes in the coming days. For now, I'm tired and need to rest.

Orion Veteran :cool:
 
Looks good OV. Here is my optimization of def getReligionShrine(iPlayer, iStateReligion):
Spoiler :
Code:
def getReligionShrine(iPlayer, iStateReligion):
	# Orion's Inquisition Mod
	# Part of the Religious Victory Check
	# Returns the Shrine Name for the given Player's State Religion
	pPlayer = gc.getPlayer(iPlayer)
	kCivilization = gc.getCivilizationInfo(pPlayer.getCivilizationType())
	
	for iBuildingClass in range(gc.getNumBuildingClassInfos()):
		if gc.getBuildingClassInfo(iBuildingClass).getMaxGlobalInstances() > 0:
			kBuilding = gc.getBuildingInfo(kCivilization.getCivilizationBuildings(iBuildingClass))
			
			if kBuilding.getGlobalReligionCommerce() == iStateReligion:
				if kBuilding.getHolyCity() == iStateReligion:
					# Get the Shrine Name
					MyShrineName = kBuilding.getType()
					#CyInterface().addImmediateMessage(str(MyShrineName), "")
					return MyShrineName
					break

Your code may be better though, as it takes into account if a mod makes a UB that changes the behavior of a shrine (ie it doesn't add gold per city with the religion, etc). Also if you want the name, isntead of the string info type, use getDescription(), this will return the name from the TextInfos file.
 
Looks good OV. Here is my optimization of def getReligionShrine(iPlayer, iStateReligion):
Spoiler :
Code:
def getReligionShrine(iPlayer, iStateReligion):
	# Orion's Inquisition Mod
	# Part of the Religious Victory Check
	# Returns the Shrine Name for the given Player's State Religion
	pPlayer = gc.getPlayer(iPlayer)
	kCivilization = gc.getCivilizationInfo(pPlayer.getCivilizationType())
	
	for iBuildingClass in range(gc.getNumBuildingClassInfos()):
		if gc.getBuildingClassInfo(iBuildingClass).getMaxGlobalInstances() > 0:
			kBuilding = gc.getBuildingInfo(kCivilization.getCivilizationBuildings(iBuildingClass))
			
			if kBuilding.getGlobalReligionCommerce() == iStateReligion:
				if kBuilding.getHolyCity() == iStateReligion:
					# Get the Shrine Name
					MyShrineName = kBuilding.getType()
					#CyInterface().addImmediateMessage(str(MyShrineName), "")
					return MyShrineName
					break

Your code may be better though, as it takes into account if a mod makes a UB that changes the behavior of a shrine (ie it doesn't add gold per city with the religion, etc). Also if you want the name, isntead of the string info type, use getDescription(), this will return the name from the TextInfos file.

OK, I have changed it to this:

Spoiler :
Code:
def getReligionShrine(iPlayer, iStateReligion):
	# Orion's Inquisition Mod
	# Part of the Religious Victory Check
	# Returns the Shrine Name for the given Player's State Religion
	pPlayer = gc.getPlayer(iPlayer)
	kCivilization = gc.getCivilizationInfo(pPlayer.getCivilizationType())
	
	for iBuildingClass in range(gc.getNumBuildingClassInfos()):
		if gc.getBuildingClassInfo(iBuildingClass).getMaxGlobalInstances() > 0:
			kBuilding = gc.getBuildingInfo(kCivilization.getCivilizationBuildings(iBuildingClass))					
					
			if kBuilding.getGlobalReligionCommerce() == iStateReligion:
				if kBuilding.getHolyCity() == iStateReligion:
					# Get the Shrine Name					
					iBuilding = kCivilization.getCivilizationBuildings(iBuildingClass)					
					MyShrineName = gc.getBuildingInfo(iBuilding).getType()
					#CyInterface().addImmediateMessage(str(MyShrineName), "")
					return MyShrineName
					break

So the question now is: What would be best for you?

Code:
iBuilding = kCivilization.getCivilizationBuildings(iBuildingClass)	
MyShrineName = gc.getBuildingInfo(iBuilding).getType()

or

MyShrineName = kBuilding.getType()

Note: getDescription() does not work with the second function, which needs the return to utilize getType() to work correctly.
 
Thinking about it, the way you did it before was probably better, as you checked the default BuildingType for shrine behavior, and who knows what modders would do to the functionality of shrine if they turned it into a UB. Though, it really doesn't matter, we are kind of going off on a tangent here; both methods seem fine. I just couldn't implement the first way you had it with a hardcoded dictionary. What ever method you deem superior for this will work for the purposes of RevDCM, they both seem fully functional and basically rely on the programmer's preference on what he deems a more valid test to determine a shrine.

As far as the getDescription bit, I was thinking you would want that for message logging or to give information to the user. If you have none of that, then nevermind. I see the main thing where you print a message is commented out, so I assume it's for debugging, and in that case returning a string seems fine, but if you want the user to see something you should pass the description, that's all I was getting at.
 
BTW, I haven't read the code yet since you seem to have it working, but where is it being called? I recommend setting up a Python dictionary using an <init> so you aren't looping over all the buildings constantly looking for which one is the shrine.
 
Back
Top Bottom