referencing an object by "it" when it's been moved

I have an object that, once examined, changes into a different object, i.e. the player has now "recognised" it. (Simply I move the original object to a room called "Nowhere" and the replacement object to the current room.) If the player then uses the pronoun "it", the engine still thinks the previous object is being referred to, not the new object, but rather than saying it is not there, it says "the Nowhere is not open". Is this a bug, or can I redirect "it" to the new object?


I get the same result in my v5.8 desktop TA game. The player drops a "pinecone" from a tree (which then lands in another room, say "the Ground"). The player can still look at "it" (the pinecone, which shouldn't be in scope), and when the player tries to take "it", the game says, "The Ground is not open." (as if "The Ground" is a closed container).

This does appear to be a bug.


UPDATE:

So when you move an object to another room out of scope, then run any command on that object's article (it, them, him, her), that object in question is still treated as if it were still in scope. If, instead, you drop an object and move to another room, then run a command on the dropped object's article, things work as they should as you get the unrecognised object message.


Yup, thanks Dcoder, you seem to have it. If there's anything I can do to re-focus the article on the "new" item - the pinecone in your example - than I would do so, but it's not obvious how.


Yup, thanks Dcoder, you seem to have it. If there's anything I can do to re-focus the article on the "new" item

There is an objectlist, game.lastobjects, containing the objects that you used in the last command.
So when you move the object away, if you have something like:

msg ("It appears to be Dr Nerk's diploma.")
MoveObject (piece_of_paper, Nowhere)
MoveObjectHere (diploma)

you would want to add the lines:

if (HasAttribute (game, "lastobjects")) {
  if (ListContains (game.lastobjects, piece_of_paper)) {
    list remove (game.lastobjects, piece_of_paper)
    list add (game.lastobjects, diploma)
  }
}

This does appear to be a bug.

Agreed.

In the function ResolveNameFromList, we have the code:

    if (objtype = "object" and game.lastobjects <> null) {
      foreach (obj, game.lastobjects) {
        CompareNames (LCase(obj.article), value, obj, fullmatches, partialmatches)
        CompareNames (LCase(obj.gender), value, obj, fullmatches, partialmatches)
      }
    }

I believe this should be:

    if (not secondaryscope = null) {
      scope = ListCombine (scope, secondaryscope)
    }
    if (objtype = "object" and game.lastobjects <> null) {
      foreach (obj, game.lastobjects) {
        if (ListContains (scope, obj)) {
          CompareNames (LCase(obj.article), value, obj, fullmatches, partialmatches)
          CompareNames (LCase(obj.gender), value, obj, fullmatches, partialmatches)
        }
      }
    }

(Note that I'm combining scope and secondaryscope here, because if the player types "drop wallet" and then "drop it", it should assume you mean the wallet even though it's no longer in the drop command's scope (which I believe is "inventory"). The game should respond "You aren't holding it." (as if you'd named a non-held object from secondaryscope) rather than failing to match anything.


Very informative, mrangel!

I put this simple turn script in my game and it seems to work ok:

game.lastobjects2 = game.lastobjects
foreach (object, game.lastobjects2) {
  if (not ListContains(ScopeVisible(), object)) {
    list remove (game.lastobjects, object)
  }
}

This just removes any unseen objects from game.lastobjects (but doesn't replace them with another object). If you see any problems with this, feel free to comment.


Many thanks to both of you! Issue solved.


(Edit: fixed a small bug in the posted code; thanks to Pixie)

Actually… my fix there is inelegant. I can see cases with more complex commands where it won't work correctly.

I think the section of code I quoted above should be removed, and the handling of lastobjects moved into the function CompareNames; either that or something like:

  <function name="ResolveNameFromList" parameters="variable, value, objtype, scope, secondaryscope" type="object">
    <![CDATA[
    value = Trim(LCase(value))
    fullmatches = NewObjectList()
    partialmatches = NewObjectList()

    foreach (obj, scope) {
      name = LCase(GetDisplayAlias(obj))
      CompareNames (name, value, obj, fullmatches, partialmatches)
      if (obj.alt <> null) {
        foreach (altname, obj.alt) {
          CompareNames (LCase(altname), value, obj, fullmatches, partialmatches)
        }
      }
      if (ListContains (game.lastobjects, obj)) {
        CompareNames (LCase(obj.article), value, obj, fullmatches, partialmatches)
        CompareNames (LCase(obj.gender), value, obj, fullmatches, partialmatches)
      }
    }
   
    // Also check the secondary scope, but only if we have not found anything yet

    if (ListCount(fullmatches) = 0 and ListCount(partialmatches) = 0 and not secondaryscope = null) {
      foreach (obj, secondaryscope) {
        name = LCase(GetDisplayAlias(obj))
        CompareNames (name, value, obj, fullmatches, partialmatches)
        if (obj.alt <> null) {
          foreach (altname, obj.alt) {
            CompareNames (LCase(altname), value, obj, fullmatches, partialmatches)
          }
        }
        if (ListContains (game.lastobjects, obj)) {
          CompareNames (LCase(obj.article), value, obj, fullmatches, partialmatches)
          CompareNames (LCase(obj.gender), value, obj, fullmatches, partialmatches)
        }
      }
    } 

    if (ListCount(fullmatches) = 1) {

(remainder of function unchanged)

That means that in odd cases like my spellcasting command (cast #object1# on #object2# with scope object1=spellbook;object2=notheld), after the player has typed "cast knock on chest", they can use both "cast it on door" and "cast fireball on it", and the parser will correctly guess which object they mean by "it".


Thanks again. You are obviously a perfectionist - or at least a "completionist"! I greatly appreciate your time and effort.


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

Support

Forums