a little help I need, please

hrochland

Prince
Joined
Apr 9, 2006
Messages
2,512
Location
Czech Kingdom
This is Zebra9 code modified by The Navy Seal. Part one separately is functional. Parts one and two in couple are not functional.
Can somebody find why, please
Thanks, HROCHland


Code:
	def cannotConstruct(self,argsList):
		pCity = argsList[0]
		eBuilding = argsList[1]
		bContinue = argsList[2]
		bTestVisible = argsList[3]
		bIgnoreCost = argsList[4]
# part one
		bCannotConstruct = True
		if eBuilding == gc.getInfoTypeForString("BUILDING_A") :
			iX = pCity.getX()
			iY = pCity.getY()
			for iiX in range(iX-1, iX+2, 1):
				for iiY in range(iY-1, iY+2, 1):
					pPlot = CyMap().plot(iiX,iiY)
					if pPlot.getOwner() == pCity.getOwner():
						if pPlot.getImprovementType() == gc.getInfoTypeForString("IMPROVEMENT_B"):
							bCannotConstruct = False
			if bCannotConstruct:
				return True
# part two
		bCannotConstruct = True
		if eBuilding == gc.getInfoTypeForString("BUILDING_C") :
			iX = pCity.getX()
			iY = pCity.getY()
			for iiX in range(iX-1, iX+2, 1):
				for iiY in range(iY-1, iY+2, 1):
					pPlot = CyMap().plot(iiX,iiY)
					if pPlot.getOwner() == pCity.getOwner():
						if pPlot.getImprovementType() == gc.getInfoTypeForString("IMPROVEMENT_D"):
							bCannotConstruct = False
			if bCannotConstruct:
				return True

		return False
 
What do you mean "not functional"? What happends? Nothing? An error message? (Have you turned on python exceptions?)
 
No message. Part one is functional sigle and part two is functional single too. If I add both, functio not work... :(
 
Before beginning part 2, if bCannotConstruct == False, you don't return, you just store bCannotConstruct = False. But at the beginning of part 2 (just after that) you put back bCannotConstruct = True.
So if bCannotConstruct == False in the first part, it's lost, no ?

I'd try to replace "bCannotConstruct = False" by "return False" in part 1, at minimum.
And then, in part 2 you begin an other test, independant that, I think, can stay like it is...
 
I will try it. Thanks Fabrysse. I´m not programmer but I thought too that test is one - no two.
I can not write it myself.
Thanks for help. I test it this evening.

HROCHland
 
I will test it this evening. This code is crucial for my mod. (yesterday I was in work for long time, could not tried it)
Thanks. I send word here if is it functional. I need this test for six situations. Without this code is my idea unusable... :(
 
Try this:
Code:
	def cannotConstruct(self,argsList):
		pCity = argsList[0]
		eBuilding = argsList[1]
		bContinue = argsList[2]
		bTestVisible = argsList[3]
		bIgnoreCost = argsList[4]

		#First, break out of this check if we don't need to be here
		buildingA = gc.getInfoTypeForString("BUILDING_A")
		buildingC = gc.getInfoTypeForString("BUILDING_C")

		if eBuilding != buildingA and eBuilding != buildingC:
			return False

		#Next, setup building types here, assume that you can't build
		#them until proven otherwise. (True means they can NOT be built)
		bCantBuildA = True
		bCantBuildC = True

		#Get the city plot, and check the surrounding plots for the
		#required improvements.
		iX = pCity.getX()
		iY = pCity.getY()
		for iiX in range(iX-1, iX+2, 1):
			for iiY in range(iY-1, iY+2, 1):
				pPlot = CyMap().plot(iiX,iiY)
				if pPlot.getOwner() == pCity.getOwner():
					if pPlot.getImprovementType() == gc.getInfoTypeForString("IMPROVEMENT_B"):
						bCantBuildA = False
					if pPlot.getImprovementType() == gc.getInfoTypeForString("IMPROVEMENT_C"):
						bCantBuildC = False

		#Return the results
		if eBuilding == buildingA:
			return bCantBuildA
		elif eBuilding == buildingC:
			return bCantBuildC

		return False
The difference here is that I changed the order around a bit. It's untested though and I'm suffering from turkey induced coma so use at your own risk. If it does work, it should be substantially easier for you to add more buildings & improvements to the list :)
 
@ Fabrysse
Hi, Fabrysse. Code after change is not functional. I´m not programmer but I think: parts One and Two must be independent but are´t.
Next problem I see in part ends:

if bCannotConstruct:
return True

It is do not end of script in first or second case, i think. All Other code ends return True. Part one and part two mustn't it cooperate. Must be independent for right function of each of code. I wrote to Zebra9 (he is author of original code) but he do not reply.
I cogitated too, maybe code must be write for:
def canConstruct(self,argsList):
and no
def cannotConstruct(self,argsList):
At all events thanks you very much. I shall be happy to cooperation if you find out some time for me. :) :)

