AnssiR66 / AlanStdLib

The Standard Library for ALAN Interactive Fiction Language
Other
5 stars 2 forks source link

We Need Clear Clothing Guidelines #64

Closed tajmone closed 5 years ago

tajmone commented 5 years ago

I keep going through all the various issues dealing with the clothing problems (#52, #57, #58, #60, #61) and the more I look into them the more the situation seems entangled — in Italian we'd say that this is "a problem without head or tail", meaning it's difficult to pin down the root of the problem.

It's my opninion that before working on any isolate issue we need to get a better picture of the way the library currently handles clothing and the way it should ultimately handle clothing. Clearly, some of the newly discovered problems weren't accounted for in the original design (eg. transferall of worn items), so chances are that in order to solve all these issues a new formal definition of how clothing are dealt with might be required.

The newly discovered bug relating to clothing Events cross-pathing with Extract introduces new challenges which force us to reconsider the whole approach to worn clothing items, especially so if we want to prevent transferral of worn items.

Much will depend also on how we chose to implement handling of worn items:

As these questions show, before getting into code solutions we really need to think about the whole logic of clothing, and how strictly or loosely it should be implemented.

Clothing logics vs logistics

Some of the current implementation details seem to have an everyday-logic motivation behind them, for example the whole idea that clothes should be donned/removed in layered order, or that undressing is prevented by default (assumingly, for decency considerations).

But this logic seems either broken or out of order in some places:

The balance between realism, optimal code, and common sense rules is a difficult one, and maybe we should consider simplifying matters here to a more code-oriented approach, leaving other considerations to end authors.

As for the various issues that came to surface regarding the clothing class and its handling, it's quite clear that you can't try and fix any single one of them without affecting all the others.

Is worn really needed?

For example, due to the problems and limitations of Extract and its effects on library code that moves clothing in and out of worn, we might question the need of having a worn entity at all. If I've understood correctly, worn was introduced to simplify separation between what the player is carrying and what he's wearing, especially when taking 'inventory' where it allows presenting them in separate lists.

As @thoni56 as pointed out, relying on sets to handle this is much safer (and, as a matter of fact, we already have a wearing set on Hero, as well as on all NPCs). The question is if we can handle all clothing operations relying only on wearing, and thus avoid moving clothing back and forth from the Hero to worn.

I think that getting rid of worn would simplify fixing all these issues for it would allow implementing the same safeguards on items worn by the player and NPCs (ie. having all checks on actors only).

tajmone commented 5 years ago

I've created a new test development branch (try-dispose-worn) where I'm trying to circumvent using the worn entity to handle clothing worn by the Hero:

https://github.com/AnssiR66/AlanStdLib/tree/try-dispose-worn

The DEV_NOTES.md file documents in detail the current status of the library regarding worn and lists all its occurences in the StdLib code, as well as sketching out a plan on how to proceed.

We could use this branch to work on fixing all the problems before merging any fixes into master (we must be sure that every aspect of clothing fits together).

tajmone commented 5 years ago

Progress Status

In the development branch I've already managed to properly handle clothing initialization without using worn. A new test log is available to track the new system progress:

With this new approach, authors wishing to dress actors will just need to add the clothing items IN the actor (Hero/NPC) and declare it IS donned, the library will do the rest at initialization time.

Inventory With Carried/Worn

Now taking inventory produces separate lists for carried and worn items, just like before. It doesn't rely on LIST, but uses custom loops that check for clothing and donned (doesn't use wearing either):

> inventory
You are empty-handed. You are wearing your socks, your boxers, your 
undershirt, your sneakers and your khakis.
...
> take wallet
Taken.

> inventory
You're carrying your wallet. You are wearing your socks, your boxers, your 
undershirt, your sneakers and your khakis.
...
> take basket
Taken.

> inventory
You're carrying a basket and your wallet. You are wearing your socks, your 
boxers, your undershirt, your sneakers and your khakis.

I'm soon going to implement the same thing on 'examine actor'.

The more I look into it, the more I'm convinced that we ca do without the worn entity by using filters and aggregators. I'm also starting to think that we might not need wearing either.

tajmone commented 5 years ago

Proposal: Moving donned on object class

I think that for the sake of the various checks in the library, having the donned attribute on every object allow a broader margin of action. My reasoning is this:

What you think Anssi?

I'd personally prefer to add a few verbose/stricter loops, filters and aggregates in some key library places, and enjoy simpler boolean checks in the rest of the library verbs and code.

AnssiR66 commented 5 years ago

@tajmone I think it's great if the various clothing attributes can be reduced to a minimum, so I think that's the direction we should go towards. I will need to take a closer look at the tests you have conjured up, but I definitely show you green light for this. Can you also explain in short the principle about how you have been able to keep only 'donned' and scrap the other attributes? So I can add that explanation to the library manual.

tajmone commented 5 years ago

Examine Actors Lists Carried and Worn Separately

Now examining an actor also produces two separate lists for carried and worn items, just like for Hero inventory. The system used is the same as for the inventory/i verb, so it relies only on donned.

tajmone commented 5 years ago

Can you also explain in short the principle about how you have been able to keep only donned and scrap the other attributes?

Well, I have kept the wearing set in the code (the tweaked worn_clothing_check Event does set it correctly), and using it, but I'm sure we could do without it. Look at the inventory and examine actor listings:

UPDATE — Now both 'inventoyy' and 'examine actor' don't rely on wearing to produce separate lists of carried and worn items, they just use donned!

VERB i
  CHECK my_game CAN i
    ELSE SAY restricted_response OF my_game.

  DOES
-- >>> devworn >>> tweaked: new method for listing separately carried and worn.
    -- ------------------
    -- List carried items
    -- ------------------
    SET my_game:temp_cnt TO COUNT IsA object, DIRECTLY IN Hero, NOT IN wearing of Hero.
    IF  my_game:temp_cnt = 0
      THEN "You are empty-handed."
    ELSE
      "You're carrying"
      FOR EACH carried_item ISA object, DIRECTLY IN Hero, NOT IN wearing of Hero
        DO
          SAY AN carried_item.
          DECREASE my_game:temp_cnt.
          DEPENDING ON my_game:temp_cnt
            = 1 THEN "and"
            = 0 THEN "."
            ELSE ","
          End Depend.

      END FOR.
    END IF.
    -- -----------------
    -- List worn clothes
    -- -----------------
    SET my_game:temp_cnt TO COUNT IsA CLOTHING, DIRECTLY IN Hero, IS donned.
    IF  my_game:temp_cnt = 0
      THEN SAY my_game:hero_worn_else.  --> "You are not wearing anything."
    ELSE
      SAY my_game:hero_worn_header.     --> "You are wearing"
      FOR EACH worn_item IsA CLOTHING, DIRECTLY IN Hero, IS donned
        DO
          SAY AN worn_item.
          DECREASE my_game:temp_cnt.
          DEPENDING ON my_game:temp_cnt
            = 1 THEN "and"
            = 0 THEN "."
            ELSE ","
          End Depend.
      END FOR.
    END IF.

The same code is used in examine on actors (DOES AFTER), just changed Hero to THIS.

The point is that now Hero is just like any other NPC regarding wearing clothes, since there is no longer the worn entity holding his clothes.

For the sake of the above code, for listing separately carried and worn, you could just check if an items is donned or not to decide in which list it belongs — after all, the assumption is that if it's donned it therefore must be a clothing, if not then it's just a carried item like any other. So it would be even simpler to just use donned — but then, we must be sure that any handling of clothes sets/unsets donned as required.

