Land Plots Over Wtaer Plots - help with a code

keldath

LivE LonG AnD PrOsPeR
Joined
Dec 20, 2005
Messages
7,580
Location
israel
hi there (again),

i hope this is the right place for this sort of question:

i have this code (by The_j) :
Code:
def generateTerrainAtPlot(self,iX,iY):
        lat = self.getLatitudeAtPlot(iX,iY)
        gc = CyGlobalContext()

        if (self.map.plot(iX, iY).isWater()):
                        [B]###changed for mars now
                        iTerrain = self.map.plot(iX,iY).getTerrainType()
                        if iTerrain == gc.getInfoTypeForString("TERRAIN_COAST"):
                                self.map.plot(iX, iY).setPlotType(PlotTypes.PLOT_LAND, false, false)
                                self.map.plot(iX, iY).setTerrainType(gc.getInfoTypeForString("TERRAIN_DESERT_WASTE"), false, false)
                        if iTerrain == gc.getInfoTypeForString("TERRAIN_OCEAN"):
                                self.map.plot(iX, iY).setPlotType(PlotTypes.PLOT_LAND, false, false)
                                self.map.plot(iX, iY).setTerrainType(gc.getInfoTypeForString("TERRAIN_DEEP_DESERT"), false, false)                                
            return self.map.plot(iX, iY).getTerrainType()
                        ###change end[/B]
        terrainVal = self.terrainGrass

        if lat >= self.fSnowLatitude:
            terrainVal = self.terrainIce
        elif lat >= self.fTundraLatitude:
            terrainVal = self.terrainTundra
        elif lat < self.fGrassLatitude:
            terrainVal = self.terrainGrass
        else:
            desertVal = self.deserts.getHeight(iX, iY)
            plainsVal = self.plains.getHeight(iX, iY)
            if ((desertVal >= self.iDesertBottom) and (desertVal <= self.iDesertTop) and (lat >= self.fDesertBottomLatitude) and (lat < self.fDesertTopLatitude)):
                terrainVal = self.terrainDesert
            elif ((plainsVal >= self.iPlainsBottom) and (plainsVal <= self.iPlainsTop)):
                terrainVal = self.terrainPlains

        if (terrainVal == TerrainTypes.NO_TERRAIN):
            return self.map.plot(iX, iY).getTerrainType()

        return terrainVal

this code suppose to turn coast and ocean into regular land terrain - but it wont for some reason,

the game just gets stuck and the map wont load,

now i have another type of code - but that one will start the game with replaced water tiles - but - after passing the turn - it will crash - im using bug based mod - and i get an error massage right on the beginning of buginit - bugunit.py failed.

so , anyone can help me achieve land over water code (that ill be able to add to various maps by my own?)

thanks for any reply,

keldath
 
If you put the code inside code tags someone might actually be able to read it.

Does your mod have these terrain types defined in the XML?
Code:
TERRAIN_DESERT_WASTE
TERRAIN__DEEP_DESERT
 
This might be a stupid question, but have you enabled Python exceptions? Because these would probably help pinpoint what causes the game to stall.

All the "self" business (you can probably see these on pretty much every line) indicates that the generateTerrainAtPlot() function is really a class method. What is the class? Where is the class definition? Are all the fields of this class instance (all the stuff beginning with "self.") defined in the constructor (the line that starts with "def __init__")?

This code can't work on its own, as it is part of a piece of Object-Oriented Programming. With that said, this code could be re-written to work on its own. But the problem is that its invoking another class-method: getLatitudeAtPlot(). Unless we know that exactly that does, it just isn't gonna work. (Someone might of course be able to guess it.)

edit: Could you please change the quote tags to code tags in the OP? Because the whitespace isn't showing and this means no indentation. Its a bit hard to read Python without the aid of indentation!
 
ok i removed the quotes,


im afraid - i dont know what to tell you, since - im no python coder - i cant read those code lines - i have vague understanding of what its suppose to do, but thats it.

i have enabled python expectations, and i do get an error message - but i dont know what to do with it....

anyway, i appreciate your interest.
 
ok i removed the quotes,
No, you need to have the code tags. Look at the toolbox above the compose field. There is the symbol for qoute and next to it is a # symbol. Use that instead and your answer rate on this board will go up. Promise!

im afraid - i dont know what to tell you, since - im no python coder - i cant read those code lines - i have vague understanding of what its suppose to do, but thats it.
I understand completely. You served up some pretty advanced stuff, and taken from its context it means even less... (But the author himself would of course be able to help you.)

i have enabled python expectations, and i do get an error message - but i dont know what to do with it....
Nothing wrong with having "expectations"! ;) But seriously, you need to post those exceptions here so that we can help you out. That is what you do with them. :D

