Requesting following features

I do like that idea and I did do a little bit on classes so it may be possible. we will have to see :D

before testing: attempted to test, didn't work. thought: why?! remembered: have to put in eventmanager first :lol:!

During my testing: no exceptions, first test was no control over byzantium at first year definition, got the popup - went and conquored byzantium. At the second year definition received my 1000 gold (yay) but didn't get a popup, why? because I didn't make one :lol:

second test was to see if the roman player only worked - it didn't...? I used these if isHuman("Rome") == True: and it's counter part:
Code:
def isHuman(name):
    pPlayer = Civ(name)
    if pHumanCiv == pPlayer:
        return True
    else:
        return False
    #Use brackets to define name, e.g. isHuman("Rome") == True
and yes I used the defined Human in the Utils: pHumanCiv = instance(Game.getActivePlayer())
whats wrong?

third test: conquored byzantium before first year definition and got alternate popup - Yay! waited the 30 turns to find out whether my new victory popup will work, spartacus razed tarrentum (forgot about him :p) but doesn't take rome :D senate gives me 1000 gold and popup appears!

fourth test: don't conquor byzantium - senate doesn't reward me :(

So, in conclusion - Everything worked perfectly (except for rome only)!!!

EDIT: ok, as I can think of no more events to do and I want a challenge, I will use my helper functions (in fact I could use my hasCivLostCity() function for a mission!) to design a little feature then! Can you explain a little about dictionaries (don't really know much about them...) I might need a few more little functions which you may need to help on too though!
 
Code:
from Utils import *
from CustomFunctions import *
##Senate Feature##
#This feature displays messages to Rome to ask them to do stuff, the events#
#(missions) are defined here!#

##constants##
#none
class Mission:
    def __init__(self, tCoords, iStartYear, iEndYear, Reward, popHeader, popMessage1, popMessage2\
                 , ePlayer):
        self.tCoords = tCoords
        self.Start = iStartYear
        self.End = iEndYear
        self.Reward = Reward
        self.Header = popHeader
        self.Message1 = popMessage1
        self.Message2 = popMessage2
        self.ePlayer = ePlayer
    def GoldMission(self):
        if isCivHuman("Rome") == True:#until function is fixed
            if isDate(self.Start):
                if isPlotOwner(self.tCoords, self.ePlayer) == True:
                    showPopup(self.Header, self.Message1)
                else:
                    showPopup(self.Header, self.Message2)
            elif isDate(self.End):
                if isPlotOwner(self.tCoords, self.ePlayer) == True:
                    showPopup(self.Header, "The Senate notes that you have succeeded in your mission and rewards you with ",self.Reward," gold!")
                    giveGold(self.Reward)
                else:
                    showPopup(self.Header, "The Senate notes that you have failed the mission it set you, you will not be rewarded!")
    def UnitMission(self):
        if isCivHuman("Rome") == True:
            if isDate(self.Start):
                if isPlotOwner(self.tCoords, self.ePlayer) == True:
                    showPopup(self.Header, self.Message1)
                else:
                    showPopup(self.Header, self.Message2)
            elif isDate(self.End):
                if isPlotOwner(self.tCoords, self.ePlayer) == True:
                    showPopup(self.Header, "The Senate noted that you have succeeded in your mission and rewards you with ",self.Reward," units of Praetorians!")
                    spawnUnits(eRome, ePraetorian, self.tCoords, self.Reward)
                else:
                    showPopup(self.Header, "The Senate notes that you have failed the mission it set you, you will not be rewarded!")

meet the start of my Generic Senate Mission Class!
does it work all fine do you think?

What I need at the moment is a helper function which find the co-ordinates of ePlayer's capital city (as it may not always be Rome) for Unit mission's Unit Spawn (I want it at the capital not target city...)

oh and would I use

Code:
def isPlotCity(tCoords):
    """
    returns if a plot is a city or not!
    """
    pPlot = getPlot(tCoords)
    if pPlot.isCity():
        return True
    else:
        return False

to say whether a certain plot is a city or not? If so this needs to be added to the class and the senate event!

And finally would this be what I would use to define the Senate event (if it was moved)?
Code:
##Byzantium Prompt##
iByzantiumStartYear = 1050
iByzantiumEndYear = 1350
iByzantiumGold = 1000
senateHeader = "Senate"
byzantiumMessage1 = "The glorius Senate of Rome requests that you take the city of Byzantium. If you take it and hold it at the end of 30 turns (turn 195) you will be greatly rewarded"
byzantiumMessage2 = "The glorius Senate of Rome wishes that you make sure that you keep control of Byzantium by the end of 30 turns (turn 195). If you successful, you will be rewarded!"
tByzantium = (46, 23)

Byzantium = Mission(tByzantium, iByzantiumStartYear, iByzantiumEndYear, iByzantiumGold, senateHeader, byzantiumMessage1, byzantiumMessage2)
Byzantium.GoldMission()
 
I'm on my lunch break so this is going to be short:

Try the other isHuman() function I posted (the multiplayer valid one), for now.

You're basically on the right track with the Mission class business! :goodjob: Color me impressed! :eek2:

This is what you need to know about dictionaries.

You can get the capital of a player with CyPlayer.getCapitalCity().
 
so this helper function:
Code:
def getCapital(ePlayer):
    pPlayer = gc.getPlayer(ePlayer)
    pCapital = pPlayer.getCapitalCity()
    pCapitalPlot = getPlot(pCapital)
    return pCapitalPlot
Would be used in: spawnUnits(eRome, ePraetorian, getCapital(eRome), 3)
to spawn 3 roman praetorians in the roman capital?

you didn't say if this would work?
Code:
def isPlotCity(tCoords):
    """
    returns if a plot is a city or not!
    """
    pPlot = getPlot(tCoords)
    if pPlot.isCity():
        return True
    else:
        return False
Because this could greatly improve the senate event and mission class!

and with these two functions in mind:
Spoiler :

Code:
from Utils import *
from CustomFunctions import *
##Senate Feature##
#This feature displays messages to Rome to ask them to do stuff, the events#
#(missions) are defined here!#

##constants##
#none
class Mission:
    def __init__(self, tCoords, iStartYear, iEndYear, Reward, popHeader, popMessage1, popMessage2\
                 , ePlayer):
        self.tCoords = tCoords
        self.Start = iStartYear
        self.End = iEndYear
        self.Reward = Reward
        self.Header = popHeader
        self.Message1 = popMessage1
        self.Message2 = popMessage2
        self.ePlayer = ePlayer
    def GoldMission(self):
        if isHuman("Rome") == True:#until function is fixed
            if isDate(self.Start):
                if isPlotOwner(self.tCoords, self.ePlayer) == True and isPlotCity(self.tCoords) == True:
                    showPopup(self.Header, self.Message1)
                else:
                    showPopup(self.Header, self.Message2)
            elif isDate(self.End):
                if isPlotOwner(self.tCoords, self.ePlayer) == True and isPlotCity(self.tCoords) == True:
                    showPopup(self.Header, "The Senate notes that you have succeeded in your mission and rewards you with ",self.Reward," gold!")
                    giveGold(self.Reward)
                else:
                    showPopup(self.Header, "The Senate notes that you have failed the mission it set you, you will not be rewarded!")
    def UnitMission(self):
        if isCivHuman("Rome") == True:
            if isDate(self.Start):
                if isPlotOwner(self.tCoords, self.ePlayer) == True and isPlotCity(self.tCoords) == True:
                    showPopup(self.Header, self.Message1)
                else:
                    showPopup(self.Header, self.Message2)
            elif isDate(self.End):
                if isPlotOwner(self.tCoords, self.ePlayer) == True and isPlotCity(self.tCoords) == True:
                    showPopup(self.Header, "The Senate noted that you have succeeded in your mission and rewards you with ",self.Reward," units of Praetorians!")
                    spawnUnits(eRome, ePraetorian, getCapital(eRome), self.Reward)
                else:
                    showPopup(self.Header, "The Senate notes that you have failed the mission it set you, you will not be rewarded!")

##Byzantium Prompt##
iByzantiumStartYear = 1050
iByzantiumEndYear = 1350
iByzantiumGold = 1000
senateHeader = "Senate"
byzantiumMessage1 = "The glorius Senate of Rome requests that you take the city of Byzantium. If you take it and hold it at the end of 30 turns (turn 195) you will be greatly rewarded"
byzantiumMessage2 = "The glorius Senate of Rome wishes that you make sure that you keep control of Byzantium by the end of 30 turns (turn 195). If you successful, you will be rewarded!"
tByzantium = (46, 23)

Byzantium = Mission(tByzantium, iByzantiumStartYear, iByzantiumEndYear, iByzantiumGold, senateHeader, byzantiumMessage1, byzantiumMessage2)
Byzantium.GoldMission()


I need a little education on subclasses and I need a few ideas on more rewards (there will be a mission I will make which includes my hasCivLostCity() function (the first one I made) probs firing on the games first turn) and mission types (at the moment there is only take city and don't lose any cities)

edit: Actually I have two new reward types and a new mission that I just thought of...
reward - Golden Age (where self.Reward defines turn amount)
reward - Happiness in all cities (where self.Reward defines turn amount)
mission - build/capture wonder (would need help on this type, and this would have to be a subclass because the main class can't define wonders...:think:)

I will have a stroll through the API and see if I can't find something for the 2 reward types...
 
so this helper function:
Code:
def getCapital(ePlayer):
    pPlayer = gc.getPlayer(ePlayer)
    pCapital = pPlayer.getCapitalCity()
    pCapitalPlot = getPlot(pCapital)
    return pCapitalPlot
Would be used in: spawnUnits(eRome, ePraetorian, getCapital(eRome), 3)
to spawn 3 roman praetorians in the roman capital?
What you suggest would be valid if you do this:
Code:
def getCapital(ePlayer):
    pPlayer = gc.getPlayer(ePlayer)
    pCapital = pPlayer.getCapitalCity()
    [B]t[/B]CapitalPlot = [B]getCoords[/B](pCapital)
    return [B]t[/B]CapitalPlot
Because the spawnUnits() function takes a tuple containing integer coordinates as the argument. And this is what the getCoords() function returns. Check it out in the Utils module!

you didn't say if this would work?
It looks ok to me! :goodjob:

I need a little education on subclasses and I need a few ideas on more rewards (there will be a mission I will make which includes my hasCivLostCity() function (the first one I made) probs firing on the games first turn) and mission types (at the moment there is only take city and don't lose any cities)
Lets just start with the Mission class before we even decide that there even needs to be any sub-classes. As fun as it is to write code, you should take one step back and work on the design of this feature before moving forward. And be advised that making the class and defining the actual missions is only haft the job. There will need to be a event interface for running all this and the project will start to become complex very fast! (I already did this with PyScenario.) But if you're up for the challenge, why not?

edit: Actually I have two new reward types and a new mission that I just thought of...
(...)
I will have a stroll through the API and see if I can't find something for the 2 reward types...
Don't forget to look in the CyTeam class for methods! There might also be stuff in CyGame. Other than that, the PyScenario crew has already thought about these things, so you could also take a look in the PyScenario API (link in the sig).
 
what sort of interface?:D

well I is clear that for a wonder related mission you would need a new class for example it should have the values:

wonder
iyear
iendyear
reward

and would have to have new features to define is a wonder has been built (if yes the popup would be capture wonder and if no then you would be instructed to build it!)

I couldn't find anything in pysenario for goldenage or happiness?
 
what sort of interface?:D
I don't know if "interface" is the word I'm looking for, but lets propose that you have a class (or some classes) and then you define individual instances of that class in a dictionary (or whatever).

Firstly there needs to be some code for picking that information up in the dictionary and creating the actual class instances - based on the dictionary entries.

But how would those instances be looked up on a turn-to-turn basis? You don't wanna recreate all instances every single turn just to check the game date against the start/end conditions. You might as well put those instances in an array of some sort (like a list) and iterate through them in order. (Expired missions could be deleted to save on processing time for further runs.)

The fun doesn't end there, however, because you either need to recreate all Mission instances every time the game is loaded/resumed - or you need to save them in between game sessions.

So I suggest we take this in strides and start with the design aspect of the feature. Like the conditions - will there only be conditions relating to historical dates? Is there always a start and an end date? Could some game event prompt the Senate to make a request to the player? How would the Senate react to the player losing the capital? Or could it reward a glorious victory on the battlefield? (I'm not saying that you need to complicate things, only to think your design through.)

The actions/effects can be handled in a variety of different ways, and you may or may not need more than one class. You already demonstrated how a Mission instance could be customized by invoking a method on it. There is no right or wrong way, or any one way to go about this. We just have to take your actual design into account when writing the code.

Anything you can learn about Python will be useful when doing this, except file I/O operations (even if pickling might come handy). So a you could just take some time to read through a textbook - you'd be well equipped to tackle this if you do.

I couldn't find anything in pysenario for goldenage or happiness?
Note that you won't be able to use any of the PyScenario methods. But those are in turn based on the Python API, so anything that can be achieved with PyScenario can be done with "regular" Python also.

You probably wanna read the method documentation to figure out what they do. And there are Actions for triggering Golden Ages and for adding happiness to cities (individual or whole empires), among other things. Like city flips or migration of population. What about spawning those auxiliary units in conquered cities by the order from the Senate, by the way? :king:
 
not historical but pretty much random. I can't really understand dictionaries at the moment (yes I understand classes but not dictionaries :lol:)

The glorious victory sounds good...:think: maybee if a unit wins a battle with a percentage chance of him winning being less than 5%?

I was thinking of an event (on the way to shop :lol:) where the senate asks you to conquor ALL the cities in range of a pair of coordinates (like how you defined the pictish power) and spawn 2 units in each city there (now that may be difficult :rolleyes:)

maybee the senate and the rebel modcomp could be linked? say if rome experiences a civil war (not the byzantium flip) then the senate may order Rome to "Obliterate" them (oh how evil that sounds :satan:) or to support the rebellion of another civ?

For the moment I will keep my class (and event) where it is and look through the API to find rewards and think of mission types. and when I have compiled my list of helper functions and my mission ideas, then we can struggle through designing the whole thing...

also how are you getting along with the rebels event/catapult construction code/anything else that I have now forgotten and will have to read this thread again to find out what it was coming along?

sound good to you?
btw, how do those event ideas sound to you and do you think they would work?

edit: in regard to start and end dates, I put them there as a way of making it work... of course it doesn't need to be there (but in some events it will be) but then how do we define when the event ends (we can make it too easy for them can we? I mean a limit of 300 turns may be a little too long)
 
not historical but pretty much random. I can't really understand dictionaries at the moment (yes I understand classes but not dictionaries :lol:)
Its not necessary to use dictionaries, and we can totally start with only one actual mission and get it working with the class setup. Then we can start to worry about how we wanna define more than one, and using some type of array seems like an option.

The glorious victory sounds good...:think: maybee if a unit wins a battle with a percentage chance of him winning being less than 5%?
I'm not sure if that exact condition would work in practice, but something along those lines. (Like when a unit wins and is unharmed while the defeated unit is of equal or greater strength.) But another word of caution: Your initial approach relied only on the BeginGameTurn event callup (in the Event Manager). If you wanna include various different event callups, then you end up with something like PyScenario... :p Much more work. :p

I was thinking of an event (on the way to shop :lol:) where the senate asks you to conquor ALL the cities in range of a pair of coordinates (like how you defined the pictish power) and spawn 2 units in each city there (now that may be difficult :rolleyes:)
Why not? You wouldn't wanna display map coordinates in the pop-up though.

maybee the senate and the rebel modcomp could be linked? say if rome experiences a civil war (not the byzantium flip) then the senate may order Rome to "Obliterate" them (oh how evil that sounds :satan:) or to support the rebellion of another civ?
Yeah, but it would require some effort to interlink the two. But anything is possible, I guess...

For the moment I will keep my class (and event) where it is and look through the API to find rewards and think of mission types. and when I have compiled my list of helper functions and my mission ideas, then we can struggle through designing the whole thing...
There are several ways of setting up the class/classes and their methods. I can give you some ideas once we get there.

also how are you getting along with the rebels event/catapult construction code/anything else that I have now forgotten and will have to read this thread again to find out what it was coming along?
I have practically no time at all this week, but I should get around to it during the winter holidays. Actually, I hope to finish my own portion of this mod. Then I can go into support mode and help you figure out the rest (Python wise, anyway).

sound good to you?
btw, how do those event ideas sound to you and do you think they would work?
Its too early to tell. Work on the design and read up on Python and we can evaluate everything once you're done. Reading up on the Python API and looking up event callups in the Event Manager (listed at the beginning) will give you loads ideas for missions.

edit: in regard to start and end dates, I put them there as a way of making it work... of course it doesn't need to be there (but in some events it will be) but then how do we define when the event ends (we can make it too easy for them can we? I mean a limit of 300 turns may be a little too long)
The big question is whether or not you wanna check every single mission for completion every single turn, or simply wait untill the end date and verify success/failure then? The former is probably better but will require significantly more work - and will also slow the game down. The latter is relatively easy to achieve.
 
I meant that finding every city and spawning 2 units inside would be hard...

I will look for inspiration and get back to you... How are we going to do the ERE spawn btw?

btw: I prefer speed over complexity :lol: so the latter option would be a good one! (because it's just better that way, for event events at least...)
 
I meant that finding every city and spawning 2 units inside would be hard...
Nah, you simply iterate through all tiles, one at the time, and check them with CyPlot.isCity(). If the method return True, then you spawn two units on that tile.

You need a helper function for locating cities on map areas anyway, but I think you could use a generator function for this (using the yield command). I can help out - what is the preferred way to define the area? A pair of tuples containing a pair of integer coordinates each?

I will look for inspiration and get back to you...
I think you should draft up a good many number of missions just to see what the class(es) need to cover. Because once you setup the actual code for it, it will be increasingly difficult to add new things without resorting to... clever things.

How are we going to do the ERE spawn btw?
It depends on how you want the whole thing to go down, like in great detail, with all imaginable exceptions considered. But I think that its a good idea to keep the design itself simple.
 
pair of tuples would be good!

I will think about byzantium aswell then!
 
You could get the cities of an area with this function:
Code:
Map = CyMap()

def findAreaCities(tCoords1, tCoords2):
	"""
	Used for looping. When supplied with the map coordinates of a area defined 
	by its lower left corner (tCoords1) and its upper right corner (tCoords2), 
	the function yields all cities (CyCity instances) in order.
	"""
	iX1, iY1 = tCoords1
	iX2, iY2 = tCoords2
	for iX in range(iX1, iX2 + 1):
		for iY in range(iY1, iY2 + 1):
			pPlot = Map.plot(iX, iY)
			pCity = pPlot.getPlotCity()
			if pCity != None:			
				yield pCity
You could use the function together with this one to find cities belonging to a certain player within a certain area:
Code:
def isPlayerCity(pCity, ePlayer):
	"""
	Returns True if pCity belongs to ePlayer. Otherwise returns False.
	"""
	if pCity.getOwner() == ePlayer:
		return True
	else:
		return False
To check the are for ownership of cities:
Code:
def isAreaOwner(ePlayer, tCoords1, tCoords2):
	"""
	Returns True if all cities in the area defined by tCoords1 and 
	tCoords2 belong to ePlayer. Otherwise returns False.
	"""
	for pCity in findAreaCities(tCoords1, tCoords2):
		if not pCity.isPlayerCity(pCity, ePlayer):
			return False
	return True
And to spawn units in all cities in area:
Code:
def spawnAreaCityUnits(ePlayer, tCoords1, tCoords2, eUnitType, iNumUnits)
	"""
	Spawns iNumUnits units of eUnitType for ePlayer in all cities 
	in the area defined by tCoords.
	"""
	for pCity in findAreaCities(tCoords1, tCoords2):
		tCoords = getCoords(pCity)
		spawnUnits(ePlayer, eUnitType, tCoords, iNumUnits)
Now would be a good time to look into the for-in statements and what they do. The range() function, by the way, returns a list array defined by its arguments. So range(4) would return the list [0, 1, 2, 3] (= a list with four entries beginning with zero). And range (1, 5) would return [1, 2, 3, 4] (= a list ranging to the fifth integer value counting from zero, beginning with the integer value of 1).
 
thanks! I will add these to custom functions. So they all reference each other then? so I would use

if isAreaOwner(eRome, findAreaCities(self.Coords1, self.Coords2)):
spawnAreaCityUnits(eRome, self.Coords1, self.Coords2, ePraetorian, self.Reward)

to say that if rome owns all cities in an area then spawn 2 units in each of his cties there?
 
No, the findAreaCities() function is a generator function and will yield one CyCity at a time. So you need to learn how the for-in statements work. I gotta run, talk to you later.
 
I'm sure there are good sources on this subject available out there, but I'll give it a try. Lets say that you have this tuple:
Code:
tValues = (True, False, None)
And you wanna iterate trough those values in order:
Code:
for value in tValues:
    print value
This would print out:
Code:
>> True
>> False
>> None
It is commonly used with lists and the range() function in CivIV Python code. So this:
Code:
for iValue in range(4):
Is the same as going:
Code:
lValues = [0, 1, 2, 3]
for iValue in lValues:
Now, the range() function returns a list array. There is also a xrange() function which doesn't return anything but is instead a generator function. But it works just the same:
Code:
for iValue in xrange(4):
The difference is that the interpreter doesn't have to go trough the trouble of creating a new list every time you want the program to iterate through some integer values. :rolleyes:

If xrange() itself was written in Python code (it isn't) it would probably look something like this:
Spoiler :
Code:
def xrange(iRange):
	iValue = 0
	while iValue < iRange:
		yield iValue
		iValue = iValue + 1
Don't add this to your other helper functions as this is already built into Python!

So, the yield command turns the function into a generator function. Each time the code hits the yield line it will return the current value (the variable iValue in this example). Note however that the function isn't exited like is the case with the return command. Instead, the generator continues to work in the background (memory) and spits out a new value on each pass.

This is how the findAreaCities() function operates, and any generator needs some code to iterate through the yielded values. The for and in commands are it.
 
ok so this would be what I would use for is rome controls x give them n units of paets in all cities in x
Code:
if isAreaOwner(eRome, tCoords1, tCoords2):
    spawnAreaCityUnits(eRome, tCoords1, tCoords2, ePraetorian, iNum)

also (probably a very stupid question which I really should know the answer to) in
isPlayerCity(pCity, ePlayer):
how would you define pCity, say if I wanted to say tarentum how would I put that as pCity?

Edit:
Btw I found these in the API
#INT getHappyTurns ()
#VOID changeExtraHappiness (INT iChange) cycity
#VOID changeHappinessTimer (INT iChange) cycity
#INT getHappinessTimer ()
#BOOL isOccupation ()
#BOOL isGoldenAge ()
#INT getGoldenAgeLength ()
#INT getGoldenAgeModifier ()
#INT getGoldenAgeTurns ()

and I hope to make them into helpers. But, I couldn't find a void for adding Golden Age turns and I'm not completly sure what the to voids regarding happiness actualy do...

My best guess would be that changeExtraHappiness changes the amount of temporary happy a city has and the timer changes how long it goes on for. I also don't know what to make of getHappyTurns...

my current helper for goldenages is this:
Code:
def giveGoldenAge(ePlayer, eTurns):
    pPlayer = gc.getPlayer(ePlayer)
    if pPlayer.isGoldenAge() == True:
        CurrentGoldenAge =  pPlayer.getGoldenAgeTurns()
        pPlayer.changeGolenAgeLength(CurrentGoldenAge + eTurns)
    else:
        pPlayer.changeGoldenAgeLength(eTurns)
but of course, changeGoldenAgeLength is just a filler and I need the correct one. I also don't know whether to use length or turns :rolleyes:

help?
 
Oh, man. I seems like I never posted my reply to the last post. I'm guessing that I, in my sleep deprived state this morning, simply clicked on preview and never submitted the reply. :rolleyes:

Short version:

pCity is the preferrred variable name for a CyCity instance. You get one with CyPlot.getPlotCity(). And the CyPlot instance you get with CyMap.plot().

You basically only use the VOID methods for granting rewards. And the one you're missing is CyPlayer.changeGoldenAgeTurns() - it works just like changeGold() - not like setGold(), remember?

The happy methods I'm unsure on myself. It would be helpful if you could test them in the console... :p
 
Back
Top Bottom