FreeOrion

Forums for the FreeOrion project
It is currently Mon Dec 11, 2017 6:51 pm

All times are UTC




Post new topic Reply to topic  [ 15 posts ] 
Author Message
PostPosted: Mon Jun 05, 2017 12:19 pm 
Offline
Dyson Forest

Joined: Tue Sep 30, 2014 10:01 am
Posts: 212
Just in case i missed it - is there a way to specify multiple stackinggroups?


I have a mixture of effects decomposed and composed (a government seat has multiple government functions).

So if the seat collapse effect happens, i want the government functions not to be in effect.

If a seat has only one function, this I can suppress the function effect using a stacking group.

If a seat more than one function, I can only suppress on of these using the stacking group.


Edit: Later on this thread turned from stackinggroups into general questions over context information in FOCS scripting and got a whole of helpful information how FOCS works.
I ended up using activation conditions and passing more static information through multiple levels of macro. For that
it what would have been great if i could have defined a static "named" property/parameter (e.g. Let name="GOVERNMENT_TYPE" be="DEMOCRACY") which i could have used in the end-macro (e.g. Building name="BLD_IMPERIAL_@GOVERNMENT_TYPE@".

_________________
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.


Last edited by Ophiuchus on Tue Jun 06, 2017 12:44 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Mon Jun 05, 2017 1:08 pm 
Offline
Programming, Design, Admin
User avatar

Joined: Wed Oct 08, 2003 1:33 am
Posts: 12040
Location: Munich
A stacking group is a single string, not a container of multiple strings.

It sounds like you should be using an activation condition, though.


Top
 Profile  
 
PostPosted: Mon Jun 05, 2017 1:43 pm 
Offline
Dyson Forest

Joined: Tue Sep 30, 2014 10:01 am
Posts: 212
Geoff the Medio wrote:
A stacking group is a single string, not a container of multiple strings.

It sounds like you should be using an activation condition, though.


I dont (yet) have the necessary information in the macro. Im two levels deep.
Are there other ways to access context information? Or a key to value mapping (probably possible with an if cascade)?

_________________
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.


Top
 Profile  
 
PostPosted: Mon Jun 05, 2017 2:16 pm 
Offline
Programming, Design, Admin
User avatar

Joined: Wed Oct 08, 2003 1:33 am
Posts: 12040
Location: Munich
Ophiuchus wrote:
I dont (yet) have the necessary information in the macro. Im two levels deep.
It not clear that you understand how macros work... Using, for example, CurrentContent, doesn't care if the actual "CurrentContent" is written in a macro or a macro within a macro, it will still be evaluated after all the macros have been expanded and while the content script is being evaluated.
Quote:
Are there other ways to access context information?
What sort of context?
Quote:
Or a key to value mapping (probably possible with an if cascade)?
There are ways to pick values based on a condition, but your question is too vague to really answer.


Top
 Profile  
 
PostPosted: Mon Jun 05, 2017 2:35 pm 
Offline
Creative Contributor
User avatar

Joined: Fri Jun 28, 2013 11:45 pm
Posts: 3286
Not sure exactly what you're trying to do (I look forward to testing the results but I'm not good enough a scripter normally), but one response to the original question that we've started using more and need to implement even more of is combining priority order and stackingroups more effectively, if you use the same stacking groups but have things trigger in a different order, which can be set out in a macro, that might be able to solve whatever you're doing.

_________________
Mat Bowles

Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.


Top
 Profile  
 
PostPosted: Mon Jun 05, 2017 3:14 pm 
Offline
Dyson Forest

Joined: Tue Sep 30, 2014 10:01 am
Posts: 212
Geoff the Medio wrote:
Ophiuchus wrote:
I dont (yet) have the necessary information in the macro. Im two levels deep.
It not clear that you understand how macros work... Using, for example, CurrentContent, doesn't care if the actual "CurrentContent" is written in a macro or a macro within a macro, it will still be evaluated after all the macros have been expanded and while the content script is being evaluated.

I think I understand macro expansion. I start to understand how CurrentContent works. I'm often lost about RootCandidate.

