Objects inside/on another object

Hi
So here's what I want to have but I can't figure out.

You enter a room. There's a statue. The statue has a children object called "hand". This object should be examined only after you typed "watch/look statue" or "examine statue". Basically, you can't examine the hand without going first near the statue. I don't want to make another room for this since it'd be super annoying and the project would clutter pretty quickly

Containers? Yeah, they work fine when I use "hide children until looked at" but once you looked once, the items inside can still be looked at even without going/watching the parent first

I hope this is making sense, thanks.


Only way I can come up with easily is put statue as container, check can be open and closed and when looked at run script to open statue and start timer reveling hand for X seconds then in timer add close statue and stop timer.


I always just give up, put the object in the room with the statue, make the object scenery, and fool the player with the descriptions and responses.

>The statue is here.
There is a doo-hickey on it.

>>take doo-hickey
You can't, its part of the statue.

>>examine doo-hickey
The doo-hickey, which is part of the statue, blah blah blah...


Sorry. I didn't read the question correctly!


This example may help.

The hand isn't in scope until you examine the statue.

I made it so the hand 'disappears' back to the statue once examined, but you can change that around.

Here's just the bit with the statue and the hand:

  <object name="statue">
      <inherit name="editor_object" />
      <look type="script">
        msg ("It looks like a statue.")
        if (hand.parent = statue) {
          statue.hand_on = true
          msg ("It has a hand.")
          MoveObjectHere (hand)
        }
      </look>
      <object name="hand">
        <inherit name="editor_object" />
        <look type="script">
          msg ("It's a hand.")
          if (HasAttribute(statue, "hand_on")) {
            if (statue.hand_on) {
              msg ("It's part of the statue right now.")
              statue.hand_on = false
              MoveObject (hand, statue)
            }
          }
        </look>
      </object>
  </object>

Here's what happens:

You are in a room.
You can see a statue.

> x hand
I can't see that.

> x statue
It looks like a statue.
It has a hand.

> x hand
It's a hand.
It's part of the statue right now.

> x hand
I can't see that.

> x statue
It looks like a statue.
It has a hand.

> x hand
It's a hand.
It's part of the statue right now.

> x hand
I can't see that.


Here the entire example game.

CLICK TO VIEW LONG CODE
<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="tester">
    <gameid>858dcb43-f0d5-4224-8091-79a12850810e</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <description type="script">
    </description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="statue">
      <inherit name="editor_object" />
      <look type="script">
        msg ("It looks like a statue.")
        if (hand.parent = statue) {
          statue.hand_on = true
          msg ("It has a hand.")
          MoveObjectHere (hand)
        }
      </look>
      <object name="hand">
        <inherit name="editor_object" />
        <look type="script">
          msg ("It's a hand.")
          if (HasAttribute(statue, "hand_on")) {
            if (statue.hand_on) {
              msg ("It's part of the statue right now.")
              statue.hand_on = false
              MoveObject (hand, statue)
            }
          }
        </look>
      </object>
    </object>
  </object>
</asl>

there's a few ways to do it:

  1. the 'scenery' or 'visible' built-in Boolean Attributes

http://docs.textadventures.co.uk/quest/attributes/scenery.html
http://docs.textadventures.co.uk/quest/attributes/visible.html

within your 'look/watch/examine' Verb, you toggle these Boolean Attributes (using 'visible' for my example below):

<object name="room">
</object>

<object name="player">
  <inherit name="editor_object" />
  <inherit name="editor_player" />
  <attr name="parent" type="object">room</attr>
</object>

<object name="pearl">
</object>

<object name="statue">
  <attr name="parent" type="object">room</attr>
  <attr name="look" type="script">
    msg ("You look at the statue, and particularly take notice of its hand, something is strange about it")
    hand.visible = true
  </attr>
<object>

<object name="hand">
  <attr name="parent" type="object">room</attr>
  <attr name="visible" type="boolean">false</attr>
  <attr name="look" type="script">
    msg ("You look at the hand, noticing it's holding a small pearl, which you take")
    pearl.parent = player
    hand.visible = false
  </attr>
</object>
  1. using the built-in 'parent' Object reference/pointer Attribute:

http://docs.textadventures.co.uk/quest/attributes/parent.html

(having the 'hand' Object not within the room, and moving it within the room, and then back out of the room)

<object name="room">
</object>

<object name="player">
  <inherit name="editor_object" />
  <inherit name="editor_player" />
  <attr name="parent" type="object">room</attr>
</object>

<object name="pearl">
</object>

<object name="statue">
  <attr name="parent" type="object">room</attr>
  <attr name="look" type="script">
    msg ("You look at the statue, and particularly take notice of its hand, something is strange about it")
    hand.parent = room
  </attr>
<object>

<object name="hand">
  <attr name="parent" type="object">null</attr>
  <attr name="visible" type="boolean">false</attr>
  <attr name="look" type="script">
    msg ("You look at the hand, noticing it's holding a small pearl, which you take")
    pearl.parent = player
    hand.parent = null
  </attr>
