Changing how description= and user_description= work

Discussion among members of the development team.

Moderators: Forum Moderators, Developers

Post Reply
User avatar
zookeeper
WML Wizard
Posts: 9739
Joined: September 11th, 2004, 10:40 pm
Location: Finland

Changing how description= and user_description= work

Post by zookeeper » May 10th, 2007, 5:31 pm

This is a continuation from this bug report. Please read the discussion therein at least somewhat before giving loud opinions, as there are a few quite good and non-obvious points made by Darth Fool there. Basically, Darth Fool wants to have a unique identifier given to recruited and scenario-spawned (right?) units in their description= field, unless of course one is manually specified. The problem with this is that description= gets used as the player-visible user_description= by default, unless that too is manually specified. This in turn causes the identifier (which is something like <unittype>-<number>) in many places currently to become player-visible.

So, I'd like to scrap the autogeneration of user_description= from description= if no user_description= is specified. We can get rid of relying on the autogeneration in mainline, and currently the only culprits that do this are the newly added NR and SotBE. I don't think there's all that much UMC that relies on this, and it's something that you haven't really been supposed to be doing in the first place (well, ok, I'm not entirely sure if this is the case, perhaps not). This would eliminate the possibility of the generated identifier from accidentally appearing as the unit's name in-game.

Now, when I really think about it, I don't think Darth Fool's idea of forcing one to specify an empty random name list for races which won't be getting random names (namely undead in mainline) is really an inconvenience, but I'd still very much dislike it if I were to spawn a nameless unit (imagine all those generic undead spawnings that always happen everywhere) manually via [unit], not specify an empty user_description= and end up with the generated description= being used in it's place. So really, this is currently my only objection to that particular solution, since I'd always have to specify an empty user_description= for nameless scenario-spawned units.

So, are any campaign authors or otherwise potentially affected WML people against the idea of removing the use of description= as the default user_description= if no user_description= is explicitly specified?

User avatar
Mist
Inactive Developer
Posts: 753
Joined: February 15th, 2007, 8:44 am
Location: Milton Keynes, UK

Post by Mist » May 10th, 2007, 7:38 pm

There was(is) a WML key used to generate random names with Markov generator. Can't we simply force it as default option that has to be explicitly switched off (though I can't see the reason for doing this) ? This way placing things with [unit] (reading form savegame) would be equal to recruiting in all technical details and end user would notice no difference.

This way wouldn't break any WML and would allow to scrap the need for generating user_decriptionfrom description.
Somewhere, between the sacred silence and sleep.
Disorder.

User avatar
zookeeper
WML Wizard
Posts: 9739
Joined: September 11th, 2004, 10:40 pm
Location: Finland

Post by zookeeper » May 17th, 2007, 2:42 pm

Well, no other replies so far, so I assume not many people care either way. Personally I think Mist came up with a pretty good idea (just having generate_description= be "yes" by default), one which I think I'd tend to agree with. Darth Fool, shall we go with that one?

User avatar
Jetrel
Art Director
Posts: 7241
Joined: February 23rd, 2004, 3:36 am
Location: Midwest US

Post by Jetrel » May 17th, 2007, 3:30 pm

zookeeper wrote:Well, no other replies so far, so I assume not many people care either way. Personally I think Mist came up with a pretty good idea (just having generate_description= be "yes" by default), one which I think I'd tend to agree with. Darth Fool, shall we go with that one?
Yeah, I think his idea was pretty good. Darth Fool?

Darth Fool
Retired Developer
Posts: 2633
Joined: March 22nd, 2004, 11:22 pm
Location: An Earl's Roadstead

Post by Darth Fool » May 17th, 2007, 3:34 pm

Well, that might work with modifications. I will have to think about it.

Darth Fool
Retired Developer
Posts: 2633
Joined: March 22nd, 2004, 11:22 pm
Location: An Earl's Roadstead

Post by Darth Fool » May 22nd, 2007, 10:11 pm

Ok, here is a matrix of how I think that it might work. In this case, "D" means that the Description exists (ie !=""), "U" means that the Underlying Description Exists, and "G" means that Generate_description exists and = "yes" or equivalent. "_" means that the corresponding element does not exist.

Code: Select all

DUG -> do nothing
DU_ -> do nothing
D_G -> generate U
_UG -> generate D from race names
D__ -> generate U
_U_ -> generate D from U
__G -> generate U.  Generate D from race names
___ -> generate U. leave D blank.
Now, let's make sure that this works:
when DU exist it doesn't matter what G is.
when U does not exist, it is generated.
when D exists it is not changed.
when D does not exist and G exists, D is generated from race names
when D does not exist and G does not exist, D is left empty.

note that saving a game will take you from a state with no U to one with a U, so
this fails after a save-reload of ___ -> _U_ -> DU_ . This is effectively what the original bug was doing.

....basically, We need a third option for G. say, Generate_Description="done", call it g.
that gives us some new states:

Code: Select all

