Specify multiple stackinggroups? Getting static context info

Creation, discussion, and balancing of game content such as techs, buildings, ship parts.

Moderators: Oberlus, Committer

Post Reply
Message
Author
Ophiuchus
Programmer
Posts: 3433
Joined: Tue Sep 30, 2014 10:01 am
Location: Wall IV

Specify multiple stackinggroups? Getting static context info

#1 Post by Ophiuchus »

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@".
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!

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13587
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Specify multiple stackinggroups?

#2 Post by Geoff the Medio »

A stacking group is a single string, not a container of multiple strings.

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

Ophiuchus
Programmer
Posts: 3433
Joined: Tue Sep 30, 2014 10:01 am
Location: Wall IV

Re: Specify multiple stackinggroups?

#3 Post by Ophiuchus »

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.

Look, ma... four combat bouts!

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13587
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Specify multiple stackinggroups?

#4 Post by Geoff the Medio »

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.
Are there other ways to access context information?
What sort of context?
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.

User avatar
MatGB
Creative Contributor
Posts: 3310
Joined: Fri Jun 28, 2013 11:45 pm

Re: Specify multiple stackinggroups?

#5 Post by MatGB »

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.

Ophiuchus
Programmer
Posts: 3433
Joined: Tue Sep 30, 2014 10:01 am
Location: Wall IV

Re: Specify multiple stackinggroups?

#6 Post by Ophiuchus »

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.
Are there other ways to access context information?
What sort of context?
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 :/
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!

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13587
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Specify multiple stackinggroups?

#7 Post by Geoff the Medio »

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
    ]
"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.
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).
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?
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: Select all

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: Select all

ThisBuilding != RootCandidate.BuildingType
, since that comparison format appears to only accept numbers.

User avatar
Dilvish
AI Lead and Programmer Emeritus
Posts: 4768
Joined: Sat Sep 22, 2012 6:25 pm

Re: Specify multiple stackinggroups?

#8 Post by Dilvish »

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

User avatar
em3
Vacuum Dragon
Posts: 630
Joined: Sun Sep 25, 2011 2:51 pm

Re: Specify multiple stackinggroups?

#9 Post by em3 »

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

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13587
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Specify multiple stackinggroups?

#10 Post by Geoff the Medio »

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.

Ophiuchus
Programmer
Posts: 3433
Joined: Tue Sep 30, 2014 10:01 am
Location: Wall IV

Re: Specify multiple stackinggroups?

#11 Post by Ophiuchus »

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?
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@".
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!

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13587
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Specify multiple stackinggroups?

#12 Post by Geoff the Medio »

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.
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: 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.
...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.

Ophiuchus
Programmer
Posts: 3433
Joined: Tue Sep 30, 2014 10:01 am
Location: Wall IV

Re: Specify multiple stackinggroups?

#13 Post by Ophiuchus »

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?
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.
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.

Look, ma... four combat bouts!

User avatar
MatGB
Creative Contributor
Posts: 3310
Joined: Fri Jun 28, 2013 11:45 pm

Re: Specify multiple stackinggroups? Getting static context

#14 Post by MatGB »

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.

User avatar
Vezzra
Release Manager, Design
Posts: 6095
Joined: Wed Nov 16, 2011 12:56 pm
Location: Sol III

Re: Specify multiple stackinggroups? Getting static context

#15 Post by Vezzra »

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.

Post Reply