• Our friends from AlphaCentauri2.info are in need of technical assistance. If you have experience with the LAMP stack and some hours to spare, please help them out and post here.

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

Attached is the custom Action rebirth():

rebirth( iNum=None, bScaling=True, ePlayer=None )

The method adds/subtracts iNum turns worth of Golden Age for the Target Player. (bScaling adapts this to the current game speed.) A None setting will auto-detect the default number of turns for that player (always scaled for speed). The optional ePlayer setting can be used to override any Target Player for this method only.
Code:
from Custom import *
Trigger.rebirth = rebirth
Did anyone ever test this out? Because I would like to add it to the next release.
 
Embryodead releases a new version of RFC: Epic/Marathon today and I'll get to working on a new version of PyScenario accordingly.

Features in the next update will be dynamic detection of mod folder (so that you can use PyScenario with your own mod-mod of RFCM) and hopefully a fully functional version of the civilization() method now only found in the Dynamic Byzantium mod-mod. (Its used to change the civilization attribute of a player in mid game. :eek2:) And if no one can come up with any issues with the tentatively released rebirth() method (granting Golden Ages) it will also be included.

Any other requests will be considered also.
 
Ugh. Everyone in my house gets evicted because the new owners want to remodel, and in the 3 months that I'm gone, I forget everything I knew about PyScenario... :sad:

Code:
Trigger("Stonehenge").date(-3000).player(31).city(51,53,"Stonehenge",1).buildings(118)

So, like... Does PyScenario know that Stonehenge goes in the city that this trigger spawns? I'm ready to get back on the horse.
 
So, like... Does PyScenario know that Stonehenge goes in the city that this trigger spawns? I'm ready to get back on the horse.
Yeah, for sure.

I think you might wanna read through the API once more before going forward.
 
Good news: I successfully got the very beginnings of my script working.

Bad news: in order to do it, Stonehenge has to be built in 2970 BC, not 3000 BC. Anything that is set to happen on a certain date will only happen when the calendar turns to that date from whatever date comes before it. It's thus impossible to trigger anything to happen in 3000 BC, as far as I can tell.

I recommend fixing this.

Anyway, on to the rest of the Wonders... and the drudgery of repeating the necessary research that's on my currently non-functioning hard drive.

EDIT: never mind, I found the mythical .startup method

EDIT #2: Okay, I made a Hanging Gardens trigger and tested it. The first time, Babylon collapsed before the event could trigger. The second time seemed to work. The third time, Persians captured the city before the event could trigger. The fourth time, China built the Gardens before the event could trigger. I have seriously never seen events 1, 3, or 4 in a regular game. This called for more test runs. So I kept going in Game 4, and guess what? A SECOND Hanging Gardens was built in Babylon right on schedule. After several more runs that were rather boring, I decided to shake things up. I destroyed Babylon. But regardless, at 595 BC, right on schedule... "The Hanging Gardens has been built in a far away land". This message really shouldn't pop up when there's no city in which to put a building. Then I tried out various collapsing and flipping triggers, and I was able to confirm that yes, the trigger will only fire if the Babylonians are still around. However, if someone else controls Babylon but the Babylonians are still alive, the Gardens will still get built. I don't even want to bother testing the "AI only" part of it. Here's my code; tell me what I'm doing wrong:

Code:
Trigger("GardenCheck").built(121)
Trigger("Gardenspawn").date(-600).fired("GardenCheck",bFired=False).check(bHuman=False,bDead=False,ePlayer=3).owned(tCoords=(76,40),eOwner=None,bVassals=False).buildings(121)
 
I guess that you should define the global setting Target Player with the player() method. (Look it up in the API section 2.3 - its one of the core methods for building Triggers.)

Or am I missing what you're trying to achieve?

And perhaps it should never be possible to spawn a second version of any World Wonder? :rolleyes:
 
2.3 Global settings

The governing principle of PyScenario is that every Trigger is used with one Player only and is aimed at one single map "target".

I must have missed some fine print somewhere. Oh, here it is:

2.5.2 Player Conditions

These Conditions are used to check different attributes of the Trigger's Target Player.

