Specify multiple stackinggroups? Getting static context info
Moderators: Oberlus, Committer
Specify multiple stackinggroups? Getting static context info
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@".
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@".
Last edited by Ophiuchus on Tue Jun 06, 2017 12:44 pm, edited 1 time in total.
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.
Look, ma... four combat bouts!
Look, ma... four combat bouts!
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13587
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: Specify multiple stackinggroups?
A stacking group is a single string, not a container of multiple strings.
It sounds like you should be using an activation condition, though.
It sounds like you should be using an activation condition, though.
Re: Specify multiple stackinggroups?
I dont (yet) have the necessary information in the macro. Im two levels deep.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.
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.
Look, ma... four combat bouts!
Look, ma... four combat bouts!
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13587
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: Specify multiple stackinggroups?
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.Ophiuchus wrote:I dont (yet) have the necessary information in the macro. Im two levels deep.
What sort of context?Are there other ways to access context information?
There are ways to pick values based on a condition, but your question is too vague to really answer.Or a key to value mapping (probably possible with an if cascade)?
Re: Specify multiple stackinggroups?
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.
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.
Re: Specify multiple stackinggroups?
I think I understand macro expansion. I start to understand how CurrentContent works. I'm often lost about RootCandidate.Geoff the Medio wrote: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.Ophiuchus wrote:I dont (yet) have the necessary information in the macro. Im two levels deep.
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.
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 sort of context?Are there other ways to access context information?There are ways to pick values based on a condition, but your question is too vague to really answer.Or a key to value mapping (probably possible with an if cascade)?
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 :/
Last edited by Ophiuchus on Tue Jun 06, 2017 12:45 pm, edited 1 time in total.
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.
Look, ma... four combat bouts!
Look, ma... four combat bouts!
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13587
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: Specify multiple stackinggroups?
Ophiuchus wrote:I think I understand macro expansion. I start to understand how CurrentContent works. I'm often lost about RootCandidate.
Code: Select all
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
]
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.
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).In this case CurrentContent would give me wrong building though (i'm checking if there is the correct building at the capital).
What does "later on in a macro" mean?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.
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 likeAlso from the name of the of the seat building one can infer the government type. Again string manipulation and comparison.
Code: Select all
0.1 <= LocalCandidate.Population
I believe that presently something like this won't work:
Code: Select all
ThisBuilding != RootCandidate.BuildingType
Re: Specify multiple stackinggroups?
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.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.
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
Re: Specify multiple stackinggroups?
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.
https://github.com/mmoderau
[...] 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
[...] 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
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13587
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: Specify multiple stackinggroups?
That is effectively not possible due to unpredictable ordering of effect evaluation and/or multithreading.em3 wrote:...store some variables in the universe itself in one script and access them in another.
The general way to implement something like that would be to try make the Source object the relevant other object.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...
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.
Re: Specify multiple stackinggroups?
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.Geoff the Medio wrote:That is effectively not possible due to unpredictable ordering of effect evaluation and/or multithreading.em3 wrote:...store some variables in the universe itself in one script and access them in another.
I thought though that priority gives guarantees in order of evaluation in case of multithreading. Is that correct?
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 wrongThere'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.
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@".
Last edited by Ophiuchus on Tue Jun 06, 2017 12:39 pm, edited 1 time in total.
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.
Look, ma... four combat bouts!
Look, ma... four combat bouts!
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13587
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: Specify multiple stackinggroups?
Yes, but enforcing the use of priorities to guard against order-of-execution type issues would be problematic.Ophiuchus wrote:I thought though that priority gives guarantees in order of evaluation in case of multithreading. Is that correct?
Depends... Are you looking in the logs for parse error messages, likeOften freeorion just crashes for me if i do something wrong
without any hints why. Should i open issues when such cases happen?
Code: Select all
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.
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....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!
Re: Specify multiple stackinggroups?
But isnt exactly what is done/the intended usecase in case of stackinggroups and priorities?Geoff the Medio wrote:Yes, but enforcing the use of priorities to guard against order-of-execution type issues would be problematic.Ophiuchus wrote:I thought though that priority gives guarantees in order of evaluation in case of multithreading. Is that correct?
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.Often freeorion just crashes for me if i do something wrong
without any hints why. Should i open issues when such cases happen?
Thanks for the info.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.
Thats what I ended up (as indicated in a post way up). But the refactoring felt wrong. So I asked for alternatives.Geoff the Medio wrote: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.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!
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.
Look, ma... four combat bouts!
Look, ma... four combat bouts!
Re: Specify multiple stackinggroups? Getting static context
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.
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.
Any code or patches in anything posted here is released under the CC and GPL licences in use for the FO project.
Re: Specify multiple stackinggroups? Getting static context
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.
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.