Invariants for OneOf / RANDOM_PICK

Programmers discuss here anything related to FreeOrion programming. Primarily for the developers to discuss.

Moderator: Committer

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

Invariants for OneOf / RANDOM_PICK

#1 Post by Ophiuchus »

The OneOf FOCS (usually?) takes a list of constant values.

The resulting valueref is a Operation with m_op_type == OpType::RANDOM_PICK

void Operation<T>::InitConstInvariants() sets all invariants to false.

The random pick between constant expressions is certainly not a constant expression, but it is invariant regarding Source, Target, LocalCandidate, and RootCandidate.
I really do not know if (and in which cases) it should be a simple increment or not.

So I guess the RandomPick should be invariant regarding a X (in Source,Target,LocalCandidate,or RootCandidate) iff all of the operands are invariant regarding that X.
So pretty much the standard case for operations, or?
Just never constant (if there are at least two operands).

Side Note: also OpType::NOOP should be totally invariant and constant
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: Invariants for OneOf / RANDOM_PICK

#2 Post by Geoff the Medio »

Ophiuchus wrote: Wed Jul 20, 2022 9:09 amrandom pick between constant expressions is certainly not a constant expression, but it is invariant regarding Source, Target, LocalCandidate, and RootCandidate.
ValueRef invariances indicate two things:
1) The result will be the same if a valueref is evaluated repeatedly, with the context the same except for a particular object in the context (eg. the source object)
2) While evaluating the valueref, no attempt is made to access a particular object in the context (eg. the source object)

The point is to indicate that the valueref can be evaluated once and the single result used even if the context is changed by modifying the indicated object. For example, if checking whether various source objects have stealth above some level, does that level depend on which source object is being checked via a Source.Stealth sub-expression. It also means that the valueref can be evaluating by passing it a context that has nothing set for the indicated object (that the valueref is invariant to). This means that an existing context can be used as is, rather than having to create a new one or modify an existing one in order to set its eg. source object appropriately to ensure the reference within the valueref will be correctedly resolved.

If the ref is generating a random number to determine its result each time it's evaluated, then it can't be invariant to anything, since if it is evaluated repeatedly with different objects in the context (or even with the exact same context), it will potentially produce different outputs. Thus it needs to be re-evaluated for each case, eg. for each object when checking a list of source objects, for each of which, the context will have a difference source object in it.

Possibly these concepts could be spearated, so that something could be eg. variant to the source object even if it doesn't attempt to access it, which would potentially enable a few minor optimizations in cases like random picking, where the valueref needs to be evaluated separately for each case, but doesn't actually need a context with a usable object set in it. The number of cases where this would be helpful is probably small, though.
I really do not know if (and in which cases) it should be a simple increment or not.
Never. Random picking is not a case of an operation involving only a target-invariant value and the current value of whatever the effect is modifying, eg. Value + 5 or Value * Source.Stealth. See https://github.com/freeorion/freeorion/ ... 1834-L1840 The point of simple increment is that it's more efficient to evaluate the the effectively-constant (with respect to target objects) number once, and then use it to modify every target object, rather than re-evaluating the number for every target object.
Side Note: also OpType::NOOP should be totally invariant and constant
The point of NoOp operations and conditions (and effects) is debugging. It's useful to be able to put a breakpoint in NoOp and get a hit each time it's evaluated. This means it can't be invariant to anything, as it should be re-evaluated for every time.

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

Re: Invariants for OneOf / RANDOM_PICK

#3 Post by Ophiuchus »

Geoff the Medio wrote: Wed Jul 20, 2022 10:21 am
Side Note: also OpType::NOOP should be totally invariant and constant
The point of NoOp operations and conditions (and effects) is debugging. It's useful to be able to put a breakpoint in NoOp and get a hit each time it's evaluated. This means it can't be invariant to anything, as it should be re-evaluated for every time.
fair enough
Geoff the Medio wrote: Wed Jul 20, 2022 10:21 am If the ref is generating a random number to determine its result each time it's evaluated, then it can't be invariant to anything, since if it is evaluated repeatedly with different objects in the context (or even with the exact same context), it will potentially produce different outputs. Thus it needs to be re-evaluated for each case, eg. for each object when checking a list of source objects, for each of which, the context will have a difference source object in it.
hm. is evaluation skipped from the outside? or is Eval getting called and that does the necessary thing?


In general, we certainly have some problems regarding totally random results (e.g. effect on a random planet; and the corresponding sitrep message is talking about a different planet because for the sitrep another planet was chosen).


I have a named valueref which uses OneOf and can be evaluated in any context: NamedString name = "NATIVE_GUARDS_TERRAN" value = OneOf("SP_RAAAGH", "SP_ANCIENT_GUARDIANS")

