PyScenario: Beta version release

I go a step further:
Code:
.target((66,30),(70,36)).owned(None,7).target((66,30),(70,36)).flip(None,7,0,0,1,0)
is it a valid trigger? I want it to fire if any plot is owned by Rome to flip all Roman cities in the area.
I only gave the Trigger a glance but it looks valid. The way the "target" values work - like target player (which is specified in the Trigger constructor) or the target tile (which can be defined pretty much anywhere inside the Trigger) - is that they are used for all methods of that Trigger. And a plot list is another of these "global targets values" and is used with all methods that can work with a plot list.

So you don't have to define the same area twice in the same Trigger - and only the last one will be valid if you try to define two different areas. This last case is where you'd need to use to separate Triggers - and bind them together. (Another case is if you need to have two different target players.)

In short: Take out one of the target() methods as it will add nothing to the Trigger.

Refer to the API for how to use the owned() method with a plot list.

Also, most of the time it doesn't really matter what order methods are stacked onto the Trigger constructor. (Like putting Actions before Conditions and tacking the label() method at the end, or whatever configuration you wanna use.) But there are special cases: the add-on methods that explicitly affect the method directly before (to the left of) them. Like how operator() is used to change the default operator of the previous method. But there are exceptions here also... Most of the time you should be able to create valid Triggers as long as you apply basic logic to them. So if they make sense to you, then they should also work.

And another question: is it possible to make an unit a mercenary simply by giving "mercenary" promotion? If it is true, what's the code of the promotion?
No, the unit will only have the Mercenary promotion (I'm guessing it is indexed as promotion 54) but not be connected to the actual Mercenaries feature. I'd have to create a mercenary() method to add mercenaries to the built-in mercenary engine. Do we need one? Do we really need one? :p (Or it could be a built-in feature of the promotions() method, but it would probably be better if you could also specify upkeep and other parameters.)
 
In short: Take out one of the target() methods as it will add nothing to the Trigger.

My logic: I define an area, owned() take 1 random tile of the area as area, I redefine area.

Do we need one? Do we really need one?

Nope. I wanted to make some Roman troops (like Numidian cavalry) spawning near enemy capitals mercenaries but just now it's OK.
 
My logic: I define an area, owned() take 1 random tile of the area as area, I redefine area.
A plot list will do different things for different methods. Some methods won't recognize it but will look for a target tile (if one exists) instead. Some other method will use it to perform some action on every tile included in the plot list. And yet another method will use it for random spawn. You need to check with the API for what the method actually will do. (I do!)

Regarding plot lists and the owned() method, the Condition will pass as long as any tile part of the plot list is owned by the target player. So if you would define the whole of Italy as an area, for example, and Rome owns any tile in that area, then they would be considered the owner of (or rather in) that area.

The important thing to remember is that there is only one target player and one map target per Trigger. So you either define the map target as a single tile or as a plot list. If you need both - or two plot lists or two target tiles - then you also need two separate Triggers. Its just the way the application is designed.
 
If used with a plot list (see section 2.3), then the method will have another use: Assuming there is already a target player defined somewhere, then the Condition will cycle through all the tiles in the plot list until it finds one that belongs to that Civ. This tile will then be set as the target tile for the entire Trigger (all Conditions and Actions)!

Above text made me to write the trigger as I did. BTW: why are you awake and posting at 5:33? :o
 
Above text made me to write the trigger as I did. BTW: why are you awake and posting at 5:33? :o
Opps! :p It turns out that I didn't read the API entry that closely myself. The lesson here would be to always check with the API... :rolleyes:

This is actually interesting. My prediction, without testing this myself, is that the plot list will still override the target tile - for those methods that use plot lists... But you should try it. :D

I start work at 07:00 so I go up early so I don't have to rush or anything...
 
So we have a little contest: who will be more lazy (we are both curious but if other one is more curious and check then we've got what we wanted and don't have to do anything) :p

Isn't it better to get up half an hour later and DO NOT turn on PC before work? Can't forget time in my life when I turned on PC before school. Freaking OGame :p
 
So we have a little contest: who will be more lazy (we are both curious but if other one is more curious and check then we've got what we wanted and don't have to do anything) :p
I might cheat and read the source code instead. :D

Isn't it better to get up half an hour later and DO NOT turn on PC before work? Can't forget time in my life when I turned on PC before school. Freaking OGame :p
No, no... You're not getting my point. I'm so drunken with sleep when I get up that I need about an hour to awaken before I can manage to put my work gear on and get ready for action. So I have a hour to kill. Caffeine, toilet, shower/shave, refreshments, check email/forum, breakfast, pack lunch, et cetera. Its hard to manage every single topic on a given morning but at least I'm not feeling any hurry, because that would be too traumatizing to go through five mornings a week...

And I can just go to bed half-an-hour earlier, right? :D I should probably go up a couple of hours earlier and also manage a trip to the gym on the way to work... Because I'm not one to exercise after work... :p
 
If I take trigger without any specified civ is it going to check through all civs seeking the one which meet the criteria?
This would depend on the case at hand. Something like a spawn Action would automatically select a minor Civ as the target player, while most Conditions would check all players. Refer to the API entries for all the methods included in that Trigger.

Were you thinking about a specific method or just in general?
 
Remember my stability modmod request? I think you've already done it. Maybe not perfectly (there is no number of cities check) but good enough. We have stability check (-20 or less), number of units count (5 or more), stability effect (+10) and yield modifier (-2) :) So, as long as you have army, the situation will hurt your economy. When you lose your army, you normally collapse. If there would be bFading with yield, we could have angriness as well (because permanent is probably too harsh. Or maybe not? We'll see).
 