DUG -> do nothing to U & D.  set G to done
DU_ -> do nothing to U & D.  set G to done
D_G -> generate U. set G to done
_UG -> generate D from race names. set G to done
D__ -> generate U. set G to done
_U_ -> generate D from U. set G to done
__G -> generate U.  Generate D from race names.  set G to done
___ -> generate U. leave D blank.  set G to done
DUg -> do nothing to U&D. set G to done
D_g -> generate U. set G to done
_Ug -> do nothing. set G to done.
__g -> generate U.  leave D empty. set G to done
I think that gives us all the desired behaviour.
- U always exists.
- in cases where U exists but D does not, and G does not, D is generated from U. (scenario designers shortcut).
- in cases where the race name does not generate any name, the value of generate_description is set to done, so the lack of name will be preserved.
- by setting G to done in all cases, if the user decides to erase the name, it will not cause the name to be regenerated.

Please review the above cases and make sure that I am correct and have addressed all the concerns.

User avatar
zookeeper
WML Wizard
Posts: 9739
Joined: September 11th, 2004, 10:40 pm
Location: Finland

Post by zookeeper » May 23rd, 2007, 10:16 am

Darth Fool wrote:Ok, here is a matrix of how I think that it might work. In this case, "D" means that the Description exists (ie !=""), "U" means that the Underlying Description Exists, and "G" means that Generate_description exists and = "yes" or equivalent. "_" means that the corresponding element does not exist.

Code: Select all

DUG -> do nothing
DU_ -> do nothing
D_G -> generate U
_UG -> generate D from race names
D__ -> generate U
_U_ -> generate D from U
__G -> generate U.  Generate D from race names
___ -> generate U. leave D blank.
Now, let's make sure that this works:
when DU exist it doesn't matter what G is.
when U does not exist, it is generated.
when D exists it is not changed.
when D does not exist and G exists, D is generated from race names
when D does not exist and G does not exist, D is left empty.
I think that's about right, with one exception: IMHO "_U_ -> generate D from U" should rather be "do nothing". Not important though as such, but might help with this:
Darth Fool wrote:note that saving a game will take you from a state with no U to one with a U, so
this fails after a save-reload of ___ -> _U_ -> DU_ . This is effectively what the original bug was doing.
Wouldn't my above suggestion of having "_U_ -> do nothing" solve this? If yes, then I think we should do that.
Darth Fool wrote:....basically, We need a third option for G. say, Generate_Description="done", call it g.
that gives us some new states:

Code: Select all

DUG -> do nothing to U & D.  set G to done
DU_ -> do nothing to U & D.  set G to done
D_G -> generate U. set G to done
_UG -> generate D from race names. set G to done
D__ -> generate U. set G to done
_U_ -> generate D from U. set G to done
__G -> generate U.  Generate D from race names.  set G to done
___ -> generate U. leave D blank.  set G to done
DUg -> do nothing to U&D. set G to done
D_g -> generate U. set G to done
_Ug -> do nothing. set G to done.
__g -> generate U.  leave D empty. set G to done
I think that gives us all the desired behaviour.
- U always exists.
- in cases where U exists but D does not, and G does not, D is generated from U. (scenario designers shortcut).
- in cases where the race name does not generate any name, the value of generate_description is set to done, so the lack of name will be preserved.
- by setting G to done in all cases, if the user decides to erase the name, it will not cause the name to be regenerated.
Are the function that recreates a unit from savefile WML and the function that spawns a new scenario-generated unit via [unit] really the same? If [unit] in [event]s, [side] etc. is specially recognized, couldn't you somehow figure out the descriptions stuff before passing control to the other functions, meaning that descriptions stuff wouldn't be auto-figured-out on saveloading, but only when the game actually encounters the [unit] and spawns it? If not, then ok, you know the code and I don't after all, but I can't help but wonder about that. In any case, if the above tweak I commented on solves the situation, then this would be unnecessary in any case.

EDIT: Except that IMHO no autogeneration of any kind should ever happen after the initial spawning of the unit (like on save/load). Someone might intentionally wipe the user_description of some unit, and it'd be a bug if the game then generated some racial name to replace it on the next saveload.

Darth Fool
Retired Developer
Posts: 2633
Joined: March 22nd, 2004, 11:22 pm
Location: An Earl's Roadstead

Post by Darth Fool » May 23rd, 2007, 2:34 pm

zookeeper wrote:
Darth Fool wrote:Ok, here is a matrix of how I think that it might work. In this case, "D" means that the Description exists (ie !=""), "U" means that the Underlying Description Exists, and "G" means that Generate_description exists and = "yes" or equivalent. "_" means that the corresponding element does not exist.

Code: Select all