I don't see why we need every actor to store list of the clothes he's wearing. It can only be wearing clothes which are INSIDE him anyhow, so it's easier to loop through them and check if they are donned. This is safer, because if a clothing items has left an actor then the next loop will simply skip it, while a non-updated set will deceive the code.

I also think that the wear and remove verbs could just do with using filters and aggregates — and if the need be, they could use a temporary set attribute (on my_game), instead of enforcing one on every actor. The important thing is avoid moving worn items (and trigger Extract checks).

But of course, I haven't yet got to that (but I did think a lot about this lately). If I manage to tweak wear without using wearing, I'll try and do without it everywhere else, until I get to a point where the code works even if I comment it out from the clothing class.

UPDATE — Now wear/remove work fine without relyin on wearing!

tajmone commented 5 years ago

Fixed Wear/Remove

Now wear and remove verbs are working like before, but they only use donned do carry out all the calculations (don't use the wearing set either).

New test log for wear/remove verbs confirm that they working as expected:

After wearing/removing, the tests "debugs" (custom DBG verb) the clothing items to see their updated status.

This confirms that there is no need for the wearing set (at least, I can't think of any right now).

tajmone commented 5 years ago

Moving Around Worn Items?

OK, so far so good: with the use of just donned I've managed to achieve:

But of course, dropping or moving around worn items still behaves like before (ie. the item is still donned and in wearing of original actor).

We now need to sit down and think about the rules governing worn items mentioned at the beginning of this issue — should we prevent it? allow it only for top-worn items?

Depending on how we chose to go about it, different solutions could be devised.

If we decide to allow it (with silent or verbose implicit remove/wear) we could just cluster together similar-syntexed verbs on clothing and add a DOES BEFORE/DOES AFTER that tweaks the donned status of the item being moved, depending if it's going to another actor of not.

Here we should find a good balance between what is cool to have in the library and keeping it easy for authors to create new verbs that don't break clothing up. It's reasonable to expect that when authors create new verbs that might affect worn items they should also take them into account and cater for them, but this shouldn't be a headacke for them, and it should straightforward.

Of course, there are many possible scenarios to consider here.

AnssiR66 commented 5 years ago

While I think it's a very good idea to limit the attributes needed with clothing (worn, wearing, donned) to one only, I would at the same time have some reservation about dropping the LIST approach. Something like my_game:tmp_cnt should be used only internally in the library, right? Because, looking at that part of the code, it starts to remain me of something like TADS. And we are talking here about something as basic as listing the possessions of the hero /an npc. This would not serve the audience that is attracted to Alan for the simplicity it offers,

Now, when the author would need to tweak that listing, how would they go about it with this proposed approach? I mean, to alter between something like

i You are carrying: a match a book and a lantern

and

i You are carrying a match, a book and a lantern.

etc.

(Now, that can be changed by editing the MESSAGES CONTAINS, CONTAINS_COMMA etc.)

Or if the author wants to have the clothing items listed before the carried ones? Or if the author just needs to list the worn items, or just the carried items, in any specific situation? All of that would necessitate tweaking the DOES part of the inventory verb, or some other verbs, which means that either make their own DOES ONLY, and then have to use the attributes carried_item, temp_cnt, etc.; or then open the library file (lib_verbs.i) and make the changes there, which is what the present approach of the library tries to avoid as much as possible - as much of the coding as possible should be done in the author's own code file. The above tweakings would be much more cumbersome than "LIST hero. LIST worn." (or just one of them):

EXIT south TO snowy_garden DOES "You take a look at yourself." LIST worn. "You have enough on you to go out into the freezing air."

or

VERB sell DOES ONLY LIST hero. "Which of that do you wish to sell?" END VERB. etc.

Also, listing of objects uses LIST anyway: LIST wardrobe. LIST treasure_chest, etc. It would be congruent to use LIST also with actors. My point, in short, would be: the DOES part of the inventory verb, as you have presented it above, now does manually what LIST would do automatically, and I would personally prefer LISTing. Would that be in any way possible with the one attribute approach?

Here is an approach that would have 'worn' even as a temporary container only: For example. VERB i ... DOES FOR EACH cl ISA CLOTHING, IS donned, IN hero DO LOCATE cl IN worn. -- this would apply for npc's as well, at 'x actor' END FOR. LIST hero. LIST worn. EMPTY worn IN hero. --- and: EMPTY worn IN actor, at 'x actor' END VERB i.

(Here, 'worn' would be a temporary container that only contains something at 'i' or 'x actor' I didn't test this, but that should work...)

Another thing would be to contemplate that if we just have 'donned', is that the right word to use? 'Donned' is probably a slightly more infrequent word than 'worn' which would be more intuitive and straightforward as an attribute, (if we don't have any 'worn' container besides),

About why worn, wearing and donned were used side-by-side in the first place:

THE jacket ISA CLOTHING IN worn

and

THE hero ISA ACTOR IS wearing {jacket}. END THE.

work side by side and do the same thing, and the library would take care that what is in the wearing set of hero would be in 'worn', and vice versa.. 'donned' was needed for the library to check if a piece of clothing was in general worn by anyone, either the hero or an actor.

Later, Anssi

AnssiR66 commented 5 years ago

Also, if the author wishes to group inventory items further, we need to keep a convenient way for it: For example:

i You are carrying the following tools: a, b, c,... the following valuables: d, e, f... the following keys: g,h, ... and you are wearing i, j, k,...

(Also without labeling any item groups, like here, but just listing the inventory items in a certain order would be easier with LIST.)

For these reasons, the approach presented above would be difficult for the author to use and to edit, compared to LISTing. I wouldn't also shun the 'worn' container as something that needs to necessarily be got rid of....

tajmone commented 5 years ago

I understand your concerns regarding listing carried and worn items. Bare in mind that right now I was trying to implement the suggestion of @thoni56 that we should at all cost avoid moving clothing from within the code (in view of the problems with extract), so I wanted to explore this path.

As for end users being able to customize how hero/NPC inventory is listed here are some considerations:

  1. First of all, the user is still free to use LIST in other places of the code, which means he/she can override inventory/i verb at any time (and, in the case of your tools/valuables/etc. example he'd surely need to do that anyway).
  2. A simple way to allow customizing the lists would be to expose some library string attributes for the employed separators, just like Alan does with MESSAGES:

    attr.name default custom
    inv_comma "," "$n"
    inv_and "and" "$n"
    inv_end "." ""

    So it's possible to find a way to customize how these lists are presented, and it would only require exposing a few settings. From the author side, it wouldn't be much different from what he'd be doing with MESSAGES anyhow.

  3. We could also think of defining a single Event and use it as it was a function, so we could reuse the same code for listing inventory, examine NPC, and anywhere else it's needed, and authors could use that Event for their verbs too (we'd need to test this first).
  4. I had thought of tweaking lib_messages.i to hande separate lists of carried/worn, but I couldn't think of any simple way of doing it — in order to show all carried items you'd have to tell messages to ignore worn items, but since LIST produces a single iteration then how could we list also worn items?

    The only solution that comes to my mind here is to use a custom attribute (eg list_carried) to control what LIST actor should output (either carried or worn) and invoke LIST twice, with different values of list_carried. Something like:

    "You're carrying"
    MAKE my_game list_carried. LIST Hero.
    
    "You're wearing"
    MAKE my_game NOT list_carried. LIST Hero.

    Where in lib_messages.i the various CONTAINS_COMMA, etc., would use list_carried to decide whether to print carried/discard worn, and viceversa.

As mentioned, more complex listing with subcategories would require anyhow the author to override the inventory verb with custom code, but in such cases we're speaking of expert authors anyhow.

I wouldn't also shun the 'worn' container as something that needs to necessarily be got rid of....

My intention in this branch is to try and rewrite most of the clothing logic with the simplest approach possibile, following Thomas advice. The idea is to start from scratch and only introduce elements which are strictly necessary — which also means that if I encounter the need to use a temporary worn container I'll just implement it. Since I haven't written the original code, I need to approach it from scratch to get a feel of the problem and the possible solutions.

I still think that temporary moving clothes for the sake of calculations and output optimization should be avoided. We need to now implement safeguards regarding attempts to move around worn items, and these will probably require the library intercepting any worn items that changes/leaves a container/place. The previous code didn't account for that (and the side effects went by unnoticed), but the next system should.

Personally, right now I'd focus on establishing some clothing rules and attempt to implement them in a strict and safe manner, giving priority to the idea that authors should not have to face problems when they create verbs that could handle worn items — the latter should have a higher priority over ease of customization of inventory (which can ve overriden anyhow). That said, I'm also sure that we'll be able to find solutions to expose customization of inventory in some simple manner.

tajmone commented 5 years ago

On Renaming donned....

Another thing would be to contemplate that if we just have 'donned', is that the right word to use?

No, worn is much better — and I already had thought of that. But since right now I'm not 100% sure we'll be able to do without worn and wearing, I'm avoiding to switch names (also, the worn entity is reference in many places still).

Another consideration on this is that by renaming donned to worn (or anything else) we'll be introducing a compatibility breaking change, which would require authors to readpat all their sources (also applies to all our test adventures). Sure it can be done (and probably should), but I wanted confirmation on this from you, due to the breaking change nature.

tajmone commented 5 years ago

On Renaming donned (2) ....

No, worn is much better

Actually, on second thought, donned is less ambiguos, for worn could also be mistaken for the adjective "worn out/damaged" (which would apply to clothing too):

Google Dictionary result for worn

verb

  1. past participle of wear.

adjective

  1. damaged and shabby as a result of much use.
  2. very tired.

But obviously, worn has a stronger association with the wear verb.

AnssiR66 commented 5 years ago

OK, please go ahead and try out what you can come up with, with regard to simplified clothing coding, and let me know :) ! Meanwhile, I made up a new clothing branch in the repository but please ignore it so far, I'm just experimenting things there... Yes, I think 'worn' has a stronger association with the wear verb so it might be not a problem to use it for our purposes..

tajmone commented 5 years ago

Meanwhile, I made up a new clothing branch in the repository but please ignore it so far, I'm just experimenting things there...

Good to know, I can always peek at it for inspiration and questions. Thanks!

tajmone commented 5 years ago

Wear Verb: Report Only Blocking Items

Now the wear verb tracks the worn clothes preventing the action, and in the failure message mentions every item which the player should remove in order to wear the new one — whereas before the verb would list every worn item instead:

> undress
You remove all the items you are wearing and drop the on the floor.

> wear red shirt
You pick up the red shirt and put it on.

> wear coat
You pick up the wool coat and put it on.

> wear black shirt
In order to wear the black shirt you should first remove the red shirt and 
the wool coat.

> wear undershirt
You pick up your undershirt. In order to wear your undershirt you should
first remove the red shirt and the wool coat.

Special handling of coat-like clothes is already implemented, but other cases still need to be covered (skirts, skirts + teddy, covearlls/dress). Just need to tweak a bit the code handling botcover values, and then thoroughly test it.

Now there's a new test targetting failed wear responses:

Once the wear verb is dealt with, including all the special exceptions, I'll only need to do the same on remove.

AnssiR66 commented 5 years ago

I have now tweaked the clothing code (through some own methods of mine) so that everything should work, there is no "being worn" message anywhere and both the hero and the npcs are described as carrying and wearing items, separately. Undo does crash the interpreter some time into a test game, though (after giving and taking clothing items). If you want, you can take a look at the clothing_solution2 branch and the library files there, and test them with a small game. But note this approach uses the worn and npc_worn containers, etc, and is not along the lines of what you discussed above. We can experiment with different things and come to a solution. In my approach, I

Please note that I modified the header/else of all actors so that if the actor doesn't carry anything, nothing is printed. (Earlier it was "(the actor) is empty-handed/ carrying nothing." but I think this is unnecessary to have. So, instead of

You notice nothing special about the actor. The actor is empty-handed. The actor is wearing a brown shirt.

we would get just

You notice nothing special about the actor. The actor is wearing a brown shirt.

which is much better; would you agree?

tajmone commented 5 years ago

I have now tweaked the clothing code (through some own methods of mine) so that everything should work [...] If you want, you can take a look at the clothing_solution2 branch and the library files there, and test them with a small game.

Excellent idea, trying different approaches is the best solution, and ultimately we can weigh the pros and cons of each one and even cross-exchange code if needed. I'll clone it locally so I can test it and study it in depth.

Please note that I modified the header/else of all actors so that if the actor doesn't carry anything, nothing is printed.

I agree with this, as I had already noted in the tests. Stressing that an NPC isn't wearing anything would be annoying in adventures that don't employ clothing at all — in such adventures the player is left to imagine that actors are not just walking around naked, but the "is not wearing anything" tends to emphasise that they are naked (just a polite way of saying so).

The Hero is different in this respect, for the player might want to know about what he/she's wearing. Although I think it would be a good idea to ultimately expose some library settings that could suppress such messages in games that don't employ clothing (laking optional modularity of clothing). Something like my_game:use_clothing, which if set to NOT would suppress "not wearing anything" for both Hero and NPC.

I think there are quite a few areas of the library that could benefit from such boolean options — e.g. the default help messages says that no help is available in the current game, forcing authors to tweak the library to change that, whereas a boolean setting (my_game:use_help) would allow to change that in "no help currently available", or the like.

You notice nothing special about the actor. The actor is wearing a brown shirt.

which is much better; would you agree?

Yes, I don't like lengthy default messages, because they tend to put in the background author descriptions. If nothing is mentioned it's obvious the NPC is not carrying anything, just like with clothes.

AnssiR66 commented 5 years ago

Now the wear verb tracks the worn clothes preventing the action, and in the failure message mentions every item which the player should remove in order to wear the new one — whereas before the verb would list every worn item instead

That's absolutely great. Looking forward to see the rest (the 'remove' verb etc). I think it's going to become a very refined and versatile system when we get it done.

tajmone commented 5 years ago

Clothing Table and Exceptions Are Not Viable

Beside the already mentioned problem of handling coveralls like skirts, thus allowing puttin-on lower body clothes when wearing a boilersuit, there are more issues with the clothing table.

For example, why pantyhose have a greater value (8) then teddy (4)? it should be the other way round.

As mentioned somewere else, we need to rethink this fixed-system and replace it with a free-form layered system where authors can decide how to employ layers based on their needs — which means we shouldn't enforce any special cases handling for skirts, etc. We should either just implement layered wearing/removing regardless of items, or add some user customizable attributes that would allow making some clothing items non-blocking for the layers below.

I've also studied the values system that doubles the value at each layer, but this might not be strictly required either. It seems that the remove verbs requires this because it uses /2 as a quick way to check if an item can be removed. But the whole system could be made to work with layers uses any numbers (1, 2, 3, ...) instead of (2, 4, 8, ...) which would be simpler to handle for end users.

We could design a system based on bit-settings and flags, and come up with some ways to implement bitwise like operations in Alan, even though the language doesn't provide bit-operators.

Whaterver the approach, specs and rules should come first, then there's always a way to find solutions to implement them.

If we don't stop here and now and layout a formal specification of how the new clothing system is going to be enforced, we risk running in circles and keep rewriting over and over the same code.

The clothing table is clearly not working (some items simply don't make sense and don't behave as expected). And it's also very limiting for end users. Since the StdLib imposes the clothing system on authors, then it should offer a flexible system IMO.

Honestly, there is something wrong in the whole design of the clothing system — whether it's because it was designed for Alan 2 and then adapted, or because in time the StdLib grew beyond the limits of the clothing system, or just because it wasn't tested thoroughly enough. Whatever the cause, the best solution is to rethink it all and, instead of keep patching it, implement/reimplement whatever is neeeded for a new and better system.

Do you agree?

tajmone commented 5 years ago

Remove Verb Now Reports Only Blocking Items

Now the remove verb tracks the worn clothes preventing the action, and in the failure message mentions every item which the player should remove in order to remove the desired item.

Special cases like coats and skirt-like are also handled.

Thorough testing required!

AnssiR66 commented 5 years ago

The clothing table is clearly not working (some items simply don't make sense and don't behave as expected). And it's also very limiting for end users. Since the StdLib imposes the clothing system on authors, then it should offer a flexible system IMO.

The clothing table is there to offer an idea about how things relate to each other. If there are some items that don't make sense, we can fix their numerical attributes. But you mention that the system is not flexible - in what ways not? The author is free to assign any numerical attributes (2,4,...) to any clothing, and doesn't need to adhere to the table which, as it says, only gives a rough idea. This should be mentioned in the library manual more clearly. I don't think it's fruitful for us to ponder what a suitable definite attribute for a coveralls or something else is, as different authors have different ideas about how the pieces of clothing they implement in their games relate to each other, and if something can go over or under something else, etc. We don't have to make an exact world model but offer a framework that can be adjusted and edited. Wouldn't strict attributes and our own fixed ideas about how clothing items can be used bring it towards more inflexibility instead?

Moreover, the clothing items can at present be used wholly without any numerical attributes if wished, this just makes it possible to wear anything at anytime, without a check on layers. So, I fail to see how the way clothing works now is inflexible? The layering is wholly voluntary, so it is not imposed on authors by the library. True, this is not emphasized in the manual at present.

Honestly, there is something wrong in the whole design of the clothing system — whether it's because it was designed for Alan 2 and then adapted, or because in time the StdLib grew beyond the limits of the clothing system, or just because it wasn't tested thoroughly enough. Whatever the cause, the best solution is to rethink it all and, instead of keep patching it, implement/reimplement whatever is neeeded for a new and better system.

How is the library working beyond the limits of the clothing system? And what is the thing that is so wrong with that system? What is the improvement we could achieve by rethinking it again? Of course, there are the errors in it that were revealed by your thorough testing, but those shortcomings were something I managed to correct easily already (in my clothing branch in the repository). At least I can see that your idea of 1,2,3,4,5... instead of 2,4,8... is good and might be worth pursuing, so that is one change we could make.

Also another idea: what do you think.. would it be a good idea if we preserve only the very basic clothing principles in the library and offer in a separate extension the layered clothing, with all the finesses and possibilities it can offer? It is one alternative, and you could of course have all the credit for it, if you wish to rethink it "from scratch"? We can of course have it included in the library, too, but as it is one class only, we shouldn't make it excessively complex to use and to sacrifice the overall ease of use of other common features, like the general listing of the hero and the npcs (when the author wishes to override the defaults). This might be also a good question to ask at the Yahoo group, to get any opinions, so that it's not just us... the traffic there might be quiet (I remember an earlier question didn't produce much reaction) but we could try anyway, to get a general idea?

AnssiR66 commented 5 years ago

Now the remove verb tracks the worn clothes preventing the action, and in the failure message mentions every item which the player should remove in order to remove the desired item.

Special cases like coats and skirt-like are also handled.

Thorough testing required!

Great, I will take a look!

tajmone commented 5 years ago

Help Testing Failed Wear/Remove Reports

Anssi, I've completed handling the reports for when a wear/remove action fails. Now both verbs should be listing only the items which are preventing the actions. Hopefully, this is a good improvement for both these verbs, which could be preserved in whichever solution end up being adopted for the clothing problems — very minor adaptments might be required, e.g. in case the worn entity is kept.

I've done my best to try the special clothing exceptions like coats, skirts, etc. Since the code that tracks blocking items is semi-independent from the actual code of the calculations, I'd like to make sure that special clothing items are being tracked correctly. From my understanding of how clothes exceptions work, this is what I've implemented in the exceptions handling:

Please, if you could do some testing to check that I haven't left out or badly implemented any special clothing handling in failed messages, I'd be grateful to you. The ega.alan adventure has been updated to provide more clothing items to tests with, so it should cover all common clothes types.

I'll answer to your post on the Clothing Table shortly. (it's going to take some time to prepare a detailed reply.)

tajmone commented 5 years ago

The Clothing Table

The clothing table is there to offer an idea about how things relate to each other. If there are some items that don't make sense, we can fix their numerical attributes. But you mention that the system is not flexible - in what ways not?

I don't agree on this, because of the special exceptions for skirt, the reality is that the Clothing Tables imposes on authors a specific system of layers associated to clothing items, and trying to adapt them to other uses is quite complicated (even for someone who has studies the sources).

The author is free to assign any numerical attributes (2,4,...) to any clothing, and doesn't need to adhere to the table which, as it says, only gives a rough idea.

How could this possibly be so? Let's say in my adventure I want to use a simpler clothing systems (without dealing with underware, lingerie, etc., but only with uniforms, hats, coats, and other more exterior clothes). My so-called freedom is actually limited to 6 layers (2, 4, 8, 16, 32, 64) where some layers will always be treated specially:

It's quite obvious to me that end users won't have control over these rather bizzare special cases handling unless they edit the library code. (I say bizzare for, as I've pointed out in various places, this system simply doesn't add up, even when sticking to the Clothing Table).

I don't think it's fruitful for us to ponder what a suitable definite attribute for a coveralls or something else is, as different authors have different ideas about how the pieces of clothing they implement in their games relate to each other, and if something can go over or under something else, etc. We don't have to make an exact world model but offer a framework that can be adjusted and edited. Wouldn't strict attributes and our own fixed ideas about how clothing items can be used bring it towards more inflexibility instead?

Which is exactly what I've been saying for quite a while, and the very reasons why I think that whole the code that currently deals with skirts/coats/etc. should be erased, leaving only a straightforward system of layers that ensures wearing/removing occurs in the right order (when non-zero coverage values are used).

The current clothing system is exactly all you just mentioned it shouldn't be:

Maybe it was not intended to be so, but the special handling for skirts does make it so. Because, the skirt system accounts for layers below being freely accesible when wearing a skirt, which leads to the "teddy" special case, which somehow forces "pantyhose" to end up being worn over a teddy (which is strange). The point I'm trying to make is that all these special cases do ultimately impose mechanics which were designed to work mainly for women clothes and that ultimately limtit authors' freedom on how they can use these layers.

I think that here we're dealing with matters of opinion of what a good clothing system should do and not do. My opinion is that it has to offer an open ended model, which can be customized by end users.

Many adventures don't even require clothing — in such games, it's implied that all actors are not naked, and a quick description might depict them as being wearing a unifrom or clothes of other types, without actually implementing any clothes beside descriptions.

As for adventures that do implement clothing, many of them wouldn't go into such details as what's below the outward (underware, etc.), unless they are of the AIF genre (which is a niche IF genere, usually offering dedicated extensions/libraries to deal with clothing that include underware).

If you consider how the current library code accounts in detail for underware garnments and lingerie (3 layers are dedicate to lingerie, from layer 2 to 8), it's quite clear that there is an underlying model of how clothing should be handled (ie. a realistic approach that deals with outward clothes and what is below them).

I've started working on the StdLib translation 10 months ago, and have been working on it on an almost daily basis since then. The translation work as forced me to study and edit the whole source of the library, multiple times, so there aren't any unexplored corners. In the last three monthes I've been focusing on the clothing part of the library, which is still the main obstacle in finishing the translation work.

Even thuough I've worked so much on the library source, I've really struggled to get a grasp on how the clothing system works, and it took me over two months to work out how the coverage values really work (or are supposed to) — yet, I can't still work out how to implement some special clothing items (that are not in the Clothing Table) and expect them to work properly.

I admit that I'm not be the smartest guy on earth, but we should both agree that end users of the library are not required/expected to have studied the library sources or memorized them by heart. If I still find it hard to use, having worked so much on its sources, how is the average user going to find it easy?

Maybe it's just me, or the current lack of in-depth documentation and examples on how to use clothing; but having worked with different IF authoring systems, I am comfortable saying that in respect to clothing, the StdLib is neither intuitive to understand nor easy to learn or flexible.

Of course, these are my opinions — but for sure, they are not the opinions of someone who has tried playing with the library five minutes and impatiently given up at the first difficulty; on the contrary, I've really striven to try and finish translating the clothing part so that the Italian library would be ready to go.

I'd really love to ear more from other Alan users on the list — how they find the current clothing system to work for them, if it's easy to learn, use and adapt.

Also another idea: what do you think.. would it be a good idea if we preserve only the very basic clothing principles in the library and offer in a separate extension the layered clothing, with all the finesses and possibilities it can offer? It is one alternative, and you could of course have all the credit for it, if you wish to rethink it "from scratch"?

On this matter, I've asked other Italian IF authors what they think, and most of them seem to agree that dialogs, clothing and help should all be in separate modules which can be optionally included. I am of the same opinion. Dialogs are used more frequently in adventures than clothing (never seen an adventure where there is clothing but no dialogs), yet the library doesn't provide conversation nodes or quip-based dialogs — that is to say, that they both belong to the realm of "add-ons", rather than "standard".

Modularity is not so easy in Alan (not with over 170 verbs and verb-attributes, anyhow). So, if we can't make the clothing module something that can be simply excluded by not importing it, we could at least expose some library boolean settings to control wether layered clothing should be enabled or not. And definitely, we should take out the skirt/coat exceptions (users can implement them on subclasses).

Another solution could be to provide separate modules to implement advanced clothing (with different approaches) that could then be included optionally. If these modules work with subclasses of clothing (eg. layered_clothing) than they could just override the wear/remove verbs on the subclasses, and coexist with "base clothing".

But we should ask/poll the Alan list to learn what others think about clothing being included at all in the library (basic, layered or otherwise) or if they'd prefer to see it optional. If I remember correctly, Yahoo Groups offers a poll system too.

tajmone commented 5 years ago

New Clothing System in Italian Library

Ciao Anssi,

Today I've finally completed fixing all the issues on the Italian Library. I wanted to share with you a brief resume of how things worked out (I'll use English attributes names here, for the sake of simplicity; unfortunately the code uses Italian referents, so it won't be of much help here).

It was a quite huge work and I had to sit down and write some formal rules on how donned items whould be dealt with in the Library — these guidelines are also important for end users who need to override verbs or create new verbs for their adventures, so that they can interact with the library in an orderly manner.

During the development stage, I also realized that implicit take actions in many verbs interfered with donned clothing, so I had to set some formal rules for those too; eg. in verbs that by default they don't do carry out the action (like "throw obj at npc") I've removed implicit taking of the object.

Ultimately, I've got rid of the worn entity and the wearing set too, and used only the donned attribute, which I've moved on the thing class to allow end users to implment non-clothing wearables too (eg. a wearable device, like VR goggles, IR goggles, headphones, ecc.). In view of this extensibility, I've also ensured that any verb which dislocated an object always sets it to NOT donned.

Verbs that should not be carried out on worn items are now blocked via CHECKs implemented on those verbs on clothing class.

Non-Exponential Wearing Layers

With the new clothing system in the Italian Library, clothing layers are no longer exponential (2, 4, 8, ...) but author can use any numbers they like. I've also added a new zone for the face, to allow wearing masks, beards, glasses, etc., without using up the head values.

Custom-Definable Skirts and Coats

I've removed the hardcoded special cases for skirts and coats, and introduced two new (entirely optional) attributes to allow users to make any item a skir-like clothes and even handle special items like "bikinis". Here's how it works...

EVERY indumento IsA OBJECT     --> 'indumento' = 'clothings'

  IS indossabile. --> 'wearable'
  HAS genere 0.

  HAS strato_testa  0.   --> head
  HAS strato_viso   0.   --> face
  HAS strato_tronco 0.   --> chest/top
  HAS strato_gambe  0.   --> legs/bot
  HAS strato_piedi  0.   --> feet
  HAS strato_mani   0.   --> hands

  IS  blocca_gambe. NOT due_pezzi.  --> 'blocks_legs' & 'two_pieces'

The blocks_legs attribute on clothing (defaults to true) can be set to IS NOT blocks_legs on a skirt/coat. When the library tries to work out which donned items are preventing wearing/removing, it will discount from legs-checks items that are marked as not blocking the legs. But before discounting them, it will check that the item being worn has a topcover value = 0, to prevent the exception when dealing with items that are one piece covering legs and torso.

The new attribute two_pieces (defaults to false) allows implmenting clothing like bikinis, which although they are handled as a single item they consist of two pieces, but these are separately covering legs and torso. So the library also considers this attribute when checking a blocking item which IS NOT blocks_legs (skirt or coat), and if the item being worn IS two_pieces then it will not check it for topcover = 0.

This means that if you're wearing a skirt you can wear/remove underpants and pantihose, but not a one-piece full body costume or a teddy, but you can wear/remove a bikini because it's seen as a two-piece costume. It's use is quite simple (approximation, since in the Italian library Italian identifiers are used instead):

-- We arbitrarily assign body layers according to need:
--   * layer 1: direct skin contact, like underpants, bra, etc.
--   * layer 2: items over underware, like pantihose, t-shirts, etc.
--   * layer 3: skirts, trousers, shirts, etc.

The skirt IsA clothing in hero
  HAS botcover 3.
  IS NOT blocks_legs. --> Doesn't prevent wearing/removing leg-only items.
  IS donned.
End the.

The teddy IsA clothing
  HAS topcover 1.
  HAS botcover 1.
End the.

The bikini IsA clothing
  HAS topcover 1.
  HAS botcover 1.
  IS two_pieces. --> Should be treated as if a legs-only item in skirts checks!
End the.

The pantihose IsA clothing
  HAS botcover 2.
End the.

The above code will allow to correctly handle skirts. Of course, a bikini will be wearable with a skirt but will still be blocked by a t-shirt (in the topcover checks though).

Verbs wear/remove

The final code in the library for the wear/remove verbs is much simpler and shorter now:

      SET mia_AT:temp_indumenti TO {}.
      IF  THIS:strato_testa
        + THIS:strato_viso
        + THIS:strato_tronco
        + THIS:strato_gambe
        + THIS:strato_piedi
        + THIS:strato_mani <> 0
        THEN
          FOR EACH ind IsA indumento, DIRECTLY IN hero, IS indossato
            DO
              IF THIS:strato_testa  <> 0 AND THIS:strato_testa  <= ind:strato_testa
                THEN INCLUDE ind IN mia_AT:temp_indumenti.
              END IF.
              IF THIS:strato_viso   <> 0 AND THIS:strato_viso   <= ind:strato_viso
                THEN INCLUDE ind IN mia_AT:temp_indumenti.
              END IF.
              IF THIS:strato_tronco <> 0 AND THIS:strato_tronco <= ind:strato_tronco
                THEN INCLUDE ind IN mia_AT:temp_indumenti.
             END IF.
              IF THIS:strato_gambe  <> 0 AND THIS:strato_gambe  <= ind:strato_gambe
                -- THEN INCLUDE ind IN mia_AT:temp_indumenti.
                THEN
                  -- -----------------------------------------------------------
                  -- Legs clothing special checks
                  -- -----------------------------------------------------------
                  IF ind:blocca_gambe
                  -- Se l'indumento ostacolo è bloccante, blocca l'azione:
                    THEN INCLUDE ind IN mia_AT:temp_indumenti.
                  -- Altrimenti, è una gonna o un cappotto.
                  -- Verifica che l'indumento che si vuole indossare non formi
                  -- un pezzo unico game-tronco.
                  ELSIF THIS:strato_tronco <> 0 AND THIS IS NOT due_pezzi
                    THEN INCLUDE ind IN mia_AT:temp_indumenti.
                  END IF.
              END IF.
              IF THIS:strato_piedi  <> 0 AND THIS:strato_piedi  <= ind:strato_piedi
                THEN INCLUDE ind IN mia_AT:temp_indumenti.
              END IF.
              IF THIS:strato_mani   <> 0 AND THIS:strato_mani   <= ind:strato_mani
                THEN INCLUDE ind IN mia_AT:temp_indumenti.
              END IF.
          END FOR.
      END IF.

Final Thoughts

I'm quite happy with the results. I've managed to save all the functionality of the original code but made it fully customizable. I think that the new system is easier to understand and use, especially for the fact that layers can be numbered freely and no special cases are hard-coded.

All complex features are fully optional, and author don't need to use them at all. Soon I'll be also exposing a boolean attribute to allow toggling on/off the enforcement of ordered wear/remove (when OFF, the library will only prevent wearing multiple items on the same layer, but not enforce wearing them in layered order). Some authors might prefer to keep clothing simple in their games.

I also think that the new system is much simpler to use for end-users, especially if they need to create new verbs that might interact with worn items. Extensibility of wearables to non-clothing items is also an added benefit.

Overall, the key factors in the success of fixing clothing were:

I strongly suggest you consider my original proposal of this thread, and formulate some explicit guidelines of how verbs should treat donned items — without them, it's going to be very hard to test and fix the current problems with clothing and keep the library behavior consistent. Also, end users of the library need these guidelines to extend library verbs on custom classes, without having to study all the Library code.

It took me two full weeks to fix all the clothing problems in the Italian library, so ... yes, it's quite some work — and many new problems came up during work, which are not even mentioned in any issues here. But it's well worth doing it (wether you keep the worn entity or not).

I hope these shared thoughts and examples might help you decide on how to approach the current problems. Needless to say, I'm still of the opinion that handling worn-items via entity containers (like worn) is a bad choice, and that the donned boolean attribute is all that is required to handle them.

AnssiR66 commented 5 years ago

Hi Tristano! Many thanks for the detailed and thorough description of how you managed to solve the problems about clothing in the Italian library. It sounds very good, and if it is indeed simpler for the end user, we can then think about transferring it to the English library as well. It would help if there is an English test example of all this - is there such one in existence in the tests branch presently? So I can take a look at some point... But basically I am all for this, maybe with the exception of using 'worn' attribute for 'donned' but those are cosmetic issues. -Anssi


From: Tristano Ajmone notifications@github.com Sent: Thursday, February 21, 2019 2:01 PM To: AnssiR66/AlanStdLib Cc: AnssiR66; Comment Subject: Re: [AnssiR66/AlanStdLib] We Need Clear Clothing Guidelines (#64)

New Clothing System in Italian Library

Ciao Anssi,

Today I've finally completed fixing all the issues on the Italian Library. I wanted to share with you a brief resume of how things worked out (I'll use English attributes names here, for the sake of simplicity; unfortunately the code uses Italian referents, so it won't be of much help here).

It was a quite huge work and I had to sit down and write some formal rules on how donned items whould be dealt with in the Library — these guidelines are also important for end users who need to override verbs or create new verbs for their adventures, so that they can interact with the library in an orderly manner.

During the development stage, I also realized that implicit take actions in many verbs interfered with donned clothing, so I had to set some formal rules for those too; eg. in verbs that by default they don't do carry out the action (like "throw obj at npc") I've removed implicit taking of the object.

Ultimately, I've got rid of the worn entity and the wearing set too, and used only the donned attribute, which I've moved on the thing class to allow end users to implment non-clothing wearables too (eg. a wearable device, like VR goggles, IR goggles, headphones, ecc.). In view of this extensibility, I've also ensured that any verb which dislocated an object always sets it to NOT donned.

Verbs that should not be carried out on worn items are now blocked via CHECKs implemented on those verbs on clothing class.

Non-Exponential Wearing Layers

With the new clothing system in the Italian Library, clothing layers are no longer exponential (2, 4, 8, ...) but author can use any numbers they like. I've also added a new zone for the face, to allow wearing masks, beards, glasses, etc., without using up the head values.

Custom-Definable Skirts and Coats

I've removed the hardcoded special cases for skirts and coats, and introduced two new (entirely optional) attributes to allow users to make any item a skir-like clothes and even handle special items like "bikinis". Here's how it works...

EVERY indumento IsA OBJECT --> 'indumento' = 'clothings'

IS indossabile. --> 'wearable'

HAS genere 0.

HAS strato_testa 0. --> head

HAS strato_viso 0. --> face

HAS strato_tronco 0. --> chest/top

HAS strato_gambe 0. --> legs/bot

HAS strato_piedi 0. --> feet

HAS strato_mani 0. --> hands

IS blocca_gambe. NOT due_pezzi. --> 'blocks_legs' & 'two_pieces'

The blocks_legs attribute on clothing (defaults to true) can be set to IS NOT blocks_legs on a skirt/coat. When the library tries to work out which donned items are preventing wearing/removing, it will discount from legs-checks items that are marked as not blocking the legs. But before discounting them, it will check that the item being worn has a topcover value = 0, to prevent the exception when dealing with items that are one piece covering legs and torso.

The new attribute two_pieces (defaults to false) allows implmenting clothing like bikinis, which although they are handled as a single item they consist of two pieces, but these are separately covering legs and torso. So the library also considers this attribute when checking a blocking item which IS NOT blocks_legs (skirt or coat), and if the item being worn IS two_pieces then it will not check it for topcover = 0.

This means that if you're wearing a skirt you can wear/remove underpants and pantihose, but not a one-piece full body costume or a teddy, but you can wear/remove a bikini because it's seen as a two-piece costume. It's use is quite simple (approximation, since in the Italian library Italian identifiers are used instead):

-- We arbitrarily assign body layers according to need:

-- * layer 1: direct skin contact, like underpants, bra, etc.

-- * layer 2: items over underware, like pantihose, t-shirts, etc.

-- * layer 3: skirts, trousers, shirts, etc.

The skirt IsA clothing in hero

HAS botcover 3.

IS NOT blocks_legs. --> Doesn't prevent wearing/removing leg-only items.

IS donned.

End the.

The teddy IsA clothing

HAS topcover 1.

HAS botcover 1.

End the.

The bikini IsA clothing

HAS topcover 1.

HAS botcover 1.

IS two_pieces. --> Should be treated as if a legs-only item in skirts checks!

End the.

The pantihose IsA clothing

HAS botcover 2.

End the.

The above code will allow to correctly handle skirts. Of course, a bikini will be wearable with a skirt but will still be blocked by a t-shirt (in the topcover checks though).

Verbs wear/remove

The final code in the library for the wear/remove verbs is much simpler and shorter now:

  SET mia_AT:temp_indumenti TO {}.

  IF  THIS:strato_testa

    + THIS:strato_viso

    + THIS:strato_tronco

    + THIS:strato_gambe

    + THIS:strato_piedi

    + THIS:strato_mani <> 0

    THEN

      FOR EACH ind IsA indumento, DIRECTLY IN hero, IS indossato

        DO

          IF THIS:strato_testa  <> 0 AND THIS:strato_testa  <= ind:strato_testa

            THEN INCLUDE ind IN mia_AT:temp_indumenti.

          END IF.

          IF THIS:strato_viso   <> 0 AND THIS:strato_viso   <= ind:strato_viso

            THEN INCLUDE ind IN mia_AT:temp_indumenti.

          END IF.

          IF THIS:strato_tronco <> 0 AND THIS:strato_tronco <= ind:strato_tronco

            THEN INCLUDE ind IN mia_AT:temp_indumenti.

         END IF.

          IF THIS:strato_gambe  <> 0 AND THIS:strato_gambe  <= ind:strato_gambe

            -- THEN INCLUDE ind IN mia_AT:temp_indumenti.

            THEN

              -- -----------------------------------------------------------

              -- Legs clothing special checks

              -- -----------------------------------------------------------

              IF ind:blocca_gambe

              -- Se l'indumento ostacolo è bloccante, blocca l'azione:

                THEN INCLUDE ind IN mia_AT:temp_indumenti.

              -- Altrimenti, è una gonna o un cappotto.

              -- Verifica che l'indumento che si vuole indossare non formi

              -- un pezzo unico game-tronco.

              ELSIF THIS:strato_tronco <> 0 AND THIS IS NOT due_pezzi

                THEN INCLUDE ind IN mia_AT:temp_indumenti.

              END IF.

          END IF.

          IF THIS:strato_piedi  <> 0 AND THIS:strato_piedi  <= ind:strato_piedi

            THEN INCLUDE ind IN mia_AT:temp_indumenti.

          END IF.

          IF THIS:strato_mani   <> 0 AND THIS:strato_mani   <= ind:strato_mani

            THEN INCLUDE ind IN mia_AT:temp_indumenti.

          END IF.

      END FOR.

  END IF.

Final Thoughts

I'm quite happy with the results. I've managed to save all the functionality of the original code but made it fully customizable. I think that the new system is easier to understand and use, especially for the fact that layers can be numbered freely and no special cases are hard-coded.

All complex features are fully optional, and author don't need to use them at all. Soon I'll be also exposing a boolean attribute to allow toggling on/off the enforcement of ordered wear/remove (when OFF, the library will only prevent wearing multiple items on the same layer, but not enforce wearing them in layered order). Some authors might prefer to keep clothing simple in their games.

I also think that the new system is much simpler to use for end-users, especially if they need to create new verbs that might interact with worn items. Extensibility of wearables to non-clothing items is also an added benefit.

Overall, the key factors in the success of fixing clothing were:

I strongly suggest you consider my original proposal of this thread, and formulate some explicit guidelines of how verbs should treat donned items — without them, it's going to be very hard to test and fix the current problems with clothing and keep the library behavior consistent. Also, end users of the library need these guidelines to extend library verbs on custom classes, without having to study all the Library code.

It took me two full weeks to fix all the clothing problems in the Italian library, so ... yes, it's quite some work — and many new problems came up during work, which are not even mentioned in any issues here. But it's well worth doing it (wether you keep the worn entity or not).

I hope these shared thoughts and examples might help you decide on how to approach the current problems. Needless to say, I'm still of the opinion that handling worn-items via entity containers (like worn) is a bad choice, and that the donned boolean attribute is all that is required to handle them.

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/AnssiR66/AlanStdLib/issues/64#issuecomment-465974448, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AF2lHljR1CzHhnzhwsp7Imzb8E1oBSKJks5vPoqdgaJpZM4au6lf.

tajmone commented 5 years ago

Hi Tristano! Many thanks for the detailed and thorough description of how you managed to solve the problems about clothing in the Italian library.

You're most welcome. Anything I can do to give back to the Alan community I'm happy to do it, rather than just take what I need I prefer to always contribute back. IF is a small niche, and Alan is even smaller niche within the niche, so our strength derives from collaborative efforts.

It sounds very good, and if it is indeed simpler for the end user, we can then think about transferring it to the English library as well. It would help if there is an English test example of all this - is there such one in existence in the tests branch presently?

In the Italian library I've used the same "Emporium Alani" (ega.alan) which I've add to StdLib too. The new system only required very small tweaks in the original test files, ie. using IN hero instead of IN worn, and adding IS donned to clothes meant to be initially worn by any actor.

The old coverage values of the Clothing Table still work fine, although the new systems doesn't require using exponential values it's still compatible with them (because each value is higher than the previous). So, tweaking the clothing values in the test file is optional, although it would be more elegant to read.

You can peek at the Italian version of the EGA test/example, and compare it to the English one:

Although they are not 100% identical (clothing items instances, etc.) they are fairly comparable.

So I can take a look at some point... But basically I am all for this,

What I suggest at this point is that I create a new dev-branch and implement there the same changes I've done on the Italian library, commit by commit (I've kept my local dev branch, so it would be easier for me to reproduce the single steps one by one, because the changes are numerous). Once the dev branch is ready, you can study and test it until you're satisfied it can be merged into master branch.

As I did with the Italian dev branch, during development I'll always keep a copy of the original code (commented out) next to its tweaked version, and I'll mark all tweaked code with comments which can be easily found via search functionality (eg: -- >>> dev-clothing: tweaked >>>, so that before merging it's easy to quickly find and examine every change done to the code, to double check everything.

maybe with the exception of using 'worn' attribute for 'donned' but those are cosmetic issues.

Definitely. This would have to be done last, because before I can actually rename it I'll need to have reached the point where no more references are present in the library to the worn entity, and it can safely be deleted. There are quite a number of verbs that refer to worn, so in the Italian library development I approach the problem gradually, one step at the time and introducing new tests at each step in order to check that everything was working as intended (which proved useful, as it allowed me to catch some unexpected side effects which needed to be addressed).

tajmone commented 5 years ago

New Dev Branch

I've created the dev-clothing development branch for fixing the clothing problems following the steps I've used for the Italian library:

I've added two temporary documents in this branch:

I've done the same during the work on the Italian Lib, because the number of changes was rather big and some things had to be done in the right order. Annotations are always useful, especially for third parties who need to follow the progress without having to sift through the whole code or commits history.

The CLOTHING_NEW.md document is going to be useful if we'd like to ask users of the Alan Yahoo group their opinion on the new approach to clothing (something I couldn't benefit from in the Italian library, due to the languistic barrier).

Hopefully, applying the same changes to the English library is going to be quicker than the original work on the Italian code (two weeks!) for I have all the commits history on my local repository, and I only need to apply the same sets of changes symmetrically (apart from difference in identifiers names between the Italian and English code, the code structure is the same).

Working on both codebases simulatenously is not always easy for me, and often confusing, for I tend to forget which changes where done in which library, especially for the tests adventures and scripts. But the commits history and the work notes should facilitate this task.

tajmone commented 5 years ago

Anssi,

I'm gradually adapting the clothing code to the new system. So far I've implemented the new attributes and the wear/remove verbs. There's still a lot of work to be done, but I wanted to give you a preview of the new layers system and how special clothes are handled.

In the DEV_skirts.a3log transcript you can see how the new way of handling special items like skirts and coats works.

Here's a few excerpts from the EGA tests, to show how easy to use is the new system.

Skirt and Coats

Now, to declare an item to be skirt-like, you only need to set it as NOT blockslegs:

EVERY proto_skirt IsA clothing.
  NAME skirt.
  HAS botcover 32. NOT blockslegs. --> Skirts don't prevent wearing lower legswear!
END EVERY.

EVERY cl_coat IsA clothing.
  NAME coat.
  HAS topcover 64.
  HAS botcover 64. NOT blockslegs. --> Coats don't prevent wearing lower legswear!
END EVERY.

And it works like a charm, out of the box:

> wear skirt

You pick up the skirt and put it on.

> wear pantyhose

You pick up the white pantyhose and put them on.

> remove pantyhose

You take off the white pantyhose.

Teddy-Like Clothes

Clothes which form a single piece covering legs and torso are automatically blocked (a one-piece swimsuite, a teddy, ecc):

> x swimsuit

A one-piece swimsuit, for women swimmers.

> wear swimsuit

In order to wear the swimsuit you should first take off the skirt.

Bikini

Now, creating clothes like a bikini, which is indeed a two-pieces item (both wearable/removable in a single action), but sicne they are two separate pieces they should not be prevented to be worn while wearing a skirt.

Creating a bikini-like only requires setting the item as IS twopieces:

THE bikini IsA clothing AT ega_sportswear.
  HAS topcover 2.
  HAS botcover 2. IS twopieces. --> legs and torso are covered separately
  HAS ex "A two-piece swimsuit, for women.".
END THE.

And it works like a charm, out of the box:

> wear skirt

You put on the skirt.

> wear bikini

You put on the bikini.

> remove bikini

You take off the bikini.

But coats and dresses will not allow wearing/removing it, because a coat blocks the upper body part:

> wear coat

You put on the men's coat.

> wear bikini

In order to wear the bikini you should first take off the men's coat.

tajmone commented 5 years ago

Ok Anssi,

I've completed implementing here all the changes I had done in the Italian Library. Apart from the need to adpat and fix the original tests, and polish up the code before merging, all the functionality is now in place.

Look at the tests in tests/clothing/ named DEV_*.a3log (the others haven't been updated) and give it a try. The dev documentation is pretty much well annotated, so you can read about the changes as well.

In the meantime I'll be fixing the original tests to the new system, and delete redundant tests.

Before merging into master, the code should be cleaned by removing copies of the original code and all the various annotations (see the dev docs about this).

Take your time to look at the changes I've introduced, and to play with the new system to get a feel of it. When you're satisfied with it and you're OK to merge it, let me know so I'll take care of the final polishing before squashing all the changes in master (might take a whole day just to clean up all the comment).

AnssiR66 commented 5 years ago

Hi Tristano! Many thanks for your extensive work. I will take a look at this and let you know my comments soon enough, Best, Anssi


From: Tristano Ajmone notifications@github.com Sent: Wednesday, February 27, 2019 12:06 AM To: AnssiR66/AlanStdLib Cc: AnssiR66; Comment Subject: Re: [AnssiR66/AlanStdLib] We Need Clear Clothing Guidelines (#64)

Ok Anssi,

I've completed implementing here all the changes I had done in the Italian Library. Apart from the need to adpat and fix the original tests, and polish up the code before merging, all the functionality is now in place.

Look at the tests in tests/clothing/ named DEV_*.a3log (the others haven't been updated) and give it a try. The dev documentation is pretty much well annotated, so you can read about the changes as well.

In the meantime I'll be fixing the original tests to the new system, and delete redundant tests.

Before merging into master, the code should be cleaned by removing copies of the original code and all the various annotations (see the dev docs about this).

Take your time to look at the changes I've introduced, and to play with the new system to get a feel of it. When you're satisfied with it and you're OK to merge it, let me know so I'll take care of the final polishing before squashing all the changes in master (might take a whole day just to clean up all the comment).

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/AnssiR66/AlanStdLib/issues/64#issuecomment-467633690, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AF2lHp_bTlVoLi_dejifOdKTNKtEtHDvks5vRa_wgaJpZM4au6lf.

AnssiR66 commented 5 years ago

Hi Tristano, thanks for your work with the clothing class, I have now taken a look and it all looks very good. I think this could be merged any time soon (no hurry for my part, take your time with polishing the files first), and of course I also have to update the library manual accordingly. I must take care I take into account all essential changes to be included in the manual, so I will show it to you before we publish it any further. Of course, there might be still something else (than CLOTHING) to edit/correct in the library before the official update can be released... I would also need to ask you about how, or if, these tricks can be done:

Later, Anssi


tajmone commented 5 years ago

thanks for your work with the clothing class, I have now taken a look and it all looks very good.

I'm glad you agree on the changes.

I think this could be merged any time soon (no hurry for my part, take your time with polishing the files first), and of course I also have to update the library manual accordingly.

I agree, this being a major change we must not hurry but take all the time to look at the code and test it before merging it. And yes, there's quite some polishing work to be done, but I've intentional left that to the post-approval stage.

I must take care I take into account all essential changes to be included in the manual, so I will show it to you before we publish it any further.

Good idea. I've tried to annotate as much as possible in the markdown docs inside the dev branch, but at this stage it's important to be sure that the end users documentation will match the actual state of the library.

Are you going to use a Word/ODT document and then produce the DPF? or are you moving the documentation toward a text-based documentation format that can be versioned controlled, like AsciiDoc or markdown? The latter makes it easier to maintain the documentation along with the code (and as if it was code).

If you use a Word/ODT document, could you put the source document in the project too? (and not just the PDF)

Of course, there might be still something else (than CLOTHING) to edit/correct in the library before the official update can be released... I would also need to ask you about how, or if, these tricks can be done:

  • list the clothing at 'x me' and not at 'inventory'

Currently x me produces the usual "You nothing nothing unsual..." reponse, but a simple LIST Hero will do the trick — See this log for how the LIST Hero output looks like:

> DBG_INV me
You are carrying your undershirt (being worn), your sneakers (being worn), 
your khakis (being worn), your boxers (being worn) and your socks (being
worn).
  • omit listing clothing altogether (even if the hero/NPC is wearing some items of CLOTHING).

That would require a custom loop that only iterates through items that are IS worn. If you mean being able to change this behaviour globally in the Library then we'd need to add a setting via a boolean attribute that would then be checked before listing clothes in every code place which lists clothes (inventory, examine actor, and MESSAGES) — I'm favourable on exposing some library settings, after all they are entirely optional, so they don't make it harder to use the library for not knowing about them will just make the Library behave according to defaults, but advanced users can take advantage of these.

  • at a DOES ONLY for >x NPC, how does the author implement for example first a general sentence about the NPC, then the listings (inventory and clothing)? For example: "Mr Smith looks very tired. He is carrying a suitcase. He is wearing a brown suit."

Via the NPCs' ex attribute, which is always honoured first (as before). For an example, see the DEV_inventory.a3log log:

> examine assistant
She's your personal shopping assistant. The assistant is wearing a uniform 
and a pair of fashion boots.
  • how does this work for DOES ONLY at 'inventory', if the author wishes to have his own way of listing carried/worn items? For example, if the author wishes to list clothing first, and only then carried items, or vice versa?

If LIST actor is not good enough, he/she'll have to use custom iteration loops via FOR EACH. Since he'd be only needing to look at the boolean value of worn (which is now available on every thing) these loops are much simpler to implement in the new system (no separate worn entity for the Hero, no parallel wearing set, and no subclass restrictions — a thing is either worn or it isn't).

I think we could add some commented out examples in the library sources, and/or provide a collection of ready-made snippets in a subfolder.Code snippets are better than examples in a PDF document (which are problematic to copy and paste). This idea of providing snippets would be useful not just for this, but in general.