Changing room desciptions when multiple items are removed

I'm working on a section of my game where there are three objects on a table:

The workbench serves as storage. On the worktop you see thing1, thing2, and thing3.

I read the section on Visible and Scenery Attributes here, and I got this far:

The workbench serves as storage. On the worktop you see{if thing1.scenery: thing1, }
{if thing2.scenery:thing2, }{if thing3.scenery: and thing3}.

The problem I'm running into is that I'm getting into all kinds of trouble with stray commas and "and" when things are removed or if only one thing remains on the worktop. I thought something from the Better Descriptions section of Cloak of Darkness might be able to help me, but I don't know if functions are really the way to go here.

I was going with a basic example here, but the actual workbench description is:

The workbench serves as storage. There are a plant mister, some potting soil, and a lighter on the worktop.

So you see it's got an are/is problem depending on the state of the list in addition to the commas and the "and." I'm at a point where I might just rewrite the description if this gives me enough trouble, but I feel like this is a problem I should work out and a solution I should be able to deploy later on if I need it.

This is honestly making me a little crazy. I know there has to be a way to do it; I'm hoping someone has some helpful advice for a novice coder who's fairly handy with the GUI.


Hmm… is the workbench a surface or container that contains those objects?

Could use either:

The workbench serves as storage. On the worktop you see {=FormatList(FilterByAttribute(GetDirectChildren(workbench),"scenery",true),", ",", and", "nothing")}.

or

The workbench serves as storage. On the worktop you see {=FormatList(GetDirectChildren(workbench),", ",", and", "nothing")}.

(the former lists all scenery objects on the workbench; the latter all objects on the workbench)

Anything more complex than that, you'd likely have to create a function for.

Hmm…
if you made a function like this:

<function name="GetObjectsList" parameters="input" type="objectlist">
  output = NewObjectList()
  if (TypeOf(input) = "string") {
    input = Split (input)
  }
  foreach (name, input) {
    if (TypeOf (name) = "string") {
      obj = GetObject (name)
      if (not obj = null) {
        list add (output, obj)
      }
    }
    else if (TypeOf (name) = "object") {
      list add (output, object)
    }
  }
  return (output)
</function>

then you could do:

The workbench serves as storage. On the worktop you see {=FormatList(FilterByAttribute(GetObjectsList("thing1;thing2;thing3"),"scenery",true),", ",", and", "nothing")}.

Thank you! The first and second bits of code work great, and I'll keep the function in mind for when things get more complicated. I appreciate your help!

EDIT: Now that I think about it for a second, is there an advantage to using the function rather than the shorter code blocks? I know the function would be applicable elsewhere, but I'd still have to enter the items on the list manually in the description code, right?


Now that I think about it for a second, is there an advantage to using the function rather than the shorter code blocks?

The function might be useful if there's any case where you only want it to list a specific set of items. I wasn't sure if that was what you wanted.

If I was doing it, I'd probably make a function anyway, because I don't like the way FormatList handles an empty list.
Something like:

<function name="FancyObjectList" parameters="preList, objects, postList, empty" type="string">
  if (TypeOf (objects) = "object") {
    objects = GetDirectChildren (objects)
  }
  if (ListCount (objects) = 0) {
    if (IsDefined ("empty") {
      return (empty)
    }
    else {
      return ("")
    }
  }
  else {
    return (preList + FormatList (objects, ", ", " and ", "") + postList)
  }
</function>

Then you could do something like:

The workbench serves as storage. {=FancyObjectList("On the worktop you see ", FilterByAttribute(GetDirectChildren(workbench),"scenery",true), ".")}

(So that if none of the objects are there, it doesn't bother printing "On the worktop you see nothing.")

or

The workbench serves as storage. {=FancyObjectList("On the worktop you see ", workbench, ".", "You don't see anything interesting among the junk on the bench.")}

so that you can use a more imaginative message for an empty list.


I see! The results of the new function were what I was really going for, so that's very helpful. Thank you!

I have to admit, I'm finding it very difficult to solve problems like this on my own. I don't have a programming background, and the solutions turn out to require expertise I just don't have. So I appreciate your help.


If you like the Oxford comma (which I believe is standard in US English), you could add:

<function name="FancyObjectList" parameters="preList, objects, postList, empty" type="string">
  if (TypeOf (objects) = "object") {
    objects = GetDirectChildren (objects)
  }
  if (ListCount (objects) = 0) {
    if (IsDefined ("empty") {
      return (empty)
    }
    else {
      return ("")
    }
  }
  else if (ListCount (objects) = 2) {
    return (preList + FormatList (objects, ", ", " and ", "") + postList)
  }
  else {
    return (preList + FormatList (objects, ", ", ", and ", "") + postList)
  }
</function>

(Because object1, object2, and object3 has a comma before the "and", but object1 and object2 doesn't)


Ha! You've hit on a sore subject with my friends and me - I went to journalism school, where they teach you to root out and destroy the Oxford comma wherever you find it. They think I should be using it, and I'm resisting. But it will do their hearts good to know they have leverage over me now! :D


First of all, I want to thank you again for all your help, mrangel. I created the function you described in your last post, and put

The workbench serves as storage. {=FancyObjectList("On the worktop you see ", workbench, ".", "You don't see anything interesting among the junk on the bench.")}

in the table description. Everything works great throughout removing each object from the workbench and looking to see how the workbench's description changes, but when I look workbench after all three objects have been removed, I get

Error running script: Missing ')'
Error running script: Error evaluating expression 'ToString(eval(section))': Object reference not set to an instance of an object. The workbench serves as storage. {=FancyObjectList("On the worktop you see ", workbench, ".", "You don't see anything interesting among the junk on the bench.")}

According to the GUI, there's a problem in the ListCount (objects) = 0 section of the function. I've tried adding ) in a couple of places where it looked like there might be something open, but no luck. Is there something I'm doing wrong?


I think this is the error:
if (IsDefined ("empty") {
blame my careless typing. It should be:
if (IsDefined ("empty")) {


Worked perfectly! Thanks again!


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

Support

Forums