check( bHuman=False, bDead=False, ePlayer=None )
This Condition checks the Target Player towards two built in sub-conditions: The first one is by default set to not allow the Trigger to fire if the specified Civ is the human player. Only the human player will however be valid if the first setting is set to True. A None setting disables this particular sub-check entirely.

The second sub-check is done in order for the Trigger not to fire if the Target Player is dead. (If the second setting is set to True then it is possible to revive a dead Civ by, for example, spawning a city or some units for it. This is not intended practice however and may cause unintended issues.)

You should probably make a habit of using this method any time you specify a Target Player with the player() method. Note that the optional ePlayer setting doesn't set the Target Player for the whole Trigger but will instead override any Target Player for this method only. (So its a "local" setting - not a "global" one.)

See, this is why I keep saying "I hate you". I spent four goddamn hours testing that trigger, trying to figure out what was wrong with it, only to find out that you're breaking your own rules...
 
This rule doesn't prevent certain methods from having local settings for player and map targets.

And drop the attitude. You simply missed some important documentation and I'm giving you free support here. Lighten up!

If you have actual suggestions on how to improve the documentation, then I'm all ear.
 
This rule doesn't prevent certain methods from having local settings for player and map targets.

You were remarkably opposed to the idea when I asked for such enhancements to the program...

The way I originally designed PyScenario was that there are only global tile targets. So if you define a target tile anywhere in a Trigger it applies to all methods. Like it or not, but this is how it works...

Sound familiar?

If you have actual suggestions on how to improve the documentation, then I'm all ear.

Okay. Replace this:

The governing principle of PyScenario is that every Trigger is used with one Player only and is aimed at one single map "target".

With something like this:

The governing principle of PyScenario is that every Trigger is used with one "primary" Player only and is aimed at one single "primary" map target. However, this does not prevent some Methods from being able to affect players or map targets different from the primary ones. See each individual Method's documentation for details.
 
:lol: Good one! :goodjob:
 
Yeah, not knowing how to use PyScenario well means that I can suggest all sorts of helpful "Allergy Warning: these peanuts may contain traces of nuts" suggestions for the documentation :lol:

Anyway, your advice should solve the problem with the Gardens spawning when someone else controls Babylon. But how do we solve the problem of .fired("GardenCheck",bFired=False) not working?
 
Anyway, your advice should solve the problem with the Gardens spawning when someone else controls Babylon. But how do we solve the problem of .fired("GardenCheck",bFired=False) not working?
What now? :confused:

I guess I should make an addition to the buildings() method that doesn't allow for World Wonders to be created if they already exist. (Have existed?) Makes sense?
 
What now? :confused:

This:

EDIT #2: Okay, I made a Hanging Gardens trigger and tested it. The first time, Babylon collapsed before the event could trigger. The second time seemed to work. The third time, Persians captured the city before the event could trigger. The fourth time, China built the Gardens before the event could trigger. I have seriously never seen events 1, 3, or 4 in a regular game. This called for more test runs. So I kept going in Game 4, and guess what? A SECOND Hanging Gardens was built in Babylon right on schedule.

It's okay; I don't blame you for not remembering.

I guess I should make an addition to the buildings() method that doesn't allow for World Wonders to be created if they already exist. (Have existed?) Makes sense?

Well, it would be easier to fix the trigger than fix the program. Also, for whatever reason, some people might WANT to spawn multiple copies of the same Wonder. Maybe you could make that an optional parameter... like .building(121,bAlready=True)?

And you should definitely block the event from going off if no city is there in which to put the building :)

EDIT: Well I tried this in order to save a few CPU cycles...

Code:
Trigger("GardenCheck").date(-600).once().built(121)
Trigger("Gardenspawn").date(-600).fired("GardenCheck",bFired=False).player(ePlayer=3).check(bHuman=False,bDead=False).owned(tCoords=(76,40)).buildings(121)

...and it's suffering the same problem. I could roll back the GardenCheck date to 610, but that carries the possibility that someone could build the Gardens on the turn before the Babylonians are supposed to, and we'd still get two of them.
 
It's okay; I don't blame you for not remembering.
Lets just say that I'm finding this very confusing.

