if (noun notin actor && ~~ImplicitTake(noun)) return L__M(##Drop, 2, noun);
Looking at ImplicitTake, it returns true on failure and false on success, so the test above ought to be ImplictTake(noun) rather than ~~ImplicitTake(noun), as it is in all of the other calls in verblibm.h.
I (vlaviano) think that this issue has gone undetected in the past because the grammar for Drop uses the multiheld and multiexcept tokens which cause the parser to generate its own ImplicitTake prior to DropSub ever being called. I (vlaviano) discovered the issue after having extended the grammar for Drop and having adapted DropSub in one of my own programs to handle a special case (of liquid in a container).
Constant Story "DROPSUB IMPLICIT TAKE";
Constant Headline "^An Interactive Investigation^";
Include "Parser";
Include "VerbLib";
Object Start_Room "Start Room"
with description "This is the starting room.",
has light;
Object tin "metal tin"
with name 'metal' 'tin',
has container openable;
Object -> mint "breath mint"
with name 'breath' 'mint',
has edible;
[ Initialise;
location = Start_Room;
move tin to player;
];
Include "Grammar";
This has the following behavior:
DROPSUB IMPLICIT TAKE
An Interactive Investigation
Release 1 / Serial number 160202 / Inform v6.33 Library 6/12-beta1 SD
Start Room
This is the starting room.
>i
You're carrying:
a metal tin (which is closed)
>open tin
You open the metal tin, revealing a breath mint.
>drop mint
Perhaps you should take the breath mint out of the metal tin first.
>eat mint
(first taking the breath mint)
You eat the breath mint. Not bad.
I had expected drop to have similar behavior as eat, implicitly taking the mint out of the tin.
However, reading ImplicitTake more carefully, I see that the first few lines are:
[ ImplicitTake obj
res ks supcon;
switch (metaclass(obj)) { Class, String, Routine, nothing: rfalse; }
if (obj in actor) rfalse;
if (action_to_be == ##Drop) rfalse;
It seems that, in the case of ##Drop, ImplicitTake will always return false before changing the model world in any way.
I overlooked this because, in the program that I referred to in my previous post, I had created a new action with its code based on the existing DropSub impl, so action_to_be wasn't ##Drop. In the case of regular ##Drop, the distinction that I made between multiheld/multiexcept and other tokens is irrelevant since the parser's invocation of ImplicitTake always matches this action_to_be test and returns false, so DropSub's ImplicitTake line is called either way.
In light of this, rather than the ~~ImplicitTake() check in DropSub being reversed, it seems that it's instead superfluous and that the same effect could be achieved with:
if (noun notin actor) return L__M(##Drop, 2, noun);
Evidently, the library explicitly does not want ##Drop ever to do an implicit take, although it's unclear to me why this should be the case given how ##Eat works. I think that maybe it's to prevent the parser's multiheld/multiexcept ImplicitTake, when the user types "drop ", from producing "(first taking the foo) Dropped." ImplicitTake could deal with that by extending its acton_to_be check to:
if (action_to_be == ##Drop && obj in parent(actor)) rfalse;
This should allow the "drop " case to produce "the foo is already here", while allowing items that are indirectly contained in the actor to be implicitly taken and dropped.
All that being said, I'm not sure to what extent existing games rely on the old behavior or if there's a mandate to improve I6 library behavior (assuming that we can agree on what constitutes an improvement) vs. just fixing bugs.
Another one reported by vlaviano (http://www.intfiction.org/forum/viewtopic.php?f=7&t=19461&start=20#p106335)
There's a small issue in DropSub in verblibm.h:
Looking at ImplicitTake, it returns true on failure and false on success, so the test above ought to be ImplictTake(noun) rather than ~~ImplicitTake(noun), as it is in all of the other calls in verblibm.h.
I (vlaviano) think that this issue has gone undetected in the past because the grammar for Drop uses the multiheld and multiexcept tokens which cause the parser to generate its own ImplicitTake prior to DropSub ever being called. I (vlaviano) discovered the issue after having extended the grammar for Drop and having adapted DropSub in one of my own programs to handle a special case (of liquid in a container).
This has the following behavior:
I had expected drop to have similar behavior as eat, implicitly taking the mint out of the tin. However, reading ImplicitTake more carefully, I see that the first few lines are:
It seems that, in the case of ##Drop, ImplicitTake will always return false before changing the model world in any way.
I overlooked this because, in the program that I referred to in my previous post, I had created a new action with its code based on the existing DropSub impl, so action_to_be wasn't ##Drop. In the case of regular ##Drop, the distinction that I made between multiheld/multiexcept and other tokens is irrelevant since the parser's invocation of ImplicitTake always matches this action_to_be test and returns false, so DropSub's ImplicitTake line is called either way.
In light of this, rather than the ~~ImplicitTake() check in DropSub being reversed, it seems that it's instead superfluous and that the same effect could be achieved with:
Evidently, the library explicitly does not want ##Drop ever to do an implicit take, although it's unclear to me why this should be the case given how ##Eat works. I think that maybe it's to prevent the parser's multiheld/multiexcept ImplicitTake, when the user types "drop", from producing "(first taking the foo) Dropped." ImplicitTake could deal with that by extending its acton_to_be check to:
This should allow the "drop" case to produce "the foo is already here", while allowing items that are indirectly contained in the actor to be implicitly taken and dropped.
All that being said, I'm not sure to what extent existing games rely on the old behavior or if there's a mandate to improve I6 library behavior (assuming that we can agree on what constitutes an improvement) vs. just fixing bugs.