Incidencia #42905

The 'survives' flag not surviving obsolescence is a logic mistake

Abrir Fecha: 2021-09-24 10:55 Última actualización: 2021-09-28 03:36

Informador:
Propietario:
(Ninguno)
Tipo:
Estado:
Open
Componente:
Hito:
Prioridad:
5 - Medium
Gravedad:
5 - Medium
Resolución:
Ninguno
Fichero:
1

Details

Basically, any req for a building that is obsolete will automatically render as false when it goes obsolete ANYWAY. So you don't ever NEED to make a req with "survives"==TRUE if you want a req to render false if an improvement is obsolete.

ON THE OTHER HAND, when would we actually want to do the 'survives' check on an obsolete improvement? That's right, to see if the improvement were ever made before, that's exactly when we'd want to check 'survives' on obsolete improvements.

The current coding allows you to check case A two different ways but not be allowed to check case B. The suggested code change below allows ruleset designers to test case A and case B, so for that reason alone is logically superior.

See the comments in the suggested code fix below. This fix now provides semantic correctness for 'survives' and allows rulesets to test ALL possibilities instead of deleting one of the cases from the matrix of possibilities that reqs can test for.

NB: This situation arose in a real ruleset where you are only allowed to build wonder A or wonder B but not both. When your built wonder A goes obsolete it then allowed you to make wonder B. There was no way to test 'survives' on it because it was obsolete. If this was what you wanted, it's easy enough to make the req without needing the 'survives' flag, that always becomes true when a wonder goes obsolete. However what we need the 'survives' flag for was to test if the wonder had EVER been built.

Hope it makes sense, feel free to comment. This is really a major important fix for allowing rulesets to incorporate EITHER/OR logic into players' strategic developmental paths.

requirements.c: /**********************************************************************//**

Are there any source buildings within range of the target that are not obsolete?
The target gives the type of the target. The exact target is a player, city, or building specified by the target_xxx arguments.
The range gives the range of the requirement.
"Survives" specifies whether the requirement allows destroyed OR obsolete
  1. If set then all source buildings ever built are counted; if not then only living buildings are counted.
source gives the building type of the source in question.

**************************************************************************/ static enum fc_tristate is_building_in_range(const struct player *target_player,

const struct city *target_city, const struct impr_type *target_building, enum req_range range, bool survives, const struct impr_type *source)