@ Seven05
Hi, Seven05. I will try your code. Thanks you very much. I will very happy if code will be functional :)
One question I have:
Will be works next code in " def cannotConstruct(self,argsList): ", when your code is´t finished: " return True " ? As other codes?

I have on mind cooperation withMachu Picchu code by GIR which I would like used too.

@ All
Sory for my bad English
 
No problem on your English, it's infinitly better than my Czech :)

It works in Cannot Construct because that code expects True to be returned if the building can not be built, False if it can be built. So in my code we assume that everything CAN be built (return False) unless it is one of the two buildings AND you don't have the required improvement.

Yes, it would have been easier if the function was canConstruct and returned true if the building could be built. :)
 
@ Seven05 :hatsoff:
Thanks you very much. Code works very good. With Machu Picchu code is not conflict here. :) Now I can finnish my new game concept. :goodjob:
Thanks, Seven05.
One question I have: I will add new buildings and improvements to the list but is here this line:

if eBuilding != buildingA and eBuilding != buildingC and eBuilding != buildingE:
is this right way how add new buildings in this line? (and eBuilding != buildingG: ETC...)?

And one more question, please
This excellent code check improvement type in inner plot (8 squares around city). Is possible write it for full one city range, please?

Thanks, Seven05.
 
One question I have: I will add new buildings and improvements to the list but is here this line:

if eBuilding != buildingA and eBuilding != buildingC and eBuilding != buildingE:
is this right way how add new buildings in this line? (and eBuilding != buildingG: ETC...)?

You can do that like this but it would be easier to do :
Code:
if not eBuilding in [ buildingA, buildingC, buildingE, buildingG ] :
        return False

This excellent code check improvement type in inner plot (8 squares around city). Is possible write it for full one city range, please?

you can change your function like this :

Code:
#Get the city plot, and check the surrounding plots for the
#required improvements.

# first check if the city argument is valid
if pCity.isNone() :
        return True

iX = pCity.getX()
iY = pCity.getY()
iCityOwner = pCity.getOwner()

playerCityCross = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1),(-2,-1),(-2,0),(-2,1),(2,-1),(2,0),(2,1),(-1,2),(0,2),(1,2),(-1,-2),(0,-2),(1,-2)]

for dX, dY in playerCityCross:
        pPlot = CyMap().plot(iX+dX, iY+dY)

        # check if the plot is valid if you are at the border of the map.
        if pPlot.isNone() :
                continue
        
        if pPlot.getOwner() == iCityOwner:
                if pPlot.getImprovementType() == gc.getInfoTypeForString("IMPROVEMENT_B"):
                        bCantBuildA = False
                if pPlot.getImprovementType() == gc.getInfoTypeForString("IMPROVEMENT_C"):
                        bCantBuildC = False

Tcho !
 
Thanks you very much, Sto
I will test it. Is here possibility of conflict when on one improvement touch two cities?


