! ----------------------------------------------------------------------------
! ADNAME - This Inform library provides a system of 'adnames', words which may
!          be used to refer to objects without themselves implicating that the
!          object name has been typed. For example, you'd want "GET TOILET
!          PAPER" to choose the toilet paper, but you wouldn't want "GET
!          TOILET" to, especially if there was also a toilet in scope.
!          Adnames are typically adjectives or other describing words (in the
!          above example, "TOILET" is the adname of the toilet paper). If you
!          want to give an object an adname, make it of class "adnc" and give
!          it the "adname" property. This property, like "name", takes a list
!          of dictionary words. Caution: unlike name, which is a special case,
!          adname names are in single quotes.
!
!          This library provides a solution similar to the answer to example
!          60 in the Inform Designers' Manual, except that groups of identical
!          objects are handled correctly. There is also (for flexibility) no
!          requirement that adnames come before names.
!
! Example  object coffin_stand "coffin stand"
!            class adnc
!            with
!              name "stand",
!              adname 'coffin' 'wooden',
!              description "You can refer to this smart wooden coffin \
!                           stand as 'coffin stand', but 'coffin' on its \
!                           own will mean the coffin itself.",
!            has
!              static;
!
!          Include this library before you define your objects.
!          (c) Andrew Clover, 1995, but freely usable. Release 1.
!          Compatible with Inform 5.5, library 5/12.
! ----------------------------------------------------------------------------

Property adname;
Class adnc
  with
    adname 0,
    parse_name
      [;
      return AdnameParser(self);           ! Calling another routine like
                                           ! this avoids excessive code
                                           ! duplication, and allows you
                                           ! to extend an object's parse_
                                           ! name routine whilst still
                                           ! calling the adname parser.
      ];

[ AdnameParser adobj w n i j a b succ fail;
  if (parser_action==##TheSame)
    {
    w= parser_one.&adname;
    n= (parser_one.#adname)/2;
    i= parser_two.&adname;
    j= (parser_two.#adname)/2;
    for (a= 0: a<n: a++)
      {
      fail= 1;
      for (b= 0: b<j: b++)
        if ((w-->a)==(i-->b))
          fail= 0;
      if (fail==1)
        return -2;
      }
    for (a= 0: a<j: a++)
      {
      fail= 1;
        for (b= 0: b<n: b++)
          if ((w-->b)==(i-->a))
            fail= 0;
      if (fail==1)
        return -2;
      }
    return 0;                              ! This bit adapted from the parser
                                           ! - check all words in adname of
                                           ! parser_one to see if they occur
                                           ! in adname of parser_two, then
                                           ! vice-versa. If either case is
                                           ! false, we say the objects are not
                                           ! the same (the player may type a
                                           ! word that distiguishes then); if
                                           ! both are true, we give the parser
                                           ! a crack at seeing if they're
                                           ! different (by looking at the name
                                           ! property).
    }
  else
    {
    n= 0;
    succ= 0;
    fail= 0;
    while (fail==0)
      {
      fail= 1;
      w= NextWord();
      for (i= 0: i<(adobj.#adname)/2: i++)
        {
        if (w==adobj.&adname-->i)
          fail= 0;
        }
      for (i= 0: i<(adobj.#name)/2: i++)
        {
        if (w==adobj.&name-->i)
          {
          fail= 0;
          succ= 1;
          }
        }
      n++;
      }
    if (succ==1)
      return n-1;
    else
      return 0;                            ! This is the bit of code executed
                                           ! normally (when the parser isn't
                                           ! trying to resolve identical
                                           ! objects). We just check that
                                           ! every word typed is in the adname
                                           ! or name property, and say that
                                           ! the phrase matches the object if
                                           ! any words are in the name.
    }
  ];
