take all only puts one item in inventory (adv3Lite)

There are three files in the room—red, blue, and green—all identified as file in the vocab property, and each disambiguated by it’s color.

I enter the command take file.

When the parser asks which file I say all.

The parser says taken, which I read to mean all three files were taken…

…but no.

When I check my inventory, I see only one file actually made it there (verified by checking the contents in the debugger).

Here’s the code, in a test bed environment…

[code]#charset “us-ascii”

#include <tads.h>
#include “advlite.h”

versionInfo: GameID
IFID = ‘445C38A3-AD1B-4729-957A-F584600DE5C1’
name = ‘test’
byline = ‘by Jerry Ford’
htmlByline = ‘by
Jerry Ford

version = ‘1’
authorEmail = ‘Jerry Ford jerry.o.ford@gmail.com
desc = ‘taking all.’
htmlDesc = ‘taking all.’

;

gameMain: GameMainDef
initialPlayerChar = me
paraBrksBtwnSubcontents = nil

;

me: Actor ‘me’ @livingRoom // @mcAllister400FourthFloorHallway
“The main man.<.p>”
isHim = true

person = 2

;
livingRoom: Room ‘The Room’ ‘room’
desc
{
“In the room. <.p>”;
}
;

  • blueFile: FileFolder ‘file;blue’
    “The <> file.<.p>”
    color = ‘blue’
    disambigName = color + ’ file’
    ;
  • redFile: FileFolder ‘file;red’
    “The <> file.<.p>”
    color = ‘red’
    disambigName = color + ’ file’
    ;
  • greenFile: FileFolder ‘file;green’
    “The <> file.<.p>”
    color = ‘green’
    disambigName = color + ’ file’
    ;
    class FileFolder: Container ‘file’
    “A file. <.p>”
    color = ‘beige’
    lableText = ‘Empty File’
    ;

[/code]

Jerry

Note that this only occurs if you type ALL in response to the Which one do you mean question; TAKE ALL FILES works just fine.

The problem is deep inside Mike Roberts’s Mercury parser code, so it was a bit tricky to track down. What seems to be happening is that the parser is accepting ALL as a valid disambiguation response, and then ignoring anything about it apart from the fact that it was valid. In particular, the fact that you typed ALL rather than, say, ANY wasn’t being passed on to the code that actually tries to work out which object(s) you meant. At that point the parser was simply trying to match TAKE FILE again, but this time deciding that any old file would do.

I’ve come up with a fix that works, though it looks a bit ad-hoc to me, so I make see if I can improve on it. In the meantime the fix is in the construct method of the CommandList class at around line 864 in parser.t. The relevant section of code now looks like this:

/* 
             *   Go through the list, looking for an item with noun phrases we
             *   can resolve.  Take the first item that we can properly
             *   resolve.  
             */
            foreach (local c in cmdLst)
            {
                try
                { 
                    /* 
                     *   If the player typed something like ALL at the
                     *   disambiguation prompt, this info needs to be passed on
                     *   to the command dobjNPs so that the appropriate match is
                     *   made.
                     */
                    if(prod == mainDisambigPhrase)
                    {
                        c.dobjNPs[1].determiner = c.disambig[1][1].determiner;
                    }
                    
                    /* resolve this phrase */
                    c.resolveNouns();

The lines that have just been added are:

                    /* 
                     *   If the player typed something like ALL at the
                     *   disambiguation prompt, this info needs to be passed on
                     *   to the command dobjNPs so that the appropriate match is
                     *   made.
                     */
                    if(prod == mainDisambigPhrase)
                    {
                        c.dobjNPs[1].determiner = c.disambig[1][1].determiner;
                    }

This ensures that the determiner information is passed on to the code that needs to know about it (it wasn’t being passed on before), but it would be nice if there were a neater way of doing it. In the meantime I’ve uploaded the fixed version to GitHub.

EDIT:
I’ve now come up with a marginally neater fix which I slightly prefer, and have uploaded the revised fix to GitHub. This simply involves using the disambig responses determiner at a slightly different point in the code.

In case anyone’s interested, instead of the change above, the new change comes in the definition of the NounPhrase class at around line 2221 in parser.t. The selectObjects() method now starts:

 selectObjects(cmd)
    {
        /* take the mode from the determiner */
        local mode = determiner;
        
        /*  //INSERTED CODE STARTS HERE
         *   If the player typed ALL or ANY or some such response in response to
         *   a disambiguation respose, that response will have set a determiner
         *   we need to use instead.
         */
        if(cmd.disambig.length > 0)
            mode = cmd.disambig[1][1].determiner;
        // END OF INSERTED CODE

This does precisely what the other fix did, it just does it at a different point where it feels slightly less ad-hoc, but the difference may be no more than an aesthetic one.