Remember my stability modmod request? I think you've already done it. Maybe not perfectly (there is no number of cities check) but good enough. We have stability check (-20 or less), number of units count (5 or more), stability effect (+10) and yield modifier (-2) :) So, as long as you have army, the situation will hurt your economy. When you lose your army, you normally collapse. If there would be bFading with yield, we could have angriness as well (because permanent is probably too harsh. Or maybe not? We'll see).
Have you managed to mod stability with PyScenario? :eek: This was never my intention, but good work in that case! :king: I'm already looking forward to you next update. :D
 
About the owned() method: I looked in the source code and it turns out that any plot list within the Trigger will be nullified if the owned() method finds a valid tile within that plot list.

So you can't have a plot list in a Trigger with the owned() method unless you want it to turn that into a target tile instead. In short: You currently need two separate Triggers if you wanna be able to first detect whether or not a Civ owns some tile - and then flip a map area.

This strikes me as not so useful however, so it probably needs to be changed. Any suggestions?
 
"bSomething = false" at the end to decide if area should be changed.

BTW: may I ask for some cities count as "heads" counts units, please? Still, probably it will take time before I use it because I have to reinstall cIV due to strange bug (every unit is invisible :/ )... and I'm too lazy to do it right now.
 
"bSomething = false" at the end to decide if area should be changed.
Or we could just save the plot picking feature for another method altogether...

BTW: may I ask for some cities count as "heads" counts units, please?
You may, but unfortunately I don't think I'm quite following... :confused:

Did you mean a method for checking whether or not there is a target number of cities belonging to some Civ?
 
Sure, I'm on it. The hard part is to come up with a name for the method... :rolleyes: I guess I could go with cities() for the time being? The new operator() method will of course be useful, once again...

Another idea I had was a reverse() method that turns (pretty much) any Condition into its opposite. So the Condition would pass if the prerequisites are not met. I'm not entirely sure how to implement something like that though...
 
NOT() is shorter than reverse()
And leaves place for OR() and AND(), which are very helpful with a bit more advanced modmaking.
I can see where you are going with this - and there is nothing wrong with thinking big. But there comes a time when you just need to know how to do programming yourself. :rolleyes: I'd suggest it for the "advanced" scenarios - and for modding and such (like making changes to how stability works).