{

/* Check if it's certain that the building is obsolete given the
    • specification we have. 23Sept2021 (!survives && ...) was added. Its absence was a logic flaw.
This allowed a dead dummy case while preventing a much needed obligatory case. If you want a req to go unfulfilled after an improvement goes obsolete, you don't NEED to mess with the survives flag, since obsolete improvs will render non-present and false anyway. On the other hand, it is very common in XXXX games to have a requirement that you can only make one of X or Y in a game. e.g., either/or one-way strategic paths or defining factions/races/decisions/development paths, or basically any (X || Y && !(X && Y)) type of conditions.
In theory, this change disallows reqs testing the 'survives' flag on the never-before-seen case of an improvement whose purpose is to prevent other improvements only until it's
                1. BUT, since obsoleteness makes improvement reqs render false anyway, the only time you use the 'survives' flag w.r.t. obsolete improvements is to see if they've ever been
This means the 'survives' req is now semantically correct insofar as it 'survives obsolescence' and we can now consistently use 'survives' for the proper purpose of checking if an improvement was ever made. Rulesets can now have conditions on whether something was ever built, instead of leaving rulesets BLIND to whether something was ever built, when it goes obsolete. See changes in reqtext.c commited on this date. */
if (!survives && improvement_obsolete(target_player, source, target_city)) {
return TRI_NO;
}

Ticket History (3/6 Histories)

2021-09-24 10:55 Updated by: lexxie9952
  • New Ticket "The 'survives' flag not surviving obsolescence is a logic mistake" created
2021-09-24 16:31 Updated by: cazfi
  • Hito Update from (Ninguno) to 3.2.0
  • Componente Update from (Ninguno) to General
Comentario

I agree that implementation of seemingly general flag named "survives" is not logically clean (even if I'm not yet exactly convinced of your specific reasoning here - need to reread it with more time in my hands). I think it was added more like "anything-we-need-to-get-apollo-to-work" when effects system was introduced in freeciv-2.0.

I'm not sure if there are any rulesets out there that actually have 'survives' buildings that can also obsolete, but I wouldn't want to start changing semantics for them even in S3_1 (and obviously not in older branches that are d3f) -> targeting to 3.2.

2021-09-24 17:17 Updated by: cazfi
Comentario

Reply To lexxie9952

Basically, any req for a building that is obsolete will automatically render as false when it goes obsolete ANYWAY. So you don't ever NEED to make a req with "survives"==TRUE if you want a req to render false if an improvement is obsolete.

Here you discuss about req rendering *false* when the point of 'survives' is to render req *true* even when the building is destroyed.

I considered the possibility of including building's obsoletion reqs, but negated, in effect's requirements (i.e. if a tech obsoletes the building, that tech would be !present req for the effect), but that wouldn't work because of different point to ranges; obsoletion may have city range requirements about the city the wonder is in, but player-wide effect can't have requirements with the range of that specific city.

2021-09-27 01:41 Updated by: cazfi
  • Prioridad Update from 8 to 5 - Medium
2021-09-28 03:36 Updated by: lexxie9952
Comentario

Reply To cazfi

Reply To lexxie9952

Basically, any req for a building that is obsolete will automatically render as false when it goes obsolete ANYWAY. So you don't ever NEED to make a req with "survives"==TRUE if you want a req to render false if an improvement is obsolete.

Here you discuss about req rendering *false* when the point of 'survives' is to render req *true* even when the building is destroyed. I considered the possibility of including building's obsoletion reqs, but negated, in effect's requirements (i.e. if a tech obsoletes the building, that tech would be !present req for the effect), but that wouldn't work because of different point to ranges; obsoletion may have city range requirements about the city the wonder is in, but player-wide effect can't have requirements with the range of that specific city.

Sorry I found this so difficult to explain. It's better to understand by making a matrix grid for every possible case a ruleset might want.

What rulesets need to be able to do is have a way to test all cases.

The status quo makes 'survives',TRUE on obsolete wonders render false. That would be OK if there were another possible way to check that an obsolete wonder was ever built. But there isn't. Any possible way to fix this will satisfy ruleset designers. In my opinion, the easiest way to fix it is by making 'survives' 100% semantic consistency across all cases: "any tech or wonder that was ever discovered or made at any point, will render true with 'survives',TRUE in the req vector."

The first thing we think when making such a change is, "what use case gets destroyed by this new 'semantic correctness'? I'll say it here. It's a black swan and truly RARA AVIS: it would be a wonder that you want to use to prevent other improvements only until it's obsolete, which continues to prevent other improvements even after destroyed, but not after the destroyed wonder would be made obsolete if it still existed and hadn't been destroyed. I'm pretty sure this case has never existed, but yes...

We want to preserve the ability to code ALL possibilities in the ruleset, even this rare one. But we sure don't want to prevent the ability to check if a wonder was ever made, because of this super rare hypothetical case.

How do we preserve the ability for a wonder that when destroyed but not obsolete still has the effect of preventing other effects?

I would argue that ruleset designers can code such a rare case another way.

They could code for (X && Y)==TRUE, where X==The wonder was ever made must be true AND Y==The things which make that wonder obsolete are not fulfilled.

In my opinion, this is a good solution because 1. It now allows ruleset designers to test every possible case. 2. The much more frequent case of wanting to test if a wonder was ever made, is a lot more consistent and semantically cleaner. 3. The fix is ultra simple and only adds one snippet to a single line of code.

Whatever solution is ultimately adopted, I will be happy as long as we can test if a wonder has ever been built.

Cheers

Attachment File List

Editar

You are not logged in. I you are not logged in, your comment will be treated as an anonymous post. » Entrar