Introducing: PyScenario - easy-to-use scenario event scripting for RFC

Ok, I can see that it is the autoplay... I'll try to figure out what causes the lag. :confused:
 
Great work! I didn't know it because it's in the subforum.

My little concern is that it might be still hard for most non-computer science people.
Maybe a development tool can make it easier.
I'm thinking of making one when I got some free time, but I'll first need to read your intro.
 
My little concern is that it might be still hard for most non-computer science people.

Maybe a development tool can make it easier.
Yeah, some sort of graphical interface would of course be ideal!

I'm thinking of making one when I got some free time, but I'll first need to read your intro.
Do your worst! :D Unfortunately I don't know how to make something like that myself, but I have considered trying to (eventually) make something like this that can be used in game. Like the World Builder or the Mercenaries window.

My big concern right now is that a sizable script will slow down the game considerably. :p I don't know what exactly is causing the lag, but I haven't tested big scripts myself before. I didn't think it would be a problem, as conditions are checked and Triggers discarded in a timely fashion. Or so I thought... :rolleyes:

How do I time how long a Python process takes? I believe you can print out a time stamp or something, or activate a timer of some sort... :confused:
 
I was able to reduce lag in between turns by disabling debug messages that were written into the Python Debug Log. That took it down by some 30%, but thats not nearly sufficient! :p

I'll have to look into this further...
 
It was while simulating the turns not loading the game and yes I had both files I will enable debugging.
edit: The lag issue is resolved from beta version 1.010 and onward. Rhye's original Python code is still about 2,5 times faster than the corresponding PyScenario script though - but its only a matter of milliseconds and the average time for checking all Triggers in between turns only add up to about 1/100 second (as long as no Triggers actually fire). I've calculated that 1000 Triggers could be checked in about 1/10 second, by the way, which is still hardly noticeable. :D

As far as I can gather this is due to the sheer amount of Triggers that is being checked every turn. Even if only a few Triggers would fire on any single turn, all the conditions for all the Triggers still need to be checked each time.