One thing to understand about PyScenario is that the Trigger lines are used for initialization only. They create Trigger objects which in turn contain references to Condition and Action objects. These "things" are what the game uses to run you PyScenario scripts - not the actual lines of code making up your scripts.

After they are read once the contents of the Scenario module are never used again, and that is shy it makes little difference how many characters each Trigger is made up of, or how large the actual Scenario module is (in kilobytes). Its rather the number of Trigger objects that is the cause for lag, as pretty much each one is processed at least once every turn. This is why it is better to combine two or several Triggers with the same target player and target tile/area into one long Trigger.

As with anything to do with CivIV, everything is an object of some sort, and the PyScenario application is also such an entity residing inside the RFC Event Handler. One of its attributes is a list references to Trigger objects. And each Trigger object holds - potentially - lists of (references to) Condition and Action objects. They are processed - pretty much - in the order that they appear were initialized by the script in the Scenario module, but there are currently no connections between them.

To make the Scenario script work with not/and/or clauses the Conditions would probably have to stored in some advanced data set like a stack or a tree or something, instead of a list. While I do like a good challenge (I've actually been contemplating the notion of having multi-choice pop-ups in PyScenario, just to get the opportunity to work with them) this feels somewhat like another project altogether.

But maybe we might have some sort of larger clusters of custom Conditions, or something. Like you create what you suggested independently from the actual Trigger, and then use a reference to that as the Trigger Condition, or something.

I'll have to think about that...
 
My trigger would look like this:
Code:
Trigger().check(None).solidity(-20).operator(5).OR(NOT(cities(2)).heads(2),NOT(cities(6)).heads(5),NOT(cities(11)).heads(12),NOT(cities(21)).heads(25),cities(21).heads(35)).stability(10).yield(0,0,-2,-1)
but if you need to create condition headcities() for it I can live with just:
Code:
Trigger().check(None).solidity(-20).operator(5).heads(5).stability(10).yield(0,0,-2,-1)
because of Ockham's razor.

I don't know how Python works, you does so I think what I would need and you say if it's possible (and easily done) or not. This way (I hope) you're going to make even better modding tool :)
 
My trigger would look like this:
Code:
Trigger().check(None).solidity(-20).operator(5).OR(NOT(cities(2)).heads(2),NOT(cities(6)).heads(5),NOT(cities(11)).heads(12),NOT(cities(21)).heads(25),cities(21).heads(35)).stability(10).yield(0,0,-2,-1)
Your example is telling me two things:

1. Since I'm having a hard time following your code I'm thinking that PyScenario really isn't suited for being used as a programming language.
2. What you are trying to do is programming and you should probably look into Python eventually. You could totally learn it. :goodjob:

How you would express this as a Python condition would probably be something like:
Spoiler :
Code:
if bAlive == True and iStability <= -20:
    if iNumCities >= 2 and iNumUnits >= 2:
        (then...)
    elif iNumCities >= 6 and iNumUnits >= 5:
        (then...)
    elif iNumCities >= 11 and iNumUnits >= 12:
        (then...)
    elif iNumCities >= 21 and iNumUnits >= 25:
        (then...)
    elif iNumCities >= 21 and iNumUnits >= 35:
        (then...)
    else:
        (then...)
It wouldn't all fit on one single line of code, but on the other hand you'd get to have six different results! You could do whatever you wanted with the code and not feel restricted my my API. :p

but if you need to create condition headcities() for it I can live with just:
Code:
Trigger().check(None).solidity(-20).operator(5).heads(5).stability(10).yield(0,0,-2,-1)
I don't see cities() or headcities() anywhere on that line, but I'll get to work making you a method for checking number of cities for the target player. I'll include the operator() method in the Custom module.

I don't know how Python works, you does so I think what I would need and you say if it's possible (and easily done) or not. This way (I hope) you're going to make even better modding tool :)
I appreciate all the good ideas, so keep them coming. :king:
 
Top Bottom