Up to Main Index Up to Journal for August, 2019 JOURNAL FOR THURSDAY 15TH AUGUST, 2019 ______________________________________________________________________________ SUBJECT: Parsing is complicated DATE: Thu 15 Aug 22:16:27 BST 2019 I’ve been steadily adding tests for the PUT command to cover the new matcher functionality. As a result I came across a few oddities which have caused me to pause and ponder. The syntax for the PUT command is deceptively simple: PUT <item...> <container> We specify ‘PUT’ as the command, list the items we want to PUT into something and the container we want to PUT the items into. For example: You see a small box here. You see a small green ball here. You see a small red ball here. >GET BALL You get a small green ball. >PUT BALL BOX You put a small green ball into the box. With the new matcher we can also qualify exactly which items we mean: >PUT ALL BALL BOX // Put all held balls into the box >PUT ALL RED BALL BOX // Put all the red balls into the box >PUT ALL SMALL BALL BOX // Put all the small balls into the box >PUT 2ND BALL BOX // Put 2nd held ball into the box >PUT 3 BALL BOX // Put up to three held balls into the box >PUT 2-4 BALL BOX // Put from the 2nd up to the 4th ball into the box >PUT RED BALL BOX // Put only the red ball into the box However, what if we try specifying multiple containers to put things into? For example: You see a small box here. You see a large box here. You see a small green ball here. >GET BALL You get a small green ball. >PUT BALL ALL BOX … Which box should be used? In this case ‘ALL BOX’ would match the small box and the large box. Originally I had the PUT command complain: >PUT BALL ALL BOX Which container did you mean? A small box. A large box. > That seemed overly clumsy, so I modified the PUT command to pick the first container matched automatically: >PUT BALL ALL BOX You put a small green ball into a small box. > If you really meant to put the ball into the large box then either of these incantations would work: >PUT BALL LARGE BOX >PUT BALL 2ND BOX But, always a but, what if you had the following: You see a closed box here. You see an opened box here. You see a small green ball here. >GET BALL You get a small green ball. >PUT BALL ALL BOX A closed box is not something you can put things in. > In this example ‘ALL BOX’ matches the closed box first and the open box second. It uses the first box found, the closed box, and says you can’t put things into it. What should we do here? As multiple items have been identified for the container should we just blindly try to use the first one? Or should we work our way through the list of possible matches until we find a useable one? That could get complicated and computationally expensive quickly as we check if each item has an inventory, does not veto the command and other checks on attributes yet to be added. To take this even further, assume there is a half full box and an empty box, the half full box gets picked first. We try to put multiple items into ‘ALL BOX’. When the half full box becomes full should we automatically start filling the next, empty box? If we tried something slightly different, like ‘PUT <multiple items> LARGE BOX SMALL BOX’ instead of ‘PUT <multiple items> ALL BOX’, how would the parser know you want to fill large box then the small box instead of putting the large box into the small box? As an aside, should you be able to specify ‘PUT <item> HALF FULL BOX’ or ‘PUT <item> EMPTY BOX’ to differentiate between boxes?[1] It’s turtles all the way down… That then raises the question of whether commands like GET should be modified to also resolve ambiguities: You see a gigantic rock here. You see a small rock here. >GET ROCK You get a small rock. >GET ROCK The gigantic rock is too heavy for you to lift. > In this example the gigantic rock is matched first but cannot be picked up, so the 2nd match, the small rock, is tried which succeeds. Is this what players would want though? However we need to be careful, otherwise players can abuse the PUT command to fish for containers that should only be discoverable through exploration. For example, suppose we have 1,000 balls somehow. Then in what looks like an empty location: Store Room You are in a small, windowless store room which seems to be empty at the moment. Odd considering the thick and heavy iron door protecting it. You can see exits south. >PUT ALL BALL ALL CONTAINER You put a small green ball into a small hole in the floor. You put a small green ball into a crack in the wall. You put a small green ball onto a small shelf above the door. > Now the player has no need to wonder why the store room is empty and they have no need to explore it further :( My gut tells me that the parser/commands/matcher should try to do as much as possible to resolve ambiguities for the player. My brain is telling me that it hurts and writing a two or three word parser is so much easier… I’m currently working through all this and seeing what I can make work and what I can’t. I’ll either end up with something awesome and complicated code or something mediocre with simpler code — I don’t think it will be awesome and simple :| -- Diddymus [1] This wouldn’t be to difficult. Containers, well Inventory, already have an Empty() method. We could implement the has.Alias interface and add an EMPTY qualifier on the fly if it returned true. Hrm… Up to Main Index Up to Journal for August, 2019