Well, it would be easier to fix the trigger than fix the program. Also, for whatever reason, some people might WANT to spawn multiple copies of the same Wonder. Maybe you could make that an optional parameter... like .building(121,bAlready=True)?
Well, I don't see any good reason to allow multiple World Wonders. Because it would make more sense to make them National Wonders instead. But you're suggestion has merit nonetheless and is under consideration.

And you should definitely block the event from going off if no city is there in which to put the building :)
What exactly happens when the "event is going off" when "no city is there"? Because it shouldn't be possible to add buildings to non-city map tiles. What could possibly happen?

EDIT: Well I tried this in order to save a few CPU cycles...

Code:
Trigger("GardenCheck").date(-600).once().built(121)
Trigger("Gardenspawn").date(-600).fired("GardenCheck",bFired=False).player(ePlayer=3).check(bHuman=False,bDead=False).owned(tCoords=(76,40)).buildings(121)

...and it's suffering the same problem.
And the problem would be that the "GardenCheck" Trigger isn't being fired? Because it doesn't register as fired with the fired() method in the "GardenSpawn" Trigger?

I'm getting the feeling that what you need is a method for checking whether or not there is a city on a given tile. I can't seem to be able to find anything for this in the current API, so why not request one such method to your specifications? Or perhaps could one of the existing methods be augmented somehow?

It was a while since I worked on PyScenario actually and its all coming back to me now. G-Max, I now realize how much you have contributed to the last few versions and that I should probably thank you for you this. If you only had been on-board from the get-go this application might have been better than it is currently. (I might make a new version from the ground-up someday, but I doubt anyone else would be around modding RFC in such a distant future.)
 
What exactly happens when the "event is going off" when "no city is there"? Because it shouldn't be possible to add buildings to non-city map tiles. What could possibly happen?

I get a message saying "X has been built in a far away land", but the Wonder doesn't get built. It's more of a nuisance than a functional problem.

And the problem would be that the "GardenCheck" Trigger isn't being fired? Because it doesn't register as fired with the fired() method in the "GardenSpawn" Trigger?

Well, I've traced the problem to either .built not properly working or .fired not properly working. I used the following code...

Code:
Trigger("GardenCheck").built(121)
Trigger("KillChina").fired("GardenCheck").player(ePlayer=2).collapse(bFragment=False)

...fired up a game as Japan, and waited for China to collapse. They never did. Babylon built the Gardens and China kept going as if nothing had happened.

So it looks like you have some work to do, cute lady ;)

I'm getting the feeling that what you need is a method for checking whether or not there is a city on a given tile. I can't seem to be able to find anything for this in the current API, so why not request one such method to your specifications? Or perhaps could one of the existing methods be augmented somehow?

I was going to suggest that, but it was a low priority (for my project anyway). I figured that if there was a city on the tile, then great, and if not, then nothing would happen anyway.

It was a while since I worked on PyScenario actually and its all coming back to me now. G-Max, I now realize how much you have contributed to the last few versions and that I should probably thank you for you this. If you only had been on-board from the get-go this application might have been better than it is currently.

Thanks :D But the folks who you should really thank are the guys at Blizzard who made Starcraft. I'm used to seeing/making stuff like "If player 1 brings a Battlecruiser to Location X and player 2 brings 5 Archons to Location Y, then spawn 200 Zerglings for Player 3 at location Z, set players 4 and 5 to fighting each other, and move all flags on the map to wherever Kerrigan is". Naturally, when I try to do even simple (in my opinion) things in Pyscenario, I learn that they're still not simple enough, and start going nuts. I'll probably end up being the most strenuous tester you'll ever have...

"If the Greeks control a city at 65,40 and at least 5 Immortals have been killed by Phalanxes between 68,43 and 70,45 then play audio clip ThisIsSparta and spawn Xerxes at..."
 
I get a message saying "X has been built in a far away land", but the Wonder doesn't get built. It's more of a nuisance than a functional problem.
Oh, that. I have no idea how that is even possible... I guess I need to add a check towards any active cities on the target tile, then.

Well, I've traced the problem to either .built not properly working or .fired not properly working. I used the following code...