DUG -> do nothing
DU_ -> do nothing
D_G -> generate U
_UG -> generate D from race names
D__ -> generate U
_U_ -> generate D from U
__G -> generate U.  Generate D from race names
___ -> generate U. leave D blank.
Now, let's make sure that this works:
when DU exist it doesn't matter what G is.
when U does not exist, it is generated.
when D exists it is not changed.
when D does not exist and G exists, D is generated from race names
when D does not exist and G does not exist, D is left empty.
I think that's about right, with one exception: IMHO "_U_ -> generate D from U" should rather be "do nothing". Not important though as such, but might help with this:
Darth Fool wrote:note that saving a game will take you from a state with no U to one with a U, so
this fails after a save-reload of ___ -> _U_ -> DU_ . This is effectively what the original bug was doing.
Wouldn't my above suggestion of having "_U_ -> do nothing" solve this? If yes, then I think we should do that.
This is essentially back to your original proposal in how to solve it. It would mean that if someone does not have a description tag in their scenario, their hero will be nameless. I am not really opposed to that solution, but I did think that it requires more input from scenario designers who will be affected by it. Granted, hopefully they already have description tags since they should be translatable.

Are the function that recreates a unit from savefile WML and the function that spawns a new scenario-generated unit via [unit] really the same?
yes. Units are generated from a config (essentially a portion of the wml tree). It does not know where that config came from.
If [unit] in [event]s, [side] etc. is specially recognized, couldn't you somehow figure out the descriptions stuff before passing control to the other functions, meaning that descriptions stuff wouldn't be auto-figured-out on saveloading, but only when the game actually encounters the [unit] and spawns it? If not, then ok, you know the code and I don't after all, but I can't help but wonder about that. In any case, if the above tweak I commented on solves the situation, then this would be unnecessary in any case.

EDIT: Except that IMHO no autogeneration of any kind should ever happen after the initial spawning of the unit (like on save/load). Someone might intentionally wipe the user_description of some unit, and it'd be a bug if the game then generated some racial name to replace it on the next saveload.
So, with a general lack of comments from scenario/campaign/WML devs, I am inclined at this time to use zookeeper's solution. I have updated it below. It will force a change on scenario designers to explicitly name their units, which will be good for the translators and simplify the C++ code. It will mean that the underlying description used by WML will be completely decoupled from the description that the player sees.

I have made it more explicit what will happen to G, which is to say that it will always be set to _. After initial name generation or after a save, a unit will always either be in a state of DU_ or _U_, and so nothing will be done with future save/loads. A user can safely rename the unit to "" thus moving it from DU_ to _U_, and not have this cause the name to be regenerated.

Code: Select all

DUG -> set G to _
DU_ -> do nothing
D_G -> generate U.  set G to _
_UG -> generate D from race names.  set G to _
D__ -> generate U
_U_ -> do nothing  **** change from current operation ****
__G -> generate U.  Generate D from race names. set G to _
___ -> generate U. leave D blank.

User avatar
zookeeper
WML Wizard
Posts: 9739
Joined: September 11th, 2004, 10:40 pm
Location: Finland

Post by zookeeper » May 23rd, 2007, 3:01 pm

Darth Fool wrote:This is essentially back to your original proposal in how to solve it. It would mean that if someone does not have a description tag in their scenario, their hero will be nameless. I am not really opposed to that solution, but I did think that it requires more input from scenario designers who will be affected by it. Granted, hopefully they already have description tags since they should be translatable.
If someone could run a search to find any instances of [unit][/unit] tags which have a description= but no user_description= or generate_description=yes in the mainline campaigns, that would probably give a pretty good idea of how much content would be affected by it. However, it's IMO quite clearly the proper convention to use both of those keys, so I wouldn't worry about breaking a few names in some UMC. Not when I can just post a note after the change telling people to do the appropriate changes, if necessary, in their UMC for/after the next release.
Darth Fool wrote:So, with a general lack of comments from scenario/campaign/WML devs, I am inclined at this time to use zookeeper's solution. I have updated it below. It will force a change on scenario designers to explicitly name their units, which will be good for the translators and simplify the C++ code. It will mean that the underlying description used by WML will be completely decoupled from the description that the player sees.

I have made it more explicit what will happen to G, which is to say that it will always be set to _. After initial name generation or after a save, a unit will always either be in a state of DU_ or _U_, and so nothing will be done with future save/loads. A user can safely rename the unit to "" thus moving it from DU_ to _U_, and not have this cause the name to be regenerated.

Code: Select all

DUG -> set G to _
DU_ -> do nothing
D_G -> generate U.  set G to _
_UG -> generate D from race names.  set G to _
D__ -> generate U
_U_ -> do nothing  **** change from current operation ****
__G -> generate U.  Generate D from race names. set G to _
___ -> generate U. leave D blank.
Cool. I'll be looking forward to that. :)

Darth Fool
Retired Developer
Posts: 2633
Joined: March 22nd, 2004, 11:22 pm
Location: An Earl's Roadstead

Post by Darth Fool » June 7th, 2007, 11:49 am

Ok, it looks like my response got blown away with the forum reload. Basically, I have implemented the change so that user_description will no longer be replaced by description if it is empty. This means that campaign developers may need to add a user_description tag to units that they use. The description tag is now used exclusively for WML identification of the unit.

Post Reply