</object>
  1. having the 'hand' be a Verb, and adding/removing it from the built-in 'displayverbs' or 'inventoryverbs' Stringlist Attributes:

http://docs.textadventures.co.uk/quest/guides/using_lists.html
http://docs.textadventures.co.uk/quest/using_lists.html
http://docs.textadventures.co.uk/quest/attributes/displayverbs.html
http://docs.textadventures.co.uk/quest/attributes/inventoryverbs.html
http://docs.textadventures.co.uk/quest/guides/display_verbs.html

<object name="room">
</object>

<object name="player">
  <inherit name="editor_object" />
  <inherit name="editor_player" />
  <attr name="parent" type="object">room</attr>
</object>

<object name="pearl">
</object>

<object name="statue">
  <attr name="parent" type="object">room</attr>
  <attr name="displayverbs" type="simplestringlist">look</attr>
  <attr name="look" type="script">
    msg ("You look at the statue, and particularly take notice of its hand, something is strange about it")
    list add (statue.displayverbs, "hand")
  </attr>
  <attr name="hand" type="script">
    msg ("You look at the hand, noticing it's holding a small pearl, which you take")
    pearl.parent = player
    list remove (statue.displayverbs, "hand")
  </attr>
<object>
  1. using the 'openable' or 'container_closed' Object Types / Types:

http://docs.textadventures.co.uk/quest/attributes/openable.html
http://docs.textadventures.co.uk/quest/attributes/container_closed.html
http://docs.textadventures.co.uk/quest/elements/object.html (scroll down to the very bottom for the various 'container' Object Types / Types)
http://docs.textadventures.co.uk/quest/attributes/isopen.html