anyway, i appreciate your interest.
Sure, if you find and post - with code tags - the method I was wondering about - getLatitudeAtPlot() - then I might be able to help you for real. :p

What exactly are you trying to achieve, by the way? Change the map during game-play? Simply edit the scenario map? Because it isn't that hard to change the plot type, really...

I don't know what you want with the code you posted, as it seems to be from the Mars Now mod, with Martian deserts, desert longitudes and whatnot. Are you mod-modding a Mars map? :confused:
 
ok i warped it - i think that what you meant right?

"expectations"....oops...

getLatitudeAtPlot - what do you mean?


well - what im trying to do -
you heard of dune wars?
well im working on a version - a bit different then the current one - for my own uses mainly,

and i dont want to have water tiles on the map - i want the map to be all land terrain - and the original shape of each map script, to remain - meaning - like im playing archipelago script - instead of the water tiles, i want to have desert A type terrain for coasts and desert B type
instead of ocean.
and in the game land units will be able to walk all over.

its not for a scenarion, but a code that ill be able to inseret into alomost any map script.
 
ok i warped it - i think that what you meant right?
With the code tags enabled I can immediately see that there is a problem with the indentation levels. It looks like you've merged code from three different sources without correcting the indentation. Do you know anything about what I'm talking about? This i pretty basic stuff and you should know about it if you're even gonna edit a Python file!

Anyway, it should (probably) look like this:
Spoiler :
Code:
    def generateTerrainAtPlot(self,iX,iY):
        lat = self.getLatitudeAtPlot(iX,iY)
        gc = CyGlobalContext()

        if (self.map.plot(iX, iY).isWater()):
            ###changed for mars now
            iTerrain = self.map.plot(iX,iY).getTerrainType()
            if iTerrain == gc.getInfoTypeForString("TERRAIN_COAST"):
                self.map.plot(iX, iY).setPlotType(PlotTypes.PLOT_LAND, false, false)
                self.map.plot(iX, iY).setTerrainType(gc.getInfoTypeForString("TERRAIN_DESERT_WASTE"), false, false)
            if iTerrain == gc.getInfoTypeForString("TERRAIN_OCEAN"):
                self.map.plot(iX, iY).setPlotType(PlotTypes.PLOT_LAND, false, false)
                self.map.plot(iX, iY).setTerrainType(gc.getInfoTypeForString("TERRAIN_DEEP_DESERT"), false, false)                                
            return self.map.plot(iX, iY).getTerrainType()
            ###change end
        
        terrainVal = self.terrainGrass

        if lat >= self.fSnowLatitude:
            terrainVal = self.terrainIce
        elif lat >= self.fTundraLatitude:
            terrainVal = self.terrainTundra
        elif lat < self.fGrassLatitude:
            terrainVal = self.terrainGrass
        else:
            desertVal = self.deserts.getHeight(iX, iY)
            plainsVal = self.plains.getHeight(iX, iY)
            if ((desertVal >= self.iDesertBottom) and (desertVal <= self.iDesertTop) and (lat >= self.fDesertBottomLatitude) and (lat < self.fDesertTopLatitude)):
                terrainVal = self.terrainDesert
            elif ((plainsVal >= self.iPlainsBottom) and (plainsVal <= self.iPlainsTop)):
                terrainVal = self.terrainPlains

        if (terrainVal == TerrainTypes.NO_TERRAIN):
            return self.map.plot(iX, iY).getTerrainType()

        return terrainVal
getLatitudeAtPlot - what do you mean?
Find the passage in the code that starts with
Code:
        def getLatitudeAtPlot(self, iX, iY):
If you can't find it, then that is probably one of you potentially many problems. (The generateTerrainAtPlot() method can't get away with calling an undefined method, now can it?)

and i dont want to have water tiles on the map - i want the map to be all land terrain - and the original shape of each map script, to remain - meaning - like im playing archipelago script - instead of the water tiles, i want to have desert A type terrain for coasts and desert B type
instead of ocean.
and in the game land units will be able to walk all over.
Ok, its for map scripts then... Are you certain where to insert this code of yours? Because it has to be part of a class, meaning there should be a line like:
Code:
class ThisIsAClass:
...before the code you've inserted. And all the variables starting with self. needs to be defined somewhere, probably in the constructor - starting with:
Code:
        def __init__(self...
Otherwise it won't work.

its not for a scenarion, but a code that ill be able to inseret into alomost any map script.
As I've yet to dabble with map scripts myself, I'll just let someone else take it from here... :p
 
The way mapscripts work is that each class (like the TerrainGenerator class) subclasses a class found in CvMapGeneratorUtil. Therefore, functions like getLatitudeAtPlot don't need to be defined in a mapscript- functions are only defined if you want to change them. (That's why Continents.py has almost no code other than calls to a set of default classes in CvMapGeneratorUtil).

