Dialog library version 0.46 has support only for a single noun in except clauses. I wanted to add support for multiple nouns like [take all but doll and truck].
No need to change the library, just adding the five six two predicates below (2 library overrides 1 library addon, 1 override , 3 4 new ones) anywhere in your story file is enough.
Here is the code:
%% Adds support for multiple nouns in except clauses, now working:
%% [take all but robot and sassy doll],
%% [take all but a doll and a truck],
%% [take all but the doll and the truck], etc.
(parse $Words as object $Output $Policy $ $AllAllowed)
*(split $Words by [but except] into $Left and $Right)
*(parse noun list $Left as $BaseList $Policy $AllAllowed)
*(parse noun list $Right as $DecRightBaseList {($_ is one of $BaseList)} 0)
%%(undecorate list $DecRightBaseList into $RightBaseList)
(strip decorations from $DecRightBaseList into $RightBaseList)
(remove from $BaseList matching $RightBaseList into $ObjList)
(mark multi-object $ObjList into $Output)
%% [take all but a doll] was not working properly due to decoration,
%% now fixed and working as intended.
(parse negative noun [$Number | $Words] from $BaseList into $Result)
{
($Number is one of [a an])
($N = 1)
(or)
(parse numeral $Number into $N)
}
(just)
(if) (empty $Words) (then)
(take $N from $BaseList into $NegList)
(else)
*(parse indefinite $Words as $DecNegList $N {($_ is one of $BaseList)})
%%(undecorate list $DecNegList into $NegList)
(strip decorations from $DecNegList into $NegList)
(endif)
(remove from $BaseList matching $NegList into $Result)
%%(interface (undecorate list $<InputList $>OutputList))
%%(interface (undecorate noun $<Input into $>Output))
%% [[a #brokendoll] [a #sassydoll] #wideeyeddoll]
%% -> [#brokendoll #sassydoll #wideeyeddoll]
%%(undecorate list [] into [])
%%(undecorate list [$Head | $Tail] into [$Undecorated | $Out])
%% (undecorate noun $Head into $Undecorated)
%% (undecorate list $Tail into $Out)
%% [a #brokendoll] -> #brokendoll, #brokendoll -> #brokendoll
%%(undecorate noun [a $Out] into $Out)
%%(undecorate noun $Out into $Out)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Example scenario
#store
(room *)
(name *) toy store
(look *) All kinds of dolls and other toys are on the shelves.
#brokendoll
(item *)
(name *) broken doll
(plural dict *) dolls
(descr *) One of its arms is missing.
#sassydoll
(item *)
(name *) sassy doll
(plural dict *) dolls
(descr *) It's clad in a lively sundress.
#wideeyeddoll
(item *)
(name *) wide-eyed doll
(plural dict *) dolls
(descr *) Wonder in its eyes, might be my imagination.
#firetruck
(item *)
(name *) red firetruck
(dict *) fire truck
(plural dict *) trucks
(descr *) Plastic, almost new.
#dumptruck
(item *)
(name *) heavy duty dump truck
(dict *) dump truck
(plural dict *) trucks
(descr *) It has a faded blue cab and gray open-box bed.
#robot
(item *)
(name *) battery powered robot
(descr *) It has metallic shiny colors, but no batteries or battery cover.
(#brokendoll/#sassydoll/#wideeyeddoll is #in #store)
(#firetruck/#dumptruck/#robot is #in #store)
(*(item $) is handled)
#player
(current player #player)
(* is #in #store)
These examples are working in original as well as with my addition:
take all but fire truck
take all but one
take all dolls but two
take all but dolls
take all but the doll (disambiguation)
The following commands work correctly with the new version:
take all but a doll (was bugged due to decoration in (parse negative noun), fixed)
take all but robot and sassy doll
take all but a doll and a truck
take all but the dolls and the trucks
take all but robot and dolls
take all but the robot and 2 dolls
take all but the doll and the truck (disambiguation with 6 correct choices, original code disregards truck exception and offers 3 choices for dolls only)
take all but robot, doll and truck (disambiguation with 6 correct choices)
Working with new code but maybe it should not (original one gives error):
take all but all dolls
Also take all but all
gives a different error now, old one:
(I only understood you as far as wanting to take something.)
new one:
(I only understood you as far as wanting to take the battery powered robot,
the heavy duty dump track, the red firetruck, the sassy doll, the wide-eyed
doll, and the broken doll.)
This last command can be made to work by changing
*(parse noun list $Right as $DecRightBaseList {($_ is one of $BaseList)} 0)
to
*(parse noun list $Right as $DecRightBaseList {($_ is one of $BaseList)} $AllAllowed)
Although why would anyone want to type that to take nothing?
Edit: Just a slight change to code, to make it more idiomatic. Functions the same.
Edit 2: I was an idiot. The library already had a (strip decorations) predicate, heh. Reflected the changes in the code above, commenting out unnecessary predicates and queries.
Edit 3: The code below in the second post is better and fixes more problems with less intrusive methods to the data structures used by the standard library.