behind schedule I´m sorry, I do not test how you advice me because Seven05´s code in addition is solving my problem:
"conflict or no"
with Machu Picchu code :) here I find not conflict at two test games...
 
Yes , the function allow 2 cities with a common improvement to build the building . I don't know how to check if the plot is in the city A or B . I've tried to search how the screen save/hide some plot when you select a plot for a city or another , but i don't find anything . There is some functions in the API that would be for that but that need some tests .

Tcho !

Edit : in your test games try to place some cities with common tiles and at the border of the map ( with no wrap ) .
 
OK. Thanks you very much.

I can see, here is many excellent programmers. Could anybody of you, please, manage to solve my problem from this thread? :::
http://forums.civfanatics.com/showthread.php?t=249358

It is problem that I need to have more models for the same improvement. It is castle and I made more models to change
first build = model one
second build = model two
...
fourth build = model one
fifth build = model two
etc.

If is it possible... help please

HROCHland
 
@ Seven05 :hatsoff:
Thanks you very much. Code works very good. With Machu Picchu code is not conflict here. :) Now I can finnish my new game concept. :goodjob:
Thanks, Seven05.
Glad it worked. Sto's additions should handle you other questions, if you need more help just ask. Also, how many buildings do you need to check with this? If it's more than 5 or 6 I'd write it differently, using lists similar to Sto's suggestion.
 
Glad it worked. Sto's additions should handle you other questions, if you need more help just ask. Also, how many buildings do you need to check with this? If it's more than 5 or 6 I'd write it differently, using lists similar to Sto's suggestion.


In this while I have usage for 6 situations. If I can add buildings and improvements to the list how you wrote, my new game concept will be work very good. Thanks you very much, Seven05. I will work with it. This code is perfect :goodjob:
as regards one line, I asked if OK write and... and... and... :
or is need for more situations change this line
for example as wrote Sto ???
I will test it :)
You very help me :goodjob:
 
You can try that and just have to define the list of buildings and improvement required in the same order of the buildings :

Code:
# make a list of buildings and improvement needed in the same order
buildingList = ["BUILDING_A" ,"BUILDING_B" ,"BUILDING_C" ,"BUILDING_D" ,"BUILDING_E" ,"BUILDING_F"]
improvementList = ["IMPROVEMENT_A" ,"IMPROVEMENT_B" ,"IMPROVEMENT_C" ,"IMPROVEMENT_D" ,"IMPROVEMENT_E" ,"IMPROVEMENT_F"]

# convert type strings to integer :
buildingList = [ gc.getInfoTypeForString(item) for item in buildingList ]

# Then, break out of this check if we don't need to be here
if not eBuilding in buildingList:
        return False

# first check if the city argument is valid
if pCity.isNone() :
        return True

improvementToCheck = gc.getInfoTypeForString(improvementList[buildingList.index(eBuilding)])

#Get the city plot, and check the surrounding plots for the required improvement.

iX = pCity.getX()
iY = pCity.getY()
iCityOwner = pCity.getOwner()
bCantBuild = True

playerCityCross = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1),(-2,-1),(-2,0),(-2,1),(2,-1),(2,0),(2,1),(-1,2),(0,2),(1,2),(-1,-2),(0,-2),(1,-2)]

for dX, dY in playerCityCross:
        pPlot = CyMap().plot(iX+dX, iY+dY)

        # check if the plot is valid if you are at the border of the map.
        if pPlot.isNone() :
                continue
        
        if pPlot.getOwner() == iCityOwner:
                if pPlot.getImprovementType() == improvementToCheck:
                        bCantBuild = False
                        break

return bCantBuild

Tcho !

Edit : i've changed the place of the test to check if the city argument is valid in order to not prevent all buildings from being built if this argument is not valid .
 
Ok, I had some free time so here's some answers :)

Sto, the function you want is canWork(CyPlot* pPlot) which will return true if the city can work the plot passed. For instance, pCity.canWork(pPlot).