(if you need a code example, let me know --- I'm lazy/tired, so not doing it already lol, unless you let me know you need it)

just to finish it off: you'd close (via the 'statue.isopen=false' built-in Boolean Attribute) the 'statue' container parent Object when done, so you can't see its 'hand' child Object within it


The problem with all the examples is this

-x statue
-Ok, you see a hand

-x something else
-You see something else

-x hand
-I can see the hand

The last part should say "No visible hand" because you're not examining the statue anymore, but you are near something else (x something else).

I was wondering if there's a way to do "if lastcommand == x statue" ?

(Timer solution might work, but it's a bit too complex considering I might want to do this for a lot of objs)


I found this code in libraries (end of post).
Now, how would I add the condition to put the boolean back to true? I'll make an easier example.
There's a sink filled with water. Normally, you can't drink the water or examine or anything: it doesn't exist until you examine the sink. So, to drink the water, you need to examine the sink, and then the water becomes visible. If you do anything else after examining the sink, the water turns back to invisible.

    <![CDATA[
    if (GetBoolean(object, "hidechildren")) {
      object.hidechildren = false
    }
    

I changed most of it. Now it uses a turn script.

NOTE: It will print "You can't see that" if you don't X HAND in the 1 turn following examining the statue.
ANOTHER NOTE: This statue (in my example) is not a container. Its children will be hidden by default.

<object name="statue">
      <inherit name="editor_object" />
      <look type="script">
        msg ("It looks like a statue.")
        if (hand.parent = statue) {
          statue.hand_on = true
          msg ("It has a hand.")
          MoveObjectHere (hand)
          SetTurnTimeout (2) {
            MoveObject (hand, statue)
          }
        }
      </look>
      <object name="hand">
        <inherit name="editor_object" />
        <look type="script">
          msg ("It's a hand.")
        </look>
      </object>
    </object>
    <object name="distraction">
      <inherit name="editor_object" />
    </object>
  </object>

Here's the code for the entire example game:

CLICK HERE TO VIEW THE CODE
<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="tester">
    <gameid>858dcb43-f0d5-4224-8091-79a12850810e</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <description type="script">
    </description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="statue">
      <inherit name="editor_object" />
      <look type="script">
        msg ("It looks like a statue.")
        if (hand.parent = statue) {
          statue.hand_on = true
          msg ("It has a hand.")
          MoveObjectHere (hand)
          SetTurnTimeout (2) {
            MoveObject (hand, statue)
          }
        }
      </look>
      <object name="hand">
        <inherit name="editor_object" />
        <look type="script">
          msg ("It's a hand.")
        </look>
      </object>
    </object>
    <object name="distraction">
      <inherit name="editor_object" />
    </object>
  </object>
</asl>


I was wondering if there's a way to do "if lastcommand == x statue" ?

You'd need to put this line in the game's scripts under EVERY TURN:

(make sure you click 'Enabled when the game begins'!)

player.lastcommand = player.currentcommand

Then, this would be the syntax for the bit you asked about:

if (player.lastcommand = "x statue") {
  msg ("The last command was examining the statue.")
}

Of course, that only works for X STATUE, not examine statue or any of these:

look at #object#; look #object#; x #object#; examine #object#; exam #object#; ex #object#

You'd need an else if for each one, or perhaps a switch, unless you know .NET style Regular Expressions...


So, these two scripts are much less work:

LOOK Script for statue:

msg ("It looks like a statue.")
        if (hand.parent = statue) {
          statue.hand_on = true
          msg ("It has a hand.")
          MoveObjectHere (hand)
          SetTurnTimeout (2) {
            MoveObject (hand, statue)
          }
        }

LOOK script for hand:

msg ("It's a hand.")

Update

I found the EndsWith function.

This adds to the fun:

player.lastcommand = player.currentcommand
if (player.lastcommand = "x statue") {
  msg ("The last command was 'x statue'.")
}
player.lastcommand = player.currentcommand
if (EndsWith (player.lastcommand, "statue")) {
  msg ("The last command ended with 'statue'.")
}

This yields:


> x statue
It looks like a statue.
It has a hand.
The last command was 'x statue'.
The last command ended with 'statue'.

> kill statue
You can't kill it.
The last command ended with 'statue'.

x hand
I can't see that.

> x statue
It looks like a statue.
It has a hand.
The last command was 'x statue'.
The last command ended with 'statue'.

> x hand
It's a hand.


One Regular Expression could probably cover it (I think)...

Perhaps a master of RegEx will help us out.

(I shall research it further. (I've already learned two neat things while playing around with this one!))


Excellent job Richard... it's frightening/depressing how fast you're learning to code... there's some really smart and/or hard-working people out there, like you Richard, sighs.


@ Richard:

ya, the 'String Manipulation Functions', are extremely powerful/useful:

http://docs.textadventures.co.uk/quest/functions/ (go to the 'String Functions' section/part)

StartsWith, EndsWith, Mid, Instr, InstrRev, UCase, LCase, etc etc etc


... it's frightening/depressing how fast you're learning to code ...

I'm just copying & pasting stuff...

The only tricks I've got up my sleeve are the resources this site provides (a LOT of which is provided by HK) and a whole lot of free time!

I do appreciate the kind words, though!

...but, make no mistake: I'm just an anal-retentive researcher. (Plus, at my age, for every seventh thing I learn, I forget one thing I learned before. It's akin to memorizing spells in the Enchanter games.)


Anyway, do you know of an equivalent to if string includes 'statue'? Or is StartsWith and EndsWith the best way to go (without fooling with RegEx)?


there's:

'StartsWith', 'EndsWith', 'Mid', 'Instr', "InstrRev', and etc

the one you want to use is 'Mid' (if I understand it correctly):

http://docs.textadventures.co.uk/quest/functions/string/mid.html

for an example:

string_variable = "Hegemon_Khan_String"

// (1) H (2) e (3) g (4) e (5) m (6) o (7) n (8) _ (9) K

// (1) K (2) h (3) a (4) n

getting_Khan_string_variable = Mid (string_variable, 9, 4)
// getting_Khan_string_variable = "Khan"

and there's lots of other techniques that you can do too, for example:

if (StartsWith (string_variable, "Hegemon_") and EndsWith (string_variable, "_String") {
  getting_Khan_string_variable = Mid (string_variable, LengthOf ("Hegemon_") + 1, LengthOf ("Khan"))
  // getting_Khan_string_variable = "Khan"
}

you can also use the 'Instr' and 'InstrRev' too, but these are just like the 'HasXXX' Functions: if returns '0', then the sub-string is not within the string. Else: you can then use the returned index number (via with/within the 'Mid' Function) for getting the sub-string.

for example:

string_variable = "Hegemon_Khan_String"

integer_variable = Instr (string_variable, "Khan")
if (integer_variable = 0) {
  msg ("the 'Khan' sub-string is not found within the 'Hegemon_Khan_String' string")
} else {
  getting_Khan_string_variable = Mid (string_variable, integer_variable, 4)
}

this probably works with quest:

the manual way: iterating through the string:

(I had to think of how the 'Mid/Instr/InstrRev' Functions are done underneath on my own, lol ... so probably a better way of doing it: see the 'Mid/Instr/InstrRev' Function's scripting, lol, meh)

string_variable = "H;e;g;e;m;o;n;_;K;h;a;n;_;S;t;r;i;n;g"

stringlist_variable = split (string_variable, ";")

sub_string_variable = ""

index_integer_variable = 0

terminator_boolean_variable = false

while (not terminator_boolean_variable and index_integer_variable + 3 < ListCount (stringlist_variable)) {
  for (current_index_integer_variable, index_integer_variable, index_integer_variable + 3, 1) {
    sub_string_variable = sub_string_variable + StringListItem (stringlist_variable, current_index_integer_variable)
  }
  if (sub_string_variable = "Khan") {
    terminator_boolean_variable = true
    game.sub_string_attribute = sub_string_variable
  } else {
    sub_string_variable = ""
    index_integer_variable = index_integer_variable + 1
  }
}
if (not terminator_boolean_variable) {
  msg ("The 'Khan' sub-string was not found in the 'Hegemon_Khan_String' string")
}

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

Support

Forums