In this case CurrentContent would give me wrong building though (i'm checking if there is the correct building at the capital).

I changed and instead of picking the information from context I provide them now as parameters Activate government functions only if government exists.

Quote:
Quote:
Are there other ways to access context information?
What sort of context?
Quote:
Or a key to value mapping (probably possible with an if cascade)?
There are ways to pick values based on a condition, but your question is too vague to really answer.

With context i mean i want to set a value somewhere and retrieve it later on in a macro. Like a variable or a map.

I was thinking to get the CurrentContent (the "seat building") and maybe tag it, but probably I'd need string manipulation to do something useful with it.
Also from the name of the of the seat building one can infer the government type. Again string manipulation and comparison.

So probably parameters are the way to go :/

_________________
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.


Last edited by Ophiuchus on Tue Jun 06, 2017 12:45 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Mon Jun 05, 2017 4:08 pm 
Offline
Programming, Design, Admin
User avatar

Joined: Wed Oct 08, 2003 1:33 am
Posts: 12040
Location: Munich
Ophiuchus wrote:
I think I understand macro expansion. I start to understand how CurrentContent works. I'm often lost about RootCandidate.

Code:
BuildingType
    name = "BLD_EXAMPLE"
    description = "BLD_EXAMPLE_DESC"
    buildcost = 200 * Target.SizeAsDouble
    buildtime = 8
    location = And [
        Planet
        Not Contains Building name = ThisBuilding
        Number low = 1 high = 999 condition =
            WithinDistance distance = RootCandidate.Population condition = RootCandidate
    ]

"ThisBuilding" will be replaced with "BLD_EXAMPLE", because what is being scripted here is "BLD_EXAMPLE".

RootCandidate has two uses here... as a object you can access properties of (like Source), and as a condition. In the RootCandidate.Population case, it will refer to the planet being matched by the top level "location" condition. This is distinct from LocalCandidate, which would refer to the object being considered in the immediate containing condition, which is the WithinDistance condition in this case. RootCandidate will always be the same object, which is being considered by the top-level condition, no matter how many nested conditions appear within. The LocalCandate and the RootCandate can be completely different objects (or could be the same object by coincidence), or can be the same object if there isn't more than one nested condition to make them distinct.

Quote:
In this case CurrentContent would give me wrong building though (i'm checking if there is the correct building at the capital).
What are you scripting? A tech? A building? If you want to refer to building type A within a script for building type B, then you don't need CurrentCondition or ThisBuilding for that; you'd just write it out (or use a macro parameter).
Quote:
With context i mean i want to set a value somewhere and retrieve it later on in a macro. Like a variable or a map.
What does "later on in a macro" mean?
Quote:
Also from the name of the of the seat building one can infer the government type. Again string manipulation and comparison.
If you have an object, such as a Source or RootCandidate or LocalCandidate within a location condition or activation condition, you can get properties of it, such as its building type, or test it with a condition to see if it has a particular property that there is a condition for. You can also use a value comparison like
Code:
0.1 <= LocalCandidate.Population
, which is a condition (like Source or Planet or OwnedBy empire = Source.Owner).

I believe that presently something like this won't work:
Code:
ThisBuilding != RootCandidate.BuildingType
, since that comparison format appears to only accept numbers.


Top
 Profile  
 
PostPosted: Mon Jun 05, 2017 6:25 pm 
Offline
AI Lead, Programmer
User avatar

Joined: Sat Sep 22, 2012 6:25 pm
Posts: 4390
Ophiuchus wrote:
With context i mean i want to set a value somewhere and retrieve it later on in a macro. Like a variable or a map.
Keep in mind, RootCandidate and LocalCandidate are variable-like references that take values (and change values) during gameplay evaluation of the script; macro expansion on the other hand is simply a way of more concisely writing a variety of scripting components that share some substructures (like the enqueue conditions you looked at); macro expansions take place one time, when the scripts are parsed, and their result is purely static throughout gameplay.

I have sometimes mused about adding something that sounds perhaps like what you are meaning to refer to, another variable-like reference into the scripting "context", akin to RootCandidate, LocalCandidate and Target, let's call it a ReferenceNumber that if desired could correspond to an object ID, that could be set at one point in the gameplay evaluation of a script EffectsGroup section/subsection (Scope, Activation, or Effects) and then be available a fixed reference to work with at least in later parts of that section/subsection or maybe even at any later point in that EffectsGroup (because of how EffectsGroups are handled, I don't think a single ReferenceObject could be necessarily shared across EffectsGroups).

I think that one possible example use might be to take some random amount of PP/health/whatever away from one planet/ship/whatever and then *add that same amount* of the stuff to a different planet/ship/whatever.

But, I think that in the past I was always able to figure out how to make-do without it (like in the above example you could just work with a fixed amount rather than a random amount), and it would be enough nuisance to code up (and would complicate existing code) that it would take a very compelling use-case to justify it.

_________________
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0


Top
 Profile  
 
PostPosted: Tue Jun 06, 2017 8:53 am 
Offline
Vacuum Dragon
User avatar

Joined: Sun Sep 25, 2011 2:51 pm
Posts: 500
I may be way off, but I think Ophiuchus might be asking for a way to store some variables in the universe itself in one script and access them in another.

_________________
[...] for Man has earned his right to hold this planet against all comers, by virtue of occasionally producing someone totally batshit insane. - Randall Munroe, title text to xkcd #556


Top
 Profile  
 
PostPosted: Tue Jun 06, 2017 9:54 am 
Offline
Programming, Design, Admin
User avatar

Joined: Wed Oct 08, 2003 1:33 am
Posts: 12040
Location: Munich
em3 wrote:
...store some variables in the universe itself in one script and access them in another.
That is effectively not possible due to unpredictable ordering of effect evaluation and/or multithreading.
Dilvish wrote:
...variable-like reference into the scripting "context", akin to RootCandidate, LocalCandidate and Target, let's call it a ReferenceNumber that if desired could correspond to an object ID, that could be set at one point in the gameplay evaluation of a script EffectsGroup section/subsection (Scope, Activation, or Effects) and then be available a fixed reference to work with at least in later parts of that section/subsection or maybe even at any later point in that EffectsGroup...
The general way to implement something like that would be to try make the Source object the relevant other object.

There's also a general preference to not making effects scripting into a full programming / scripting environment. Mainly for reasons of debugging and testing, it has avoided adding extra state information, particularly such as arbitrarily defined extra variables that allow extra interactions outside of the standard condition / effect / valueref evaluation tree.


Top
 Profile  
 
PostPosted: Tue Jun 06, 2017 11:56 am 
Offline
Dyson Forest

Joined: Tue Sep 30, 2014 10:01 am
Posts: 212
Geoff the Medio wrote:
em3 wrote:
...store some variables in the universe itself in one script and access them in another.
That is effectively not possible due to unpredictable ordering of effect evaluation and/or multithreading.

I wasnt going for global variables. I have some thoughts though which I will put in another thread. I'll try to keep this focussed on my original problem, which could be solvable at macro expansion time.

I thought though that priority gives guarantees in order of evaluation in case of multithreading. Is that correct?

Quote:
There's also a general preference to not making effects scripting into a full programming / scripting environment. Mainly for reasons of debugging and testing, it has avoided adding extra state information, particularly such as arbitrarily defined extra variables that allow extra interactions outside of the standard condition / effect / valueref evaluation tree.

Understand. Debbuging focs is currently a pain. So maybe I should help improving that first. Often freeorion just crashes for me if i do something wrong
without any hints why. Should i open issues when such cases happen?


In my original case macro-expansion information would have been sufficient (the script using the macro cascade knows which building is necessary). So I am using a macro (lets call it the "macro-in-the-middle") which uses another macro ("end-macro").

The end-macro needed to know the building name and the calling code knew it.
What I didnt like was that I ended up passing the macro-in-the-middle so it could pass it along to the end-macro. The macro-in-the-middle didnt need to know this information!

So what would have been great if i could have defined a static "named" property/parameter (e.g. Let name="GOVERNMENT_TYPE" be="DEMOCRACY") which i could have used in the end-macro (e.g. Building name="BLD_IMPERIAL_@GOVERNMENT_TYPE@".

_________________
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.


Last edited by Ophiuchus on Tue Jun 06, 2017 12:39 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Jun 06, 2017 12:08 pm 
Offline
Programming, Design, Admin
User avatar

Joined: Wed Oct 08, 2003 1:33 am
Posts: 12040
Location: Munich
Ophiuchus wrote:
I thought though that priority gives guarantees in order of evaluation in case of multithreading. Is that correct?
Yes, but enforcing the use of priorities to guard against order-of-execution type issues would be problematic.

Quote:
Often freeorion just crashes for me if i do something wrong
without any hints why. Should i open issues when such cases happen?
Depends... Are you looking in the logs for parse error messages, like
Code:
14:03:02.545150 [error] server : ReportParseError.cpp:95 : C:\Users\Geoff\Desktop\FreeOrionSDK5\FreeOrionAlt\default\scripting/buildings\shipyards\BASE.focs.txt:12:8: Parse error.  Expected ] here:
    location = And [
        Planet
        TargetPopulation low = 1
        Not Contains Building name = "BLD_SHIPYARD_BASE"
        OwnedBy empire = Source.Owner
        Potato!
        ^
        ("Cow" == "Cow")
        asdf("Potato" != "Potatoes")
        ("AAARG!" == "Cowasw")
    ]
    EnqueueLocation = And [
?

In general though, preventing crashes in the parser code is difficult. If you have a simple test case that produces a crash, then it can be reported, but the chances of it being fixed if it's not actually valid script is not great. It's better if it's a very simple test case, though.

Quote:
...I am using a macro (lets call it the "macro-in-the-middle") which uses another macro ("end-macro").

The end-macro needed to know the building name and the calling code knew it.
What I didnt like was that I ended up passing the macro-in-the-middle so it could pass it along to the end-macro. The macro-in-the-middle didnt need to know this information!
In that case, just pass the needed parameters. The macro-in-the-middle does need to know the values of parameters if it's going to call another macro that needs to know them.


Top
 Profile  
 
PostPosted: Tue Jun 06, 2017 12:36 pm 
Offline
Dyson Forest

Joined: Tue Sep 30, 2014 10:01 am
Posts: 212
Geoff the Medio wrote:
Ophiuchus wrote:
I thought though that priority gives guarantees in order of evaluation in case of multithreading. Is that correct?
Yes, but enforcing the use of priorities to guard against order-of-execution type issues would be problematic.

But isnt exactly what is done/the intended usecase in case of stackinggroups and priorities?

Quote:
Often freeorion just crashes for me if i do something wrong
without any hints why. Should i open issues when such cases happen?
Depends... Are you looking in the logs for parse error messages, like...[/quote]Yes, they show up in the command line where i start freeorion, not in the logs though. These i consider helpful. The crashes usually dont give such though. Giving a wrong kind of data to a tag in a sitrep message is always fun.

Quote:
In general though, preventing crashes in the parser code is difficult. If you have a simple test case that produces a crash, then it can be reported, but the chances of it being fixed if it's not actually valid script is not great. It's better if it's a very simple test case, though.

Thanks for the info.

Geoff the Medio wrote:
Ophiuchus wrote:
...I am using a macro (lets call it the "macro-in-the-middle") which uses another macro ("end-macro").

The end-macro needed to know the building name and the calling code knew it.
What I didnt like was that I ended up passing the macro-in-the-middle so it could pass it along to the end-macro. The macro-in-the-middle didnt need to know this information!
In that case, just pass the needed parameters. The macro-in-the-middle does need to know the values of parameters if it's going to call another macro that needs to know them.

Thats what I ended up (as indicated in a post way up). But the refactoring felt wrong. So I asked for alternatives.

On the other hand this could been a valid code smell indicating you shouldn't use multiple levels of macros. So this maybe said that my code could have been structured wrongly (the alternative being more decomposition into smaller macro-parts and composing those in the calling script); but i dont think so.

_________________
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.


Top
 Profile  
 
PostPosted: Tue Jun 06, 2017 1:29 pm 
Offline
Creative Contributor
User avatar

Joined: Fri Jun 28, 2013 11:45 pm
Posts: 3286
Can specials still have a capacity set? I have a memory that they could at one point but we never used it for anything.

Because if they can have the 'warlord camp' building create a special that sets a capacity that can then be used for other things, including priority of effect.

_________________
Mat Bowles

Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.


Top
 Profile  
 
PostPosted: Thu Jun 08, 2017 7:59 am 
Offline
Release Manager, Design
User avatar

Joined: Wed Nov 16, 2011 12:56 pm
Posts: 4285
Location: Sol III
Sidenote: There are long term plans to migrate the content scripts to Python (to remove the necessity to maintain a parser for our own custom scripting language). Although that is only going to happen if those new Python content scripts can be made as easily readable and customizeable as the current FOCS scripts are (which should be not too hard to accomplish, but we won't know for sure until we're going to actually try to implement this). As this is likely to be a huge undertaking, it's not going to happen anytime soon.

Once in place, that will provide all the power of Python to content scripters. Which has it's pros and cons, as that of course is going to be a two-edged sword, see Geoff's comments why we don't have custom variables in FOCS.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group