As someone who's had mapscript trouble before, here are my two cents:

1. Often, I've noticed that Python exceptions don't get printed when a mapscript freezes up, even if they happen. If logging is turned on, they'll be printed to PythonErr.log, so you might want to take a look there after exiting Civ.

2. The TerrainGenerator of a mapscript doesn't work the way you think. It returns an array of terrain types, rather than set plots to use a specific terrain. That's why getTerrainAtPlot returns a terrainType, which is then appended to the array (I think it might be a list, actually).

So you don't want to be setting terrain types in the TerrainGenerator. Instead, you want to say:

Code:
            if iTerrain == gc.getInfoTypeForString("TERRAIN_COAST"):
                self.map.plot(iX, iY).setPlotType(PlotTypes.PLOT_LAND, false, false)
                terrainVal = gc.getInfoTypeForString("TERRAIN_DESERT_WASTE")

Also, Baldyr, Python functions (and other statements) don't have to be part of a class. In fact, if you're writing a module (a library) it's easier to not use any classes- unless, of course, you're dealing with objects and have to. It's just as valid to have functions on the first indentation level as to have them in the second indentation level under a class. For instance, a mapscript contains several top-level functions calling classes.
 
So you don't want to be setting terrain types in the TerrainGenerator.

Does it make a difference?

Because i use a simpler version of the code (i only place one type of terrain for water, i don't make a difference), and it works okay.
 
TC01, Baldyr, hi.

well, python is Chinese to me, but through your help guys, im learning some of the meanings,
so thanks for the much info on the subject!

i have turned on the python logging - saw there was an error - something about butinit failed to load.


ok i have tried your code tc01, but i got a bunch of python errors upon loading:
Code:
def generateTerrainAtPlot(self,iX,iY):
        lat = self.getLatitudeAtPlot(iX,iY)
        gc = CyGlobalContext()

        if (self.map.plot(iX, iY).isWater()):
            ###changed for mars now
            iTerrain = self.map.plot(iX,iY).getTerrainType()
            if iTerrain == gc.getInfoTypeForString("TERRAIN_COAST"):
                self.map.plot(iX, iY).setPlotType(PlotTypes.PLOT_LAND, false, false)
                terrainVal = gc.getInfoTypeForString("TERRAIN_DESERT")
            if iTerrain == gc.getInfoTypeForString("TERRAIN_OCEAN"):
                self.map.plot(iX, iY).setPlotType(PlotTypes.PLOT_LAND, false, false)
                terrainVal = gc.getInfoTypeForString("TERRAIN_DESERT")
            return self.map.plot(iX, iY).getTerrainType()
            ###change end
        
        if lat >= self.fSnowLatitude:
            terrainVal = self.terrainIce
        elif lat >= self.fTundraLatitude:
            terrainVal = self.terrainTundra
        elif lat < self.fGrassLatitude:
            terrainVal = self.terrainGrass
        else:
            desertVal = self.deserts.getHeight(iX, iY)
            plainsVal = self.plains.getHeight(iX, iY)
            if ((desertVal >= self.iDesertBottom) and (desertVal <= self.iDesertTop) and (lat >= self.fDesertBottomLatitude) and (lat < self.fDesertTopLatitude)):
                terrainVal = self.terrainDesert
            elif ((plainsVal >= self.iPlainsBottom) and (plainsVal <= self.iPlainsTop)):
                terrainVal = self.terrainPlains

        if (terrainVal == TerrainTypes.NO_TERRAIN):
            return self.map.plot(iX, iY).getTerrainType()

        return terrainVal


edit:
the_j, yeah its so weird, your code for one terrain works perfect - once we get that second terrain, all goes down the drain...
 
Oh, right.

Then I'm now thinking the way is it generates the plot type, puts down a default terrain for that plot type (Ocean for water and Grassland for everything else, I think?), then does get a list of terrain types. So maybe you can set terrain type in the feature generator.

What were the Python exceptions when you changed it to set terrainVal?
 
Also, Baldyr, Python functions (and other statements) don't have to be part of a class.
No, of course not. (Once upon a time I actually did think so. :rolleyes:) What I did mean was that the code posted in the OP clearly would have to be part of a class, so I was curious as to what it was. Otherwise all those references to "self" would have to be taken out, as they refer to the class instance it-self. This is also why I said the class method could have been rewritten as a class-less function. But that is of course no good as its actually part of a map script, which as you say works with classes. :p
 
hi people,

well this is the error i get upon loading the game:

attachment.php



also -i have added the map script.


maybe someone can solve this...
 

Attachments

Quite obvious error, if you use the python editor for merging ;).

