trying to use a minimalist mod to do big things

Ok, here are the problems with your code:
Code:
		getAdjacentList(pRome)
The getAdjacentList() function takes a tuple containing two integers as the argument. You are giving it a CyPlot instance. These things are a world apart as far as types go.

Secondly, you should probably assign the return value of getAdjacentList() to some name/variable, not? Otherwise the interpreter won't know what the name tCoords is referring to:
Code:
		x, y = tCoords
Because trying to unpack a data structure that doesn't exist will cause an exception.

Also make sure your indentation levels match up, because the code you posted doesn't look right.
 
ah, now the message it gives me when using pRome makes more sense! but in following what you originally put, AdjacentList(34, 43) it counts that as two arguments unless I put ((34, 42)) (just making numbers up, here...

now, for the coords, the AdjacentList function returns the SquareList function which returns a PlotList with x, y. should the return be added to the end of either of those helper functions or into the function I'm working on before the x, y = tCoords line?
 
ah, now the message it gives me when using pRome makes more sense! but in following what you originally put, AdjacentList(34, 43) it counts that as two arguments unless I put ((34, 42)) (just making numbers up, here...
Yeah, exactly. But you could of course make your own version of these helper functions (or only make one for yourself) that either takes two integer values instead of the tuple. Or one that takes a CyPlot instance - the way you originally tried to use it.

now, for the coords, the AdjacentList function returns the SquareList function which returns a PlotList with x, y. should the return be added to the end of either of those helper functions or into the function I'm working on before the x, y = tCoords line?
Hmm... I'm not sure I follow. Can you exemplify with some code?

Basically you can't reference something that you haven't already defined. So if a line contains a name (variable, function, class, method) that isn't already in the name space of that module, then it doesn't compute.

About names and name spaces: You can actually delete the gc = CyGlobalContext() assignment statement from your module. :eek: Try commenting it out and you'll see that the interpreter can still recognize the name "gc". How can this be? (Lets see if you can figure it out. There is a lesson in here in any case.)
 
when I put the code this way:
Spoiler :
Code:
#compiles a list of plots
def getPlotList(tBL, tTR):
        lPlotList = []
        for x in range(tBL[0], tTR[0]+1):
                for y in range(tBL[1], tTR[1]+1):
                        lPlotList.append((x, y))
        return lPlotList

#gets all tiles within the given distance of the tile given
def getSquareList(tCoords, iDistance):
        return getPlotList((tCoords[0]-iDistance, tCoords[1]-iDistance), (tCoords[0]+iDistance, tCoords[1]+iDistance))

#gets all tiles adjacent to the tile given
def getAdjacentList(tCoords):
        return getSquareList(tCoords, 1)


#spawns the classical civs 800BC on the map (different date used for testing change before release)
def classicalSpawn():
	pRome = cyMap.plot(61, 46)
	pPersia = cyMap.plot(81, 41)
	pJapan = cyMap.plot(115, 46)
	pKorea = cyMap.plot(109, 46)
	if isDate(-3985):
		getAdjacentList((61, 46))
		for tCoords in lPlotList:
				x, y = tCoords
				pCurrentPlot = cyMap.plot(x, y)
				if pCurrentPlot.isCity():
						pCity = pCurrentPlot.getPlotCity()
						pCity.kill()
		PyPlayer(7).initCity(61, 46)
		pPersia.getPlotCity().kill()
		PyPlayer(8).initCity(81, 41)
		pJapan.getPlotCity().kill()
		PyPlayer(9).initCity(115, 46)
		pKorea.getPlotCity().kill()
		PyPlayer(10).initCity(109, 46)
#Romans
		PyPlayer(7).initUnit(4, 61, 46, 2)
		PyPlayer(7).initUnit(5, 61, 46, 2)
		PyPlayer(7).initUnit(57, 61, 46, 15)

it returns an error that says "lPlotList is not defined"...I thought that's what the line "return lPlotlist" was doing...

it's beef is still with the "x, y = tCoords" line
 
Each function--classicalSpawn() above--has its own collection of local names (variables) that only it has access to. When you define a variable in one function, its name is not available to any other function. A return <variable> statement returns only the value of the variable, not its name.

The expression "getAdjacentList((61, 46))" results in an unnamed list of coordinate tuples. If you don't assign it to a variable in classicalSpawn(), it disappears. Try this:

Code:
lPlotList = getAdjacentList((61, 46))

and if you only need that list in the for-loop you can combine them:

Code:
for tCoords in getAdjacentList((61, 46)):
    x, y = tCoords

or even further

Code:
for x, y in getAdjacentList((61, 46)):
    pCurrentPlot = cyMap.plot(x, y)

Don't worry if you don't understand these combined forms. You don't need to use them, but I often find it easier to understand something if I see an example written a couple different ways.
 
oh, no...I do too. Thank you so much! I will try this right away and report back what it does. Thanks again, I've been puzzling that out all day...
 
that was the missing key...it worked perfectly!

now for the complication - I need to make the city spawn with a population of 3, culture of 1000, and a few buildings like walls. I'm guessing that I should simply include a line that changes those elements and adds the building after the new city is spawned. I'm going to check the API to see what I can use to do those things.

after that, I need to take an opposite-corner tuple definition (tRome) and have it flip all culture, cities and units in that area to Roman control...the culture doesn't need to be 100% or to lack any other kind of culture, I'm just looking to make it overwhelmingly theirs on those tiles so that the romans will have access to all their resources. and after that (yeah, I'm two steps ahead) I need to code a popup that asks the human permission to flip the larger area (but flips just the city and sets them at war if they refuse)
 
Those are all doable in the Python API.

Change the population: pCity.setPopulation()
Change culture: pCity.changeCulture(1000) [I think this is correct]
Add a building: pCity.setNumRealBuilding(getInfoTypeForString("BUILDING_WALLS"), 1)

One thing I find helpful with the API when I know what object (class) needs to receive the message (in this case CyCity) is to switch to one-class-per-page view. There's a link in the top left for All Classes and another for Single Class or something like that. Click the latter one. Now the right side shows only the methods for a single class. Click CyCity and you can now use Find in your browser to find things related to culture, for example.
 
Yes, it is a big help to be able to eliminate the other classes.

I looked up those codes and implemented them. So now that all works. The next step is to get the larger area flip, complete with all units and cities on those tiles.
 
alright...got the flip to happen. It spawns one archer automatically. Spawning units on plots that are flipped cities, or flipping the units that exist is a little trickier, and it will have to wait until tomorrow.
 
because it's already in CvEventManager.py, which is imported at the start of the file?
Are you still importing CvEventManager. You don't need that, ever.

But yeah, that is basically the answer. I was thinking about PyHelpers though, as your importing it with:
from PyHelpers import *
The asterisk stand for "all/any" and you get the works. This is convenient but also unpredictable, as all of it is tacked on to the global name space of your module. The potential problem is that you're importing more stuff that you can keep track of. So there is the potential for one name overwriting another, causing issues that would be very hard to debug. So there is a price for the convenience.

You should probably keep your own gc definition though - because you might get rid of PyHelpers in the future and then it would be confusing to realize how why the name isn't recognized any more...
 
alright...got the flip to happen. It spawns one archer automatically. Spawning units on plots that are flipped cities, or flipping the units that exist is a little trickier, and it will have to wait until tomorrow.
I'm not sure you wanna go though the motions of "flipping" units, because I suspect that can't really be done. The way Rhye did it was that he firstly spawned duplicate units in Antarctica (plot 0, 0), killed the original units, flipped the target plot itself, then spawned the new units for the flipping player, then killed the duplicate units and covered up the terrain once again.

Unless there is a less painful method for doing it I'd suggest you let this be a "minimalist" mod... :p
 
after that, I need to take an opposite-corner tuple definition (tRome) and have it flip all culture, cities and units in that area to Roman control...
Note that the return value of getAdjacentList(tSpawnPlot) should get you the same 9 tiles that are defined in tRome, so unless you need to expand the 3x3 area into some other area you don't really need those tuples defining the areas...

Furthermore, you're already looping through the tiles once - you don't need to make a separate loop for each method. You can do the killing, the spawning, the tile conversion and all the city additions in one single loop, even if you could define separate functions for each task, and call on them from inside the loop:
Code:
pPlayer = gc.getPlayer(ePlayer)
for tCoords in lPlotList:
    x, y = tCoords
    pPlot = cyMap.plot(x, y)
    killPlot(pPlot)
    addCulture(pPlot, ePlayer)
    flipCity(pPlot, pPlayer)
    spawnCity(pPlot, pPlayer, name, iSize)
By making these functions generic (instead of specific for the Roman flip) you can re-use them in any other context. This will save you a lot of work in the long run!

Also, don't start to script any other spawns other than the Roman one just yet. Because instead of copy-pasting the code you just did and editing it you could (should) just make it into a generic function instead. Then all the (ancient) spawns can share the same code. (We can help you with this.)
 
works for me
Not me. :D I never implemented anything like it in PyScenario - and thus far no one has requested such functionality... :p

You could at least save this for last, or something. Because its pretty messy to implement. It'll get you sidetracked for some time, when you could move forward instead.
 
As a side note: I have some code in PyScenario that spawns a unit on tile 0, 0 in order to temporarily revive dead Civs - and then kills it again and covers up the tiles. This is a edited version of the code that covers up the plot:
Code:
pTeam = pPlayer.getTeam()
for tCoords in getSquareList((0, 0), 2):
    x, y = tCoords
    pPlot = cyMap.plot(x, y)
    pPlot.setRevealed(pTeam, False, True, -1)
But in order for getSquareList() to work at the edge of the map I had to augment the getPlotList() function with:
Code:
def getPlotList(tTL, tBR):
        lPlotList = []
        for x in range(tTL[0], tBR[0]+1):
[B]                if x > 123:
                        x -= 124
                elif x < 0:
                        x += 124[/B]
                for y in range(tTL[1], tBR[1]+1):
[B]                        if y > 67 or y < 0:
                                continue[/B]
                        lPlotList.append((x, y))
        return lPlotList
The RFC code for this is much more rudimentary however...
 
By "works for me" I believe antaine was saying that your suggestion sounded like a good plan and that s/he would use it. It's an American idiom I guess.

Bob: "Let's head to the park and see if we can meet up with Sean."
Me: "Works for me. Let's go!"
 
yes, by "works for me" I was agreeing with your suggestion to keep it minimalist.

Now...the next stage of this whole process is a bit more complicated...I need to create a popup that asks a human player permission to let the flip occur if they would be losing anything (at this point, it's just cities that would be affected - units get moved). If consent is given, the flip will occur just as I've coded. If it is not, then only the initial part (the capital city) will "flip" and war will be set between the new AI and the human who refused. I need any old AIs that stand to lose stuff to automatically consent, and to set war with a list of civs as long as each is not human (in other words, the Romans will start at war with the Greeks and Celts as long as they are AI, but the human gets a choice).

I suppose the most logical (and mundane) place to start is with the popup, no? I know you teach that in your tutorial, so I think I'll go back there and take a look...
 
Damned, the server just ate my reply. This is the short version: Lookup the Popup module in:
\Sid Meier's Civilization 4\Assets\Python\pyHelper\Popup.py

After you figure the actual popup out and have all the values you need, you should probably revisit the chapter on conditional statements (4.4 - 4.7).
 
Back
Top Bottom