Code:
Trigger("GardenCheck").built(121)
Trigger("KillChina").fired("GardenCheck").player(ePlayer=2).collapse(bFragment=False)

...fired up a game as Japan, and waited for China to collapse. They never did. Babylon built the Gardens and China kept going as if nothing had happened.
So your diagnosis is that the built() method isn't registering the Hanging Gardens, then? I suppose I should do more testing on this... :p

I was going to suggest that, but it was a low priority (for my project anyway). I figured that if there was a city on the tile, then great, and if not, then nothing would happen anyway.
Yeah, but what if you added a text-message heralding some historical event with the message() method? That would still fire even if there was no city present...

Naturally, when I try to do even simple (in my opinion) things in Pyscenario, I learn that they're still not simple enough, and start going nuts. I'll probably end up being the most strenuous tester you'll ever have...
This is actually my own experience from working with PyScenario (scripting events for the sample scenarios I've made) also. Even the simplest of tasks tend to become very complicated.

I think that the problem is that PyScenario is simply a set of constrains on what the CivIV Python API can be used for. While it should be easier to use, its mostly just restricted. And this is the cause of all the headache. I basically think everyone should just learn Python and then they'd be able to do pretty much anything they want to.
 
So your diagnosis is that the built() method isn't registering the Hanging Gardens, then? I suppose I should do more testing on this... :p

No, it's the .fired method. I just ran a test with more streamlined code to isolate .built from .fired...

Code:
Trigger("GardenCheck").built(121).player(ePlayer=2).collapse(bFragment=False)

...started as the Chinese, gave myself mathematics and a Great Engineer, and instant suicide.

The alternative possibility is that .built only works correctly when a Target Player is set.

EDIT: Damn, I'm good. I just ran my NINE THOUSANDTH test in the past 24 hours with the following code...

Code:
Trigger("GardenCheck").built(121).player(ePlayer=3)
Trigger("KillChina").fired("GardenCheck").player(ePlayer=2).collapse(bFragment=False)
Trigger("Gardenspawn").date(-2000).fired("GardenCheck",bFired=False).player(ePlayer=3).check(bHuman=False,bDead=False).owned(tCoords=(76,40)).buildings(121)

...then started up the game as Greece. China was dead. .fired works fine; it's .built that doesn't work as intended unless given a target player.

You're welcome. Now, if you'll excuse me... I'm sick of Civ IV for now. I'm gonna see if Tron Legacy has been pirated yet.
 
Baldyr passed me a note that the teacher wants me to read in front of the class:
Moderator Action: Publishing private messages is not allowed.

Baldyr said:
Hi,

It has become painfully clear to me that PyScenario has evolved far from the initial goal of being "easy to use". Its actually a very complicated system to use and to get into, at least at this point.

You as the application's target audience would probably be better off just taking the time to learn proper programming. Python is hardly more complicated to learn than to use PyScenario. The trick I've managed to pull is simply to convince some of you non-programmers that PyScenario scripting is not programming, while its just another "dialect" of Python made up by me. :rolleyes:

I'm not sure what I'm trying to say with this, but the idea has entered my mind on occasion to start over and make something similar but different. Like easy-to-define Perhaps something that people who know or are willing to learn some Python would be helped by. Conditions and Triggers that could be used together with the existing random events interface. Or just a alternate event system that is clearer to use than, but at the same time not as dumbed down as, PyScenario currently is.

I don't have the time for any such thing, however, so I'm not really suggesting anything. Or you could make this yourself if you commit to learning Python. :lol:
 
Am I imagining things or did this guy just post a private message? :eek:

As time is scarce and I have tons of other projects and also real life duties to attend to, any further development of PyScenario is in doubt. I of course realize that interest in the application has also plummeted due to the release of CiV.

But if G-Max is what I'm stuck with as far as beta-testers goes, then its not even worth the effort. I'm in no way trying to diminish his contributions or denying his talent as a tester or game designer. I'm just not gonna waste my breath on him anymore.

The promised PyScenario update might still make an appearance before the new year - since I should be able to get some hours worth of work done on it over the holidays - but right now its firmly at the bottom of my priorities list.
 
If I were you, I'd ask him to remove this or report that post ...
 
Back
Top Bottom