A thought for making ShowMenu more intuitive

Here's a function that could be used with ShowMenu when handling an objectlist.
Using this for disambiguation menus would be really neat :)

Two features:

  1. If an object has an attribute equivalent_attributes (a string of attribute names separated with semicolons), then multiple objects in which those attributes match are removed from the list. For example, if a player types "eat apple" and there are 3 identical apples on the table, you don't want a disambiguation menu asking them to choose "apple", "apple", or "apple".

    I originally thought of removing duplicate items from the menu if they have the same prototype; but then realised you could have an apple with some attribute to make it either red or green, cloned from the same base object. So this method allows an object to specify which objects it should be considered identical to. A good value might typically be "prototype;parent".

  2. Where multiple objects have the same alias, look through their alt attributes to see if there is a distinct name that only applies to one of them.

<function name="FindUniqueNames" parameters="objects" type="stringdictionary">
  filtered_objects = NewObjectList()
  names_for_object = NewDictionary()
  duplicate_names = NewStringList()
  all_names = NewStringList()
  foreach (obj, objects) {
    redundant = false
    if (ListContains (filtered_objects, obj)) {
      redundant = true
    else if (HasString (obj, "equivalent_attributes")) {
      attrs = obj.equivalent_attributes
      possibles = FilterByAttribute (filtered_objects, "equivalent_attributes", attrs)
      foreach (attr, Split (attrs)) {
        possibles = FilterByAttribute (possibles, attr, GetAttribute (obj, attr))
      if (ListCount (possibles) > 0) {
        redundant = true
    if (not redundant) {
      list add (filtered_objects, obj)
      names = NewStringList()
      list add (names, GetDisplayAlias(obj))
      if (HasAttribute (obj, "alt")) {
        names = ListCombine (names, obj.alt)
      // could add stuff here to generate alternate names like "Hat (on hatstand)", "Hat (in inventory)", "Hat (worn)", or "Lamp (switched on)"
      foreach (name, names) {
        if (not ListContains (all_names, name)) {
          list remove (all_names, name)
        else if (not ListContains (duplicate_names, name)) {
          list add (duplicate_names, name)
      dictionary add (names_for_object, obj.name, names)
  result = NewStringDictionary()
  names_used = NewStringList()
  foreach (key, names_for_object) {
    names = DictionaryItem (names_for_object, key)
    unames = ListExclude (names, duplicate_names)
    if (ListCount (unames) = 0) {
      unames = ListExclude (names, names_used)
      if (ListCount (unames) = 0) {
        unames = names
    myname = ListItem (unames, 0)
    dictionary add (result, key, myname)
    list add (names_used, myname)
  return result

OK, I've not finished polishing this (or tested it), but I need to get back to actual work and stop procrastinating with things that happened to cross my mind.

This topic is now closed. Topics are closed after 60 days of inactivity.