Fixed the indentation, see the attachment.
Haven't tested it.

Then I'm now thinking the way is it generates the plot type, puts down a default terrain for that plot type (Ocean for water and Grassland for everything else, I think?), then does get a list of terrain types.

:think: mmhh...i wish i had some time to investigate this further. No idea at this point :dunno:.
 

Attachments

WOW!

thanks the_j!

finally i get a code that works!!!

im so happy right now i can....i....can.....Take On The world!! (day of the tentacle).

i simply dont believe this - the problem was the spacing of the lines? this is so python typical!

thanks again, now i can continue my work!

edit: humm... i was too early to be happy - it works - but all i see is grass instead of land - im now checking with another terrain.



nope,
its semi working - it seems that all i get is grass terrain now - its kind of ignoring the terrain replacing and putting grass over ocean and coast no matter what.


maybe its because of this : terrainVal = self.terrainGrass
 
I think the problem is in this part:
Code:
		if (self.map.plot(iX, iY).isWater()):
			###changed for mars now
			[COLOR="Red"]iTerrain = self.map.plot(iX,iY).getTerrainType()[/COLOR]
			if [COLOR="red"]iTerrain [/COLOR]== gc.getInfoTypeForString("TERRAIN_COAST"):
				self.map.plot(iX, iY).setPlotType(PlotTypes.PLOT_LAND, false, false)
				[COLOR="darkslateblue"]terrainVal = gc.getInfoTypeForString("TERRAIN_DESERT")[/COLOR]
			if [COLOR="red"]iTerrain [/COLOR]== gc.getInfoTypeForString("TERRAIN_OCEAN"):
				self.map.plot(iX, iY).setPlotType(PlotTypes.PLOT_LAND, false, false)
				[COLOR="DarkSlateBlue"]terrainVal = gc.getInfoTypeForString("TERRAIN_DESERT")[/COLOR]
			[COLOR="SeaGreen"]return self.map.plot(iX, iY).getTerrainType()[/COLOR]
			###change end
You check if the plot is sea, change it to land and set the value of terrainVal to desert. The problem is terrainVal is never used in this case, it returns the default terrain for land, grass. Change it to return the terrainVal and it should work.
 
i simply dont believe this - the problem was the spacing of the lines? this is so python typical!
No, this is so typical of folk who don't even wanna learn how to do things the proper way. :rolleyes: Like, you don't even try to merge any Python code if you don't know how indentation works. Because the two sets of code might have incompatible indentation - not to speak that you might get the indentation level wrong...

I'm only happy to help out, but getting a whole bunch of people to look at your problem because you haven't bothered to look it up yourself is... kinda lame. :p

But I'm glad it worked out for you in the end - and that you perhaps gained some knowledge in the process.

And also: No, you're not any kind of "merger" if you don't know how to merge properly. That only makes you a merger wannabe. :p

And finally: Don't blame Python. This programming language is allowing you to do some pretty amazing things - and if you would just pick up a textbook you might be able to do all sorts of cool thing on your own. Its very lame to complain about indentation with Python if you don't even know what it does!

ps Sorry for the rant! :rolleyes:
 
yeah a lot of rant....

but, its not all true,

i have tried and i only post things as a last resort, i have spent over 20 hours with trying to get it right, i have bothered a lot believe me. although i cant read what the cod does exactly, i have busted my self tring to figure out what wrong, mixing lines and what ever.
also i have gotten the solution before i saw NotSoGood post.

also, i tak pride in calling y self a merger - i have 3 mods behind me that can prove it, i have merged and updated countless modpack together over the years, and maybe i dotn know to read programing language but i do a good job in getting two sdk codes together.
also python - i have done a lot of stuff there by merging stuff, fixing tons of errors ive had.

im no expert, sure, the python is not to blame , i know that you can do anything with the tools firaxis provided us with, but lame i am not.

as i said posting help requests are always the last thing i do, but when i need something, im not ashamed to ask for friends help here in the forum, what are these threads for if not asking for help?
what can i do, i dont know anything, but what can i say for certain that everything i do here, is for civ4 players, haven't played my mod a full game ever...im just modding modding modding.

so, Baldyr, for someone who have absolutely no idea of what c++ or python says, i would say, im an pretty ok merger...

ok now probably one of the moderators will lock this thread since were getting of the subject here,
so lets just say, everything is fine , and i truly grateful to you and the rest of the people who posted here.

cheers :)
 
Back
Top Bottom