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