RFC: A single source for default values (FOCS, python, stringtables, backend)
Moderator: Oberlus
RFC: A single source for default values (FOCS, python, stringtables, backend)
How about we add a file (or files in directory tree) for having a single source of default game values so FOCS, AI, stringtables and backend can use it.
At the moment we often have to replicate values manually in all those places and keep consistent. For example i think many values in languages other than french and english are wrong or not even mentioned because we fear they could change. Also AI could rely on outdated values.
If we have a single place to take those values from the values are always "auto-magically" consistent.
That file format should only contain key/value pairs and could be put into files default/default.values or e.g. default/scripting/ship_hulls/ship_hulls.values.
The mechanism which comes closest are game rules, but i think it is UI-overkill to add a rule for each base value which might change in development.
At the moment we often have to replicate values manually in all those places and keep consistent. For example i think many values in languages other than french and english are wrong or not even mentioned because we fear they could change. Also AI could rely on outdated values.
If we have a single place to take those values from the values are always "auto-magically" consistent.
That file format should only contain key/value pairs and could be put into files default/default.values or e.g. default/scripting/ship_hulls/ship_hulls.values.
The mechanism which comes closest are game rules, but i think it is UI-overkill to add a rule for each base value which might change in development.
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: RFC: A single source for default values (FOCS, python, stringtables, backend)
Gentoo Linux x64, gcc-11.2, boost-1.78.0
Ubuntu Server 22.04 x64, gcc-12, boost-1.74.0
Welcome to the slow multiplayer game at freeorion-lt.dedyn.io.Version 2024-04-14.ad50e93.
Donations're welcome:BTC:bc1q007qldm6eppqcukewtfkfcj0naut9njj7audnm
Ubuntu Server 22.04 x64, gcc-12, boost-1.74.0
Welcome to the slow multiplayer game at freeorion-lt.dedyn.io.Version 2024-04-14.ad50e93.
Donations're welcome:BTC:bc1q007qldm6eppqcukewtfkfcj0naut9njj7audnm
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
I'm totally in favor of that. For all the reasons listed there, and because I still don't understand the syntax of FOCS. Wiki and the such are helpful but not enough, at all, there is always places were all you (non FOC-expert) can do is trial and error until Geoff or someone else comes in rescue. If I have to learn a new language, Python would be more interesting than FOCS.o01eg wrote: ↑Sat Nov 16, 2019 11:35 am What about https://freeorion.org/forum/viewtopic.php?f=9&t=10215 ?
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13603
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
I don't think replacing FOCS with Python-parsed structs would help much with needing help or learning Python in general. The hard-to-learn domain-specific issues of what stuff can be scripted wouldn't change, and very little Python code would be involved, as the "scripting" would still be mostly declarative definitions of parts, techs, species and such with their contained effects, conditions, and valuerefs. There may be advantages to Python-declared scripting vs. Boost-parsed scripting, but those aren't. (See the example in the linked post.)Oberlus wrote: ↑Sat Nov 16, 2019 11:50 am...because I still don't understand the syntax of FOCS. Wiki and the such are helpful but not enough, at all, there is always places were all you (non FOC-expert) can do is trial and error until Geoff or someone else comes in rescue. If I have to learn a new language, Python would be more interesting than FOCS.
What default values are you referring to?
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
Any value you can find in a FOCS file, like the base structure of a hull, the boost to a meter from a tech/building, etc.
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13603
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
The issue in that case doesn't depend on what scripting language is used; switching to Python won't change anything.
What you want is either:
1) A way to look up a scripted value in another script, in a stringtable entry, or in the AI code
or
2) A way to define those values in a single place and reference the defined value in any of
(2) would could be awkward to use for things like part costs or hull structure, as it would essentially mean having a big table, or many small tables, of macro definitions, which can be inserted / referenced like normal stringtable or script macros into scripts or stringtables, rather than putting those values into the scripts themselves. This would mean the values wouldn't be defined where the content that uses them is defined. This can already be done, however, as you can #include files into other stringtable or FOCS files, and both can use macros lookups by [[KEY]].
(1) would require a way to look up scripted values by writing a little script to do so, and be able to do so within stringtable macros. It's already possible for some things in FOCS, like using the HullStructure complex value ref and passing the name of the hull ( https://github.com/freeorion/freeorion/ ... er.cpp#L47 ). But there's no way to write an equivalent FOCS script into a stringtable macro though, and have it be evaluated at runtime, and it would be a bit of work to allow it. Notably, it would be a run-time / lazy lookup, so that it can look up the data in the current game using the currently-applicable parsed content, which could change if the resources directory is changed or a game's rules are changed. Something similar is already done by having various parameters in stringtables like %1% which are replaced when the string is rendered in-game, based on the C++ code expecting a particular stringtable entry to have %1% and similar fields in it to be replaced. Scripting those substitutions in the stringtable entry itself would be more complicated and require some additional coding to support, but shouldn't be impossible... maybe something like:
[[FOCSVAL HullStructure name = "SH_COLONY_BASE"]]
Which would be replaced by whatever the stucture is of the colony base hull in the current game, evaluated when the string is being rendered.
What you want is either:
1) A way to look up a scripted value in another script, in a stringtable entry, or in the AI code
or
2) A way to define those values in a single place and reference the defined value in any of
(2) would could be awkward to use for things like part costs or hull structure, as it would essentially mean having a big table, or many small tables, of macro definitions, which can be inserted / referenced like normal stringtable or script macros into scripts or stringtables, rather than putting those values into the scripts themselves. This would mean the values wouldn't be defined where the content that uses them is defined. This can already be done, however, as you can #include files into other stringtable or FOCS files, and both can use macros lookups by [[KEY]].
(1) would require a way to look up scripted values by writing a little script to do so, and be able to do so within stringtable macros. It's already possible for some things in FOCS, like using the HullStructure complex value ref and passing the name of the hull ( https://github.com/freeorion/freeorion/ ... er.cpp#L47 ). But there's no way to write an equivalent FOCS script into a stringtable macro though, and have it be evaluated at runtime, and it would be a bit of work to allow it. Notably, it would be a run-time / lazy lookup, so that it can look up the data in the current game using the currently-applicable parsed content, which could change if the resources directory is changed or a game's rules are changed. Something similar is already done by having various parameters in stringtables like %1% which are replaced when the string is rendered in-game, based on the C++ code expecting a particular stringtable entry to have %1% and similar fields in it to be replaced. Scripting those substitutions in the stringtable entry itself would be more complicated and require some additional coding to support, but shouldn't be impossible... maybe something like:
[[FOCSVAL HullStructure name = "SH_COLONY_BASE"]]
Which would be replaced by whatever the stucture is of the colony base hull in the current game, evaluated when the string is being rendered.
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
Indeed. My issues with FOCS syntax and preference for Python were properly addressed with your previous postGeoff the Medio wrote: ↑Sat Nov 16, 2019 2:45 pmThe issue in that case doesn't depend on what scripting language is used; switching to Python won't change anything.
I think that's what I'd prefer.2) A way to define those values in a single place and reference the defined value in any of
(2) would could be awkward to use for things like part costs or hull structure, as it would essentially mean having a big table, or many small tables, of macro definitions, which can be inserted / referenced like normal stringtable or script macros into scripts or stringtables, rather than putting those values into the scripts themselves. This would mean the values wouldn't be defined where the content that uses them is defined. This can already be done, however, as you can #include files into other stringtable or FOCS files, and both can use macros lookups by [[KEY]].
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
A combination of both approaches would be best in my opinion. But standard things like part costs, hull structure etc are well enough addressed as you can simply experiment in the ship designer and have a look at the results and also the AI has access to such values.Geoff the Medio wrote: ↑Sat Nov 16, 2019 2:45 pm 1) A way to look up a scripted value in another script, in a stringtable entry, or in the AI code
or
2) A way to define those values in a single place and reference the defined value in any of
(2) would could be awkward to use for things like part costs or hull structure, as it would essentially mean having a big table, or many small tables, of macro definitions, which can be inserted / referenced like normal stringtable or script macros into scripts or stringtables, rather than putting those values into the scripts themselves. This would mean the values wouldn't be defined where the content that uses them is defined. This can already be done, however, as you can #include files into other stringtable or FOCS files, and both can use macros lookups by [[KEY]].
So what is more pressing are things like organic hull growth effects and similar for which approach 2) is probably enough.
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: RFC: A single source for default values (FOCS, python, stringtables, backend)
I'm trying to do this.
I've done the following:
New file /default/scripting/techs/defense/defense_values.macros
Changes in /default/scripting/techs/defense/Garrison.focs.txt
That is, add the end of the file #include "/scripting/common/priorities.macros"
And change the values for the macros in that included file.
Changes in /default/stringtables/en.txt:
That is, substitute the values for the macros and add the new macros files at the end of file.
It doesn't work. Specifically it breaks all referencing in all Pedia articles (and probably in other places). Examples:
The Pedia button in the splash screen now says "[[MAP_BTN_PEDIA]]".
The Pedia article for specials -> Abandoned Colony now shows "An old abandoned colony. Some of the [[metertype METER_CONSTRUCTION]] should still be useful." (that is, the macro/link for metertype METER_CONSTRUCTION is not working).
What I am doing wrong?
I've done the following:
New file /default/scripting/techs/defense/defense_values.macros
Code: Select all
DEF_GARRISON_1_FLAT_BONUS
'''50 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_2_POP_BONUS
'''2 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_2_REG
'''5 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_3_FLAT_BONUS
'''80 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_3_REG
'''10 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_4_POP_BONUS
'''2 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_4_REG
'''15 * [[TROOPS_PER_POP]]'''
#include "/scripting/common/base_prod.macros"
Code: Select all
Tech
name = "DEF_GARRISON_1"
description = "DEF_GARRISON_1_DESC"
short_description = "TROOPS_SHORT_DESC"
category = "DEFENSE_CATEGORY"
researchcost = 5 * [[TECH_COST_MULTIPLIER]]
researchturns = 3
tags = [ "PEDIA_DEFENSE_CATEGORY" ]
prerequisites = "DEF_ROOT_DEFENSE"
effectsgroups = [
EffectsGroup
scope = And [
Planet
OwnedBy empire = Source.Owner
]
stackinggroup = "GARRISON_1_TROOPS_STACK"
priority = [[LATE_PRIORITY]]
effects = SetMaxTroops value = Value + [[DEF_GARRISON_1_FLAT_BONUS]] accountinglabel = "DEF_GARRISON_1"
]
graphic = "icons/tech/troops.png"
Tech
name = "DEF_GARRISON_2"
description = "DEF_GARRISON_2_DESC"
short_description = "TROOPS_SHORT_DESC"
category = "DEFENSE_CATEGORY"
researchcost = 15 * [[TECH_COST_MULTIPLIER]]
researchturns = 5
tags = [ "PEDIA_DEFENSE_CATEGORY" ]
prerequisites = "DEF_GARRISON_1"
effectsgroups = [
EffectsGroup
scope = And [
Planet
OwnedBy empire = Source.Owner
(LocalCandidate.LastTurnAttackedByShip < CurrentTurn)
]
effects = SetTroops value = Value + [[DEF_GARRISON_2_REG]]
EffectsGroup
scope = And [
Planet
OwnedBy empire = Source.Owner
Population low = 0.01
]
stackinggroup = "GARRISON_2_TROOPS_STACK"
priority = [[EARLY_PRIORITY]]
effects = SetMaxTroops value = Value + Target.Population * [[DEF_GARRISON_2_POP_BONUS]] accountinglabel = "DEF_GARRISON_2"
]
graphic = "icons/tech/troops.png"
Tech
name = "DEF_GARRISON_3"
description = "DEF_GARRISON_3_DESC"
short_description = "TROOPS_SHORT_DESC"
category = "DEFENSE_CATEGORY"
researchcost = 50 * [[TECH_COST_MULTIPLIER]]
researchturns = 7
tags = [ "PEDIA_DEFENSE_CATEGORY" ]
prerequisites = "DEF_GARRISON_2"
effectsgroups = [
EffectsGroup
scope = And [
Planet
OwnedBy empire = Source.Owner
(LocalCandidate.LastTurnAttackedByShip < CurrentTurn)
]
effects = SetTroops value = Value + [[DEF_GARRISON_3_REG]]
EffectsGroup
scope = And [
Planet
OwnedBy empire = Source.Owner
]
stackinggroup = "GARRISON_3_TROOPS_STACK"
priority = [[LATE_PRIORITY]]
effects = SetMaxTroops value = Value + [[DEF_GARRISON_3_FLAT_BONUS]] accountinglabel = "DEF_GARRISON_3"
]
graphic = "icons/tech/troops.png"
Tech
name = "DEF_GARRISON_4"
description = "DEF_GARRISON_4_DESC"
short_description = "TROOPS_SHORT_DESC"
category = "DEFENSE_CATEGORY"
researchcost = 150 * [[TECH_COST_MULTIPLIER]]
researchturns = 9
tags = [ "PEDIA_DEFENSE_CATEGORY" ]
prerequisites = "DEF_GARRISON_3"
effectsgroups = [
EffectsGroup
scope = And [
Planet
OwnedBy empire = Source.Owner
(LocalCandidate.LastTurnAttackedByShip < CurrentTurn)
]
effects = SetTroops value = Value + [[DEF_GARRISON_4_REG]]
EffectsGroup
scope = And [
Planet
OwnedBy empire = Source.Owner
Population low = 0.01
]
stackinggroup = "GARRISON_4_TROOPS_STACK"
priority = [[EARLY_PRIORITY]]
effects = SetMaxTroops value = Value + Target.Population * [[DEF_GARRISON_4_POP_BONUS]] accountinglabel = "DEF_GARRISON_4"
]
graphic = "icons/tech/troops.png"
#include "../techs.macros"
#include "/scripting/techs/defense/defense_values.macros"
#include "/scripting/common/priorities.macros"
And change the values for the macros in that included file.
Changes in /default/stringtables/en.txt:
Code: Select all
DEF_GARRISON_1_DESC
Increases max [[metertype METER_TROOPS]] on all planets by [[DEF_GARRISON_1_FLAT_BONUS]], unmodified by species traits.
DEF_GARRISON_2
Defensive Militia Training
DEF_GARRISON_2_DESC
Increases max [[metertype METER_TROOPS]] on all planets by [[DEF_GARRISON_2_POP_BONUS]] per [[metertype METER_POPULATION]] (modified by species defensive trait), and causes troops to regenerate by an additional [[DEF_GARRISON_2_REG]] per turn.
DEF_GARRISON_3
Planetary Fortification Network
DEF_GARRISON_3_DESC
Increases max [[metertype METER_TROOPS]] on all planets by [[DEF_GARRISON_3_FLAT_BONUS]] (unmodified by species traits) and causes troops to regenerate by an additional [[DEF_GARRISON_3_REG]] per turn in addition to that from [[DEF_GARRISON_2]].
DEF_GARRISON_4
Planetary Guard Brigades
DEF_GARRISON_4_DESC
Increases max [[metertype METER_TROOPS]] on all planets by [[DEF_GARRISON_4_POP_BONUS]] per [[metertype METER_POPULATION]] (modified by species defensive trait), and causes troops to regenerate by an additional [[DEF_GARRISON_4_REG]] per turn in addition to that from [[DEF_GARRISON_3]] and [[DEF_GARRISON_2]].
// At the end of the file after the other #include:
#include "../scripting/techs/defense/defense_values.macros"
It doesn't work. Specifically it breaks all referencing in all Pedia articles (and probably in other places). Examples:
The Pedia button in the splash screen now says "[[MAP_BTN_PEDIA]]".
The Pedia article for specials -> Abandoned Colony now shows "An old abandoned colony. Some of the [[metertype METER_CONSTRUCTION]] should still be useful." (that is, the macro/link for metertype METER_CONSTRUCTION is not working).
What I am doing wrong?
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
Nothing, I think it is not supported. At least not for calculated macros.
You could try if simple string expansion for macros works already.
something like:
DEF_GARRISON_2_POP_BONUS
'''2'''
Of course what we need are calculated values, at least some support for arithmetics (+,-,*,rounding) including game rule lookups.
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: 13603
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
Macros insert text into other text, including into stringtable entries. The issue is that there is no mechanism for a non-trival (ie. not plain text) FOCS expression in a stringtable entry to be evaluated and replaced with something else. Whether or not the expression is present due to being written explicitly or by macro substitution doesn't matter.
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
If I read you correctly you would expect the following to work/be usable in stringtables?Geoff the Medio wrote: ↑Fri May 29, 2020 11:37 amMacros insert text into other text, including into stringtable entries. The issue is that there is no mechanism for a non-trival (ie. not plain text) FOCS expression in a stringtable entry to be evaluated and replaced with something else. Whether or not the expression is present due to being written explicitly or by macro substitution doesn't matter.
MACRO_OUTER
'''[[MACRO_SPACE]]'''
MACRO_SPACE
''' '''
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: 13603
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
yesIf I read you correctly you would expect the following to work/be usable in stringtables?
MACRO_OUTER
'''[[MACRO_SPACE]]'''
MACRO_SPACE
''' '''
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
I tried it. Not sure if I got it right.
New file defense_values.macros
And the references to the macros in the stringtable changed to the "*_ST" ones
I also tried putting the "_ST" macros in second place.
The scrambled Pedia problem persists.
Also, there's and error at freeorion start:
New file defense_values.macros
Code: Select all
DEF_GARRISON_1_FLAT_BONUS_ST
'''[[DEF_GARRISON_1_FLAT_BONUS]]''
DEF_GARRISON_1_FLAT_BONUS
'''50 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_2_POP_BONUS_ST
'''[[DEF_GARRISON_2_POP_BONUS]]'''
DEF_GARRISON_2_POP_BONUS
'''2 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_2_REG_ST
'''[[DEF_GARRISON_2_REG]]'''
DEF_GARRISON_2_REG
'''5 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_3_FLAT_BONUS_ST
'''[[DEF_GARRISON_3_FLAT_BONUS]]'''
DEF_GARRISON_3_FLAT_BONUS
'''80 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_3_REG_ST
'''[[DEF_GARRISON_3_REG]]'''
DEF_GARRISON_3_REG
'''10 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_4_POP_BONUS_ST
'''[[DEF_GARRISON_4_POP_BONUS]]'''
DEF_GARRISON_4_POP_BONUS
'''2 * [[TROOPS_PER_POP]]'''
DEF_GARRISON_4_REG_ST
'''[[DEF_GARRISON_4_REG]]'''
DEF_GARRISON_4_REG
'''15 * [[TROOPS_PER_POP]]'''
#include "/scripting/common/base_prod.macros"
I also tried putting the "_ST" macros in second place.
The scrambled Pedia problem persists.
Also, there's and error at freeorion start:
Code: Select all
/home/lucas/Projects/FreeOrion/master-testing-build/default/scripting/techs/defense/Garrison.focs.txt:18:49: Parse error. Expected ] here:
Planet
OwnedBy empire = Source.Owner
]
stackinggroup = "GARRISON_1_TROOPS_STACK"
priority = 110
effects = SetMaxTroops value = Value + [[DEF_GARRISON_1_FLAT_BONUS]]
^
accountinglabel = "DEF_GARRISON_1"
]
graphic = "icons/tech/troops.png"
Tech
- Geoff the Medio
- Programming, Design, Admin
- Posts: 13603
- Joined: Wed Oct 08, 2003 1:33 am
- Location: Munich
Re: RFC: A single source for default values (FOCS, python, stringtables, backend)
I'm not sure what you're trying to do here, but it doesn't appear to be a simple text substitution with nested stringtable keys likeOberlus wrote: ↑Sat May 30, 2020 1:20 pmNew file defense_values.macrosCode: Select all
DEF_GARRISON_1_FLAT_BONUS_ST '''[[DEF_GARRISON_1_FLAT_BONUS]]'' DEF_GARRISON_1_FLAT_BONUS '''50 * [[TROOPS_PER_POP]]'''
Code: Select all
MACRO_OUTER
'''[[MACRO_SPACE]]'''
MACRO_SPACE
''' '''
There are probably error messages in the logs telling you what's wrong with the stringtable. My guess is the use of undefined key substitutions.