I'll have to take a closer look at what code is processing heavy and see what can be done about it. There are some obvious measures that will be implemented - if not immediately then later on - but chances are that PyScenario simply takes too much processing power compared to simple if-statements (as with Rhye's code). :(

This has two implications: First of all of Rhye's spawns shouldn't be converted to PyScenario as they are executed much faster as is. (Probably in 1/10 of the time the corresponding Triggers would take to process.) And secondly the scenario maker should only include vital scenario events in the Scenario module, because they might count for as much as 0,1 seconds of lag time each... (So 100 Triggers could add 10 seconds of lag time. :eek:)

The application is still in beta-testing though, so there will be improvements still. Thanks for helping out with this! :goodjob:
 
I must admit I am a little intimidated by this "mod", but at the same time very excited at the possibilities. I have absolutely no programming experience, and in fact this is the only PC game I've ever played (I'm a history/anthropology student and I'm hooked). I'm confident I can learn to use this from your tutorial, but it is a lot to digest having no programming experience. PyScenario really opens up a lot of possibilities though; I can preset the little changes I've always wanted (like a spawned Kiev, and even Copenhagen). Thanks for making these types of things possible for the rank and file; you are a true hero of the proletariat!!
 
I must admit I am a little intimidated by this "mod", but at the same time very excited at the possibilities. I have absolutely no programming experience, and in fact this is the only PC game I've ever played (I'm a history/anthropology student and I'm hooked). I'm confident I can learn to use this from your tutorial, but it is a lot to digest having no programming experience. PyScenario really opens up a lot of possibilities though; I can preset the little changes I've always wanted (like a spawned Kiev, and even Copenhagen). Thanks for making these types of things possible for the rank and file; you are a true hero of the proletariat!!
Thank you for your kind words! :goodjob: Take a look at the beta release thread if you dare to try this out at this early stage. (I would of course offer up any support you would need. If you describe - in detail - what events you'd like I could create some example code for you to get you started.)

It should be noted that a PyScenario script, although complex in itself, is still much easier to create than a regular Python module. Just open up any .py file in the \Assets\Python\ folder and have a look for yourself! :eek: 6 months ago Python made very little sense to me so I know how hard it is to get into programming proper. This is in fact the reason for doing this project. :king:
 
I uploaded a new version of the PyScenario files in the beta-testing thread. As always, it would be appreciated if someone would try to successfully download, install and run the application...

I got rid of most of the debug messages and therefore lag should be down by something like 40%... Further improvements will of course follow in time.

Thanks to Conqueror500 for reporting on the amount of lag in the first place! I also added a note on optimization in the tutorial section. :goodjob:
 
In the "flip" trigger, is there a way so that the flip is actually a conquest? (i.e: city conquered rather than peacefully change hands)
 
In the "flip" trigger, is there a way so that the flip is actually a conquest? (i.e: city conquered rather than peacefully change hands)
Not directly, no. I considered it at first but opted for a different approach:

If the two Civs (the players defined as ePlayer and eReceiver by the Trigger, respectively) are at war, then it counts as a hostile take-over. But if there is state of peace between them, then the cities are considered to have been "traded".

The reason is that the flip() method would otherwise have cause a state of war between these players. So instead we need a way of first causing a war - and then flip the tiles.

Do you actually need something like a war() method, you think? It could be used for more than just flipping, of course... The guess the trick is to also make vassals join in any wars - or should that be determined by a setting (set by default)? Maybe include open borders options in the same method? (Is there a better name than war() for a generic diplo method?) Any other ideas?
 
I guess some "actions" to display messages or choices would be useful - by that, a player can know why some events have happened and what exaclty happened.
 
I guess some "actions" to display messages or choices would be useful - by that, a player can know why some events have happened and what exaclty happened.
Yeah, you are absolutely correct. This has been on my to-do list all along. Any specific suggestions/requests as to in-game text messages?
 
Do you actually need something like a war() method, you think? It could be used for more than just flipping, of course... The guess the trick is to also make vassals join in any wars - or should that be determined by a setting (set by default)? Maybe include open borders options in the same method? (Is there a better name than war() for a generic diplo method?) Any other ideas?
Ok, I thought about this further and would like to propose the treaty() method:

It would take a ePlayer value as an argument and also three optional booleans; bPeace = True, bVassals = True and bOpenBorders = False. If bPeace equals False then the method would cause a state of war between the Civs. If the bVassals argument is set to the default value it indicates that any vassal states will also follow suite. And if bOpenBorders is set to True it enables an additional open borders agreement.

Does this sound useful?

I will also be inplementing "stability stuff" in the flip() method. Otherwise there will be inevitable collapses as a consequence of some flips. :p
 
The reason I asked about conquests was for stability. If I let AI Arabia have an empire stretching from the middle east to Casablanca, it would dominate everything and also be stable... unless the flips across Africa were a result of conquest, in which case stability problems came earlier.

A way to make it so the flips cause some stability issues whilst not guaranteeing any results would be nice - this way we're not being too deterministic but as a "general" trend, we can get the AI to use this land for a change :)

I like the idea of messages too. Would it be a bad idea in your opinion if messages like "<civ name> has discovered the new world" as soon as a certain civ settles first in the Americas? I'm assuming in history, tales of such a discovery would have gone around the world? It would add to the immersion imo, and add the feeling of a "race" to certain things :)
 
The reason I asked about conquests was for stability. If I let AI Arabia have an empire stretching from the middle east to Casablanca, it would dominate everything and also be stable... unless the flips across Africa were a result of conquest, in which case stability problems came earlier.
I'll have to look into what stability penalties already are in place. I think we'll have to revisit this topic when I get around to it.

A way to make it so the flips cause some stability issues whilst not guaranteeing any results would be nice - this way we're not being too deterministic but as a "general" trend, we can get the AI to use this land for a change :)
What is an issue right now, is that once a AI Civ loses half of its cities at once, there is an inevitable collapse down the line. :p I'll fix this in the next update though. Also, losing cities to flips causes instability, and this is also a cause for the odd collapse. I'll have to come back to this however.

I like the idea of messages too. Would it be a bad idea in your opinion if messages like "<civ name> has discovered the new world" as soon as a certain civ settles first in the Americas? I'm assuming in history, tales of such a discovery would have gone around the world? It would add to the immersion imo, and add the feeling of a "race" to certain things :)
I don't think this idea, while good, is something that fits into the scope of PyScenario. It would rather make a nice modmod (or mod component) in itself! :king: You could develop the idea further and post as a suggestion in a new thread. :goodjob:

I do however intend to give users some options for both messages and even pop-ups. So if you script, say a spawn or a flip, you will also be able to add a in-game message to the human player. Another use could be that once the first Civ enters, say, the Modern Age there is a message heralding this new age. Or when the game itself enters the Modern Age. (This is actually not a bad idea and could be included in your "In-game messages" modmod idea. :goodjob:)
 
I was more thinking stability penalty (or at least some sort of eventual problems) for civs that receive these free cities. After all I'd be giving Arabia a bit of a boost, we can't give them this without a price, right? ;)

I've been trying the random turns idea to spawn cities:
Code:
Trigger(iJapan).check().turn(181,226,10,-1).once().city(116,47,"Edo").buildings(lJapanBuildings).culture(10).garrison(eType=iArcher,iNum=1)
I wanted to use the random turn condition so that the results are broadly similiar, but the game doesn't play out the same way each time. Am I right in assuming the condition isn't fulfilled every ten turns, but more that it has a ~10% chance of occuring every turn?

I figure I need the "once()" condition so that the game doesn't try to spawn Edo again if it has already done so. Is this correct?
 
I was more thinking stability penalty (or at least some sort of eventual problems) for civs that receive these free cities. After all I'd be giving Arabia a bit of a boost, we can't give them this without a price, right? ;)
What about a stability() method, then? It could be used to add or subtract stability points as you see fit! :goodjob: Then it would only be a matter of figuring out the exact right amount of Arabian instability. :D