Combining my original post with Sto's enhancements and knowing that you want to add several building/improvement combinations I would try something like:
Code:
	def cannotConstruct(self,argsList):
		pCity = argsList[0]
		eBuilding = argsList[1]
		bContinue = argsList[2]
		bTestVisible = argsList[3]
		bIgnoreCost = argsList[4]

		if pCity.isNone():
			return True

		#Here we create two matching arrays
		buildings = array('i')
		improvements = array('i')

		buildings.append(gc.getInfoTypeForString("BUILDING_A"))
		improvements.append(gc.getInfoTypeForString("IMPROVEMENT_B"))

		buildings.append(gc.getInfoTypeForString("BUILDING_C"))
		improvements.append(gc.getInfoTypeForString("IMPROVEMENT_D"))

		buildings.append(gc.getInfoTypeForString("BUILDING_E"))
		improvements.append(gc.getInfoTypeForString("IMPROVEMENT_F"))

		iBuilding = -1
		iImprovement = -1
		for i in range(len(buildings)):
			if eBuilding == buildings[i]:
				iBuilding = buildings[i]
				iImprovement = improvements[i]
				break
		#Now we know both infotypes if there is a match
		#Otherwise iBuilding will still be -1, test it now and
		#get out if we have a building that's not in our list
		if iBuilding == -1:
			return False

		#Assume we can't build this until proven otherwise
		bCantBuildThis = True

		#Get the city plot, and check the surrounding plots for the
		#required improvements.
		iX = pCity.getX()
		iY = pCity.getY()
		playerCityCross = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1),(-2,-1),(-2,0),(-2,1),(2,-1),(2,0),(2,1),(-1,2),(0,2),(1,2),(-1,-2),(0,-2),(1,-2)]

		for dX, dY in playerCityCross:
			pPlot = CyMap().plot(iX+dX, iY+dY)

			# check if the plot is valid and can be worked by this city.
			if pPlot.isNone() :
				continue
			elif !pCity.canWork(pPlot):
				continue

			if pPlot.getOwner() == iCityOwner:
				if pPlot.getImprovementType() == iImprovement:
					bCantBuildThis = False

		#Return the results
		return bCantBuildThis
To add different buildings to the list is easier. It works with a pair of arrays, one for the building and the next for the improvement. The order you add buildings & improvements to the list is important since the rest of the code assumes they share an index (same position in the different arrays). In other words, the first building will match only the first improvement, the second building matches the second improvement and so on.

To add more buildings to the check you need to extend these lines:
Code:
		buildings.append(gc.getInfoTypeForString("BUILDING_A"))
		improvements.append(gc.getInfoTypeForString("IMPROVEMENT_B"))

		buildings.append(gc.getInfoTypeForString("BUILDING_C"))
		improvements.append(gc.getInfoTypeForString("IMPROVEMENT_D"))

		buildings.append(gc.getInfoTypeForString("BUILDING_E"))
		improvements.append(gc.getInfoTypeForString("IMPROVEMENT_F"))
You can have duplicates as long as each test is entered as a pair. So, for example this would also work:
Code:
		buildings.append(gc.getInfoTypeForString("BUILDING_A"))
		improvements.append(gc.getInfoTypeForString("IMPROVEMENT_B"))

		buildings.append(gc.getInfoTypeForString("BUILDING_C"))
		improvements.append(gc.getInfoTypeForString("IMPROVEMENT_B"))

		buildings.append(gc.getInfoTypeForString("BUILDING_E"))
		improvements.append(gc.getInfoTypeForString("IMPROVEMENT_D"))
Note the repitition of "IMPROVEMENT_B" for buildings A & C. It is VERY important that you make absolutely sure that both lists are the same size, if your building array is larger than your improvement array you will go 'out of bounds' and break the code.

Since I like to live dangerously (at your expense :)) this code is also untested. Make sure you save the working file you have now before adding this in it's place. It should work, at least I don't see any glaring errors with it.
 
Back
Top Bottom