But it shows a warning in the logs that invariant valuerefs are not supported (in the sense that has not really been tested) - in this case this warning is bogus as it can be evaluated in any context.
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: Invariants for OneOf / RANDOM_PICK

#4 Post by Geoff the Medio »

Ophiuchus wrote: Wed Jul 20, 2022 11:03 amhm. is evaluation skipped from the outside? or is Eval getting called and that does the necessary thing?
Not sure what you're asking. Various places do something similar to a check if a valueref or condition is invariant to something, and if it is, evaluate it once with a context that is suitable in that case, and if it isn't, evaluate it reapeatedly with a context that is updated for each tested object, with that object set as the value of the not-invariant thing in the context.
...effect on a random planet; and the corresponding sitrep message is talking about a different planet because for the sitrep another planet was chosen
Sounds like a situation where the randomness should be in the scope condition, not within the effect itself. Or possibly something that shouldn't be done if it's a meter effect, as those get re-run multiple times per turn and could have inconsistent random results between those re-runs.
I have a named valueref which uses OneOf and can be evaluated in any context: NamedString name = "NATIVE_GUARDS_TERRAN" value = OneOf("SP_RAAAGH", "SP_ANCIENT_GUARDIANS")

But it shows a warning in the logs that invariant valuerefs are not supported (in the sense that has not really been tested) - in this case this warning is bogus as it can be evaluated in any context.
I would need to see specifics to comment. Edit: I guess: https://github.com/freeorion/freeorion/ ... #L155-L157 I think the intended use was for constants, but I'm not sure if / why that error message is needed.

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

Re: Invariants for OneOf / RANDOM_PICK

#5 Post by Ophiuchus »

Geoff the Medio wrote: Wed Jul 20, 2022 11:35 am
...effect on a random planet; and the corresponding sitrep message is talking about a different planet because for the sitrep another planet was chosen
Sounds like a situation where the randomness should be in the scope condition, not within the effect itself. Or possibly something that shouldn't be done if it's a meter effect, as those get re-run multiple times per turn and could have inconsistent random results between those re-runs.
AFAICR that was (is?) also happening with all sitrep messages because those had (have?) their own phase of evaluation. Probably this wont get solved completely as long as we have different phases or we make the randomness deterministic.
One way to make the randomness deterministic: the random number generator gets three parameters as input: a random seed per turn, the Source id, the id of the evaluated effect/condition). Battle currently does not need this as the effects are not reevaluated, else also the bout needs to be added to the input parameters.
Geoff the Medio wrote: Wed Jul 20, 2022 11:35 am
I have a named valueref which uses OneOf and can be evaluated in any context: NamedString name = "NATIVE_GUARDS_TERRAN" value = OneOf("SP_RAAAGH", "SP_ANCIENT_GUARDIANS")

But it shows a warning in the logs that invariant valuerefs are not supported (in the sense that has not really been tested) - in this case this warning is bogus as it can be evaluated in any context.
I would need to see specifics to comment.
well, I wrote the check in NamedValueRefManager - I check if the valueref claims to be invariant to Source,Target,LocalCandidate,and RootCandidate.

Code: Select all

12:33:10.162871 {0x00007f36fee58640} [error] server : NamedValueRefManager.cpp:157 : Currently only invariant value refs can be named. NATIVE_GUARDS_TERRAN
the point being that at registration time one cannot ensure that those actually exist/ that the context in which the value ref is used fits to the value ref. E.g. printing out some value ref in the pedia.
but i think if the context fits, also invariant valuerefs should work (but that has not been tested).

For the moment I think i will simply ignore the warning.

Anyway the listing of named value refs in the pedia is broken it seems (at least it does not print anything for me).
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: Invariants for OneOf / RANDOM_PICK

#6 Post by Geoff the Medio »

Ophiuchus wrote: Wed Jul 20, 2022 11:59 amAnyway the listing of named value refs in the pedia is broken it seems (at least it does not print anything for me).
Works for me, at least from the title screen...
named refs listed in pedia
named refs listed in pedia
named refs in pedia.png (535.56 KiB) Viewed 1052 times

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

Re: Invariants for OneOf / RANDOM_PICK

#7 Post by Ophiuchus »

Geoff the Medio wrote: Wed Jul 20, 2022 1:05 pm
Ophiuchus wrote: Wed Jul 20, 2022 11:59 amAnyway the listing of named value refs in the pedia is broken it seems (at least it does not print anything for me).
Works for me, at least from the title screen...
Also checked from title screen; it does not work in the current snap build as well as local built on my fedora 36 workstation.
Aaargh :x
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!

Post Reply