I've been trying the random turns idea to spawn cities:
...
Am I right in assuming the condition isn't fulfilled every ten turns, but more that it has a ~10% chance of occuring every turn?
Yes, because a new random number between 0 and 9 will be generated each turn inside the interval (181-226) and if that number happens to be zero, then the Condition will be met. This will happen about 1/10 of the time. So the city should spawn about turn 190, in average, but it might also not spawn at all. (Even if this is very unlikely with a 46 turn interval! :D)

I figure I need the "once()" condition so that the game doesn't try to spawn Edo again if it has already done so. Is this correct?
You have grasped the concept, but the once() method is really not necessary when using the city() Action in any Trigger. Because this is one of the methods that will ever only fire once. (This is mentioned briefly in the documentation but I haven't specified which exact methods it concerns. In the future I might add this information.)

Also, if the turn() method doesn't get a value for the iTurn2 argument the Trigger is set to always expire once it has fired once. Because with only a specific turn requirement it can only fire once, and should thus never be checked again... I will eventually probably have such methods deleted from memory altogether once they expire. (To conserve computing resources.)

But when in doubt, it would probably be wise to include the once() method. It won't slow the game down, at least.
 
Bug found, these lines didn't work as planned when the Vikings entered the Renaissance:

Code:
#Vikings
Trigger(iVikings).tech(eEra=con.iRenaissance).name("Stockholm","Birka")
Trigger(iVikings).tech(eEra=con.iRenaissance).name("Kj&#248;bmandehavn","Roskilde")
Did I screw something up at some point?
 
Bug found, these lines didn't work as planned when the Vikings entered the Renaissance:

Code:
#Vikings
Trigger(iVikings).tech(eEra=con.iRenaissance).name("Stockholm","Birka")
Trigger(iVikings).tech(eEra=con.iRenaissance).name("Kjøbmandehavn","Roskilde")
Did I screw something up at some point?
It seems to be correctly formatted, but I wouldn't know what exactly the rest of your script looks like. I actually think this is my the code I supplied for you myself when I converted your scenario into a PyScenario script, right? It worked when I tried it back then, but something could of course be off now... :rolleyes:

What have you done in order to verify these Triggers? Are you absolutely positive that the Vikings were in the renaissance era when nothing happened? (If you know how to open and use the built-in Python console there is actually a way to verify what era a Civ is in currently... This would of course make things much easier!)

If you can't figure it out yourself (a Python exception could for instance have thrown all Triggers off for that critical turn) you could always post your script (or send to me via email) and I could try it out myself.

If this approach proves to be less than predictable/reliable I believe there is another way of achieving the same thing, but lets wait with that. By the way, I believe these Triggers would be candidates for the once() method discussed earlier, but that can also wait until we sort out this issue.
 
Sorry I didn't really tell you anything in my post:

Vikings reached the Renaissance, because Nidaros renamed to Trondheim (which is a default rename code present in citynamemanager.py) correctly.
The Vikings owned Birka at the time (not Roskilde, but I'm assuming both won't work)

I have debugging enabled and nothing popped up :(

I also had a trigger for Russian renames when they hit the industrial era which didn't fire (I was Russia so I definitely know I was in industrial era ;)). I will email you the scenario.
 
Top Bottom