Need Help With Attributes.

Hello,

Brand new to Quest. Can't quite figure out how to use Custom Attributes. I have the tutorial and have tried to follow it. I don't use the examples - I make my own to be sure I understand.

The tutorial gives the example of eggs. You create the object "Eggs," you give it an attribute of "weight," and then you type ""A box of eggs, weighing " + eggs.weight + " grams." OK. Except WHERE do I type that??

Instead of eggs, I created a Waste Basket. Gave it an attribute of "Full," and set it to "True." Went to "Setup" page and description changed "Text" to "Script." Below that, it says "Print" and next to that a little gray box says "Message" with a down arrow. So in the box I typed ""Waste Basket is " + Full + "."

As I understood the Eggs example, that should say "Waste Basket is full" when User looks at it. Instead I get this:

Error running script: Error compiling expression 'game.pov.parent = ': SyntaxError: Unexpected end of fileLine: 1, Column: 35```

Appreciate any help pointing me in right direction.

That error sounds like your game file is corrupted to me. The error doesn't seem to relate to the script you're talking about.

Could you try sharing the game so we can take a look and work out what's wrong?

Also, "Waste Basket is " + Full + "." probably won't work, unless Full is the name of an object.
I suspect you want either "Waste Basket is " + wastebasket.Full + "." (making sure you use the exact name of the object) or "Waste Basket is " + this.Full + "." (using this, which is an easier way of specifying "the object that has this script")

However, these options will display a message like "Waste basket is true." which probably isn't what you want.

If you leave the print type set to "Message" (or the look-at type set to "Text") you can use text processor directives, which might be easier in this case. You could put something like:

Waste basket is {either wastebasket.Full:full:empty}.

either is the quickest way to turn true/false into two pieces of text you specify. The syntax is

{either object name.attribute name:text if true:text if false}

That needs to go inside a text string; so you specify "message" within a print command, or "text" for an object/room description.


Thank you for responding. I would love to post my game here and have the experts steer me in the right direction. But I don't know how. Sent a message to the UpLoad feature asking if I could upload game there. Don't want to upload it if that is reserved for finished games. Is there a way to post game here, in a regular post?? I have no clue.


Plenty of stuff is uploaded here, just be sure to let everyone know it's a work in progress.


If you're using the desktop Quest editor, you could put the aslx file on dropbox or somewhere, and post a link here. (The downside of this method is that people who don't have the desktop editor won't be able to play it, only look at the code)

Or you could publish the game and choose to make it unlisted ("Only people I give the link to"), and post the link in the forum. (the downside of this method is that the published game includes a load of extra code, so it can be harder to find problems)


Make sure to use https in your link, not http. Only that works for some reason.


Thanks for your replies. I did upload my game. But now it doesn't seem to be there. I figure there are two possibilities.

  1. I'm too dumb to find it.

  2. It's such a pathetic little fragment that a Moderator (Or someone) deleted it.

Well, I will try again.


OK, I created a Drop Box account. Apparently it's free for thirty days. I have no idea how it works. I hope you guys are able to access my game from here and tell me what I need to do to create and use Attributes.

https://www.dropbox.com/s/i4xhz87k09e9kn2/Prac%20I.quest?dl=0

Thanks.


OK, your look script for the wast basket is:

        msg ("\"Waste Basket is \" + Full + \".\"")
        if (game.pov.parent = ) {
        }

Now, when you play the game, you get two messages. One for each of those lines.

When asking for help, you showed us only the first line of your script, and the second line of the game's output.

First line

   msg ("\"Waste Basket is \" + Full + \".\"")

This gives the output:

"Waste Basket is " + Full + "."

I suspect that in the GUI editor, you have selected "Message" (which prints exactly what you entered), rather than "Expression" (which lets you enter a Quest expression to determine what to print).

After changing the parameter type to "Expression", you will also need to refer to the variable by its correct name, as I explained in my previous post.

It also seems like your 'Full' attribute contains the string True.
So if you change the code to use an expression:

msg ("Waste Basket is " + Waste Basket.Full + ".")

it will give you the output:

Waste Basket is True.

Second line:

 if (game.pov.parent = ) {

This line doesn't mean anything. You seem to be comparing game.pov.parent (the current room) to nothing.
This explains the error message you quoted in your post.

I don't know what you intended to do with this line, but an unfinished line of code will only cause problems. You need to either fix it, or remove it, so you can get rid of the error message.

I hope that helps some.


But this line: "if (game.pov.parent = ) {"

I have no clue where that came from. I certainly didn't type it and I can't find it in the Quest game-create tool. All I can see is the first line. I can't delete that line if I don't know where it is.

Maybe I'm a lost cause.


Well, my post above left off the first part. I said I did change parameter to Expression, and it did change the output. Don't know why it got left off.


You'll need to look in code view to remove the extra lines. I'm assuming the GUI editor can't display it because it's not valid code.


OK, thanks. Actually, I didn't know Code View Existed. I erased that extra line. (Still no idea why it appeared.)

Now I will try again. I have a Waste Basket. I want to give it a "Full" attribute. When Players looks at it, I want game to say, "Waste Basket is full" if "Full" is set to True or "Waste Basket is empty" if "Full" is set to False.


Here is how you use attributes.
https://imgur.com/o9X6rbc
https://imgur.com/c27Gkvf

Here is the code.
First, you do this.

Wastebasket.full = false

Then, you do this when you want the waste basket to be full.

Wastebasket.full = true

The code to check it should look something like this.

if (Wastebasket.full = true) {
  msg ("The waste basket is full.")
}
else {
  msg ("The waste basket is not full yet.")
}

You can create a waste basket. You can then create a counter, and each time the basket is used, the counter can go up by one, until the basket is "full."


OK, thanks. I will check out your links.


Still can't get my "full" attribute to work. The error message is different. Maybe that's progress.

One problem is, I'm not sure WHERE to type the code you give. Went to SetUp tab for Waste Basket. Changed "Look at" description to Script. Changed "Print" to expression. In the box to the right of that, I typed, if (Waste Basket.Full = true) {msg ("It's full.") }

But when I run the program, I get

Error running script: Error compiling expression 'if (Waste Basket.Full = true) {msg ("It's full.") }': CompareElement: Operation 'Equal' is not defined for types 'String' and 'Boolean'

You guys have been patient with me. I'm sure I'll figure this out.


This code:

if (Waste Basket.full = true) {
  msg ("The waste basket is full.")
}

is a script, not an expression. You need to enter it in code view.
The equivalent in the GUI will look like this:
Screenshot 1

However, this is also bad practice.
More sensible code would be something like:

if (Waste Basket.full) {
  msg ("The waste basket is full.")
}

(which is slightly more efficient, but doesn't look so neat in GUI view)
Screenshot 2

OR the preferred way to check boolean attributes:

if (GetBoolean (Waste Basket, "full")) {
  msg ("The waste basket is full.")
}
Screenshot 3

However, in a case like this, it is so much easier to use the text processor. if statements are good for controlling the flow of text, but if you just want to change the text, you don't even need a script. You can just do:

msg ("The waste basket is {either Waste Basket.full:full:empty}.")
Screenshot 4 which is similar to what the tutorial advises. Or you could decide not to run a script at all: Screenshot 5

Since I'm obviously never going to figure out attributes, I decided to start at the beginning of the tutorial and go through it carefully. I learned things I had missed the first time around. Now I'm on the Custom Commands' page. Was doing fine till I got toAdditional Example (Advanced.)' Have tried to follow Tutorial exactly.

Command is `say.' In Command pattern box, I have say #text_talk# to #object_one#

Then I made a `switch' script. In the switch box, I put object_one.

In the `cases' box I have Bob under Key column and
Print "You say " + text_talk / Print "Bob pays no attention." in the column to the right. That is exactly the form used in the Tutorial. But now I get ...

You say "hi", but no answer.
Error running script: Error compiling expression '"You say " + text_talk / Print "Bob pays no attention"': Unknown object or variable 'Print'

Any ideas??


I think you've mixed two commands together.

The command "Print" in the GUI is actually called msg in code view. So your code should look like:

msg ("You say " + text_talk)
msg ("Bob pays no attention.")
Screenshot of GUI view

or if you want the responses to be a single line, it would be a single command:

msg ("You say " + text_talk + "Bob pays no attention.")
Screenshot of GUI view

https://docs.textadventures.co.uk/quest/tutorial/custom_commands.html#additional-example-advanced

image


I think this is the screenshot that caused the confusion.

In code view, that looks like this:

switch (object_one) {
  case (troll) {
    msg ("You say " + text_talk)
    msg ("The troll grunts, but otherwise ignores you.")
  }
  case (bob) {
    msg ("You say " + text_talk)
    msg ("Bob smiles back at you.")
  }
}

I can see how that screenshot could confuse a new Quest user.


Aw right! Mr. Angel's idea works.

msg ("You say " + text_talk + "Bob pays no attention.") Actually I omitted the word `msg' and the parentheses; simply added plus sign to what I had before. Works exactly as I wanted. Well ... Almost. There is one thing:

I say Hi to the couch, and I get `You say "hi", but no answer.' And that's perfect. Problem is, I also get that when I say Hi to Bob.

You say "hi", but no answer.
You say hi. Bob pays no attention

Shouldn't the game leave out the first line?? Is there a way to make program omit the generic response if Player is talking to a character/object who will give a specific response??


Actually I omitted the word `msg' and the parentheses

The "msg" appears as "Print" in the GUI. You entered it by choosing the command rather than typing it in.

I think this is the screenshot that caused the confusion.

Oh, I didn't know that… the 'switch' command looks completely different in the desktop and web editors. That's a bizarre design choice, and I have no idea why it's been done like that.


Shouldn't the game leave out the first line??

It would make sense. But where is the first line in your code?

Quest just does what you tell it. So, for example, if your code looks like:

msg ("You say \"" + text_talk + "\", but no answer.")
switch (object_one) {
  case (bob) {
    msg ("You say " + text_talk + ". Bob pays no attention.")
  }
}

It will do the things in order. First it prints the first message; then if the person is bob, it prints the second message.

If you want it to only do the first message as a default, if it doesn't do any of the others, it would be:

switch (object_one) {
  case (bob) {
    msg ("You say " + text_talk + ". Bob pays no attention.")
  }
  default {
    msg ("You say \"" + text_talk + "\", but no answer.")
  }
}

(There should be a 'code view' button that lets you view the code for the whole script. Even if you don't understand code yet, this lets you copy and paste the code so it's easier to show us what you're doing. It also means you can paste in the code that someone else has given you, and then switch back to the GUI view to see what it looks like there. Apparently I can't share helpful screenshots because I'm using the online version of Quest, and some stuff looks very different)


Have made progress! Ready to move on to next section of tutorial. There's just one little nagging item.

If I type Say Hello with no `To' clause; that is if I don't specify the person to whom I'm speaking, I get

"I don't understand your command."

On the page where we type the commands, there's a box that says, "Unresolved object text." And in the picture in the tutorial, that field is filled with `Say it to who?' But apparently this part of the command doesn't kick in.

Shouldn't there be some sort of mechanism so the Player can type "Hello" to the world in general?? Or maybe there should be two `Say' commands?? One that requires an object and one that doesn't??

Well, it's a small matter and I'm eager to move on.


On the page where we type the commands, there's a box that says, "Unresolved object text." And in the picture in the tutorial, that field is filled with `Say it to who?' But apparently this part of the command doesn't kick in.

When interpreting a command, Quest compares what the player entered to the pattern. So with a pattern like say #text# to #object#, the command will be selected every time the player enters something that starts with "say" and has a "to" in the middle.

Once it already knows what #text# is, and what part of the player's input matches #object# it will compare the #object# text to the aliases of all objects the player can see. If none of them matches, the "unresolved object" text appears.

Basically, this appears if the player types "say hello to john" when there isn't anybody called John in the room.

If you want to allow just "say hello", you would need to change the pattern.
You could make a second command, whose pattern is just say #text# - this one will only run if there is no "to" in what the player typed, so you can just make it print out "Who do you want to say it to?" or "Talking to yourself doesn't make you feel any better."

Alternatively, you could give your command a pattern like say #text_talk# to #object_one#;say #text_talk# (I think that works) and then make the script something like:

if (IsDefined(object_one)) {
  // put your existing code here
}
else {
  msg ("Who do you want to talk to?")
}

Thanks. I did make a second "say" command and it does what I want.


Have got to Section 8 of Tutorial, titled, "More things to do with objects." Flags seem like a really handy tool, and I think I've figured out how to use them. Um ... Somewhat.

It's not clear exactly how to change them. Tutorial gives the example of using a defibrillator on Bob, and I got that to work. Resurrect Bob from dead to alive. But then tutorial goes on to discuss Functions, and I'm kinda lost there. Will go over material again and maybe I'll figure it out.

But what I really wanna ask about is this quote from Tutorial: "It is good practice to give flags meaningful names, and to have them start off (or false)."

If I decide to rebel and have a flag start off True, how can I do that?? And can I arbitrarily change the flag at a later time??


In scripts, is there anything equivalent to "And??" Going through the Tutorial. Have got defibrillator to work on Bob by typing either "Use defibrillator" or "Use defibrillator on Bob." Tutorial suggests adding an "If" command to make sure Player is in same rom as Bob. But I just can't figure that out. Is there anyway to use two conditions in the same If clause?? "If Bob is in same room AND Bob is not moving ..."

Alternatively, is there something equivalent to "Exit Function??" So if first condition (Same room as Bob) is not met, program leaves and does not run following commands in that function??

Thank you.


OK, I think the problem I'm having with scripts is that the "If" command doesn't work. At least it doesn't work properly for me. I added a verb, "Break" to eggs. Want Player to be able to break eggs if he's in same room as eggs, but not if he's in a different location. Didn't use Code View, but this is what I see in Code view:

        if (game.pov.parent = eggs) {
          msg ("You scramble a few eggs.")
        }
        else {
          msg ("You must be in same room as eggs.")
        } 

My condition has changed from "Player In Room" to "game.pov.parent=eggs." Is it supposed to do that?? What does game.pov,parent mean?? Anyway, it says, "Must be in same room" even when I AM in same room.

Any ideas??
Thank you.


game.pov.parent is an expression that means "the room the player is in". game.pov means "the player", and .parent finds the room something is in.

So you're testing if the player is in a room named eggs.

If you want to check if the player is in the same room as an eggs object, you would want that line to be:

if (game.pov.parent = eggs.parent) {

or:

if (Contains (game.pov.parent, eggs)) {

(which will also be true if the eggs are inside something that's in the room; like the player's inventory)
or:

if (ListContains (ScopeReachable(), eggs)) {

(which tests if eggs are in ScopeReachable(), a list of objects the player can reach)

but you probanly don't need to do this. The player can only use verbs on objects they can see. So if this script is a verb on the eggs, it won't run at all when they're in a different room.


I created a Drop Box account. And I don't look in vain.


Thanks, Mr. Angel. I am making progress. The tutorial is unclear on "game.pov.parent." But thanks to you, I was able to get the defibrillator working correctly and not working when I'm not in the room with Bob.

Still have a ways to go though. Started this thread because I was frustrated I couldn't create a waste basket and make it behave the way I wanted. Still frustrated; maybe I'm biting off more than I can chew. Want to be able to do all these actions:

  1. Examine waste basket and tell if it's empty or full. This one can do.
  2. It's it's empty, put stuff in it, thus making it full.
  3. If it's full, get told I can't put any more into it.
  4. Empty it.
  5. Get told it's empty if I try to empty it while it's empty.

Will keep plugging away. Still think there must be a way to check for two conditions at once. "IF Bob is not moving AND Player is in same room THEN he can use defibrillator."


Still think there must be a way to check for two conditions at once. "IF Bob is not moving AND Player is in same room THEN he can use defibrillator."

There is an and operator (as well as or and not).

If you take any boolean expression (one that you could put between brackets of an if statement in code view), you can join 2 expressions together with and.

For example (I don't know what attributes you're using to indicate that Bob isn't moving; I'm sure you can replace my example with the check you want):

if (Contains (game.pov.parent, Bob) and GetBoolean (Bob, "stopped_moving")) {
  // Do something
}

However, in most cases you would want to break the conditions down to something like:

if (Contains (game.pov.parent, Bob)) {
  if (GetBoolean (Bob, "stopped_moving")) {
    // code to shock Bob goes here
  }
  else {
    msg ("Bob backs away. He probably doesn't need a shock right now.")
  }
}
else {
  msg ("Bob isn't here.")
}

Because in a lot of cases where you might use and, you'll want to display a different message depending which one isn't true.
An alternative way to arrange this (so that it's easier to see which if goes with which message) is to invert the conditions like this:

if (not Contains (game.pov.parent, Bob)) {
  msg ("Bob isn't here.")
}
else if (not GetBoolean (Bob, "stopped_moving")) {
  msg ("Bob backs away. He probably doesn't need a shock right now.")
}
else {
  // neither problem applies, so code to shock him goes here
}

Thanks, Mr. Angel. Appreciate your taking time to work with me.


Still plugging away on my attempt to create a waste basket. Learning a bit (A LITTLE bit) about Code View.

Can put stuff in the waste basket if it's empty, but not if it's full. That's what I want, but I end up with an extra word in the output. Here's the code:

        if (GetBoolean(waste basket, "full")) {
          msg ("The waste basket is full. You cannot possibly stuff anything else into it.")
        }
        else {
          msg ("OK, you put the " + object + " into the waste basket.")
          SetObjectFlagOn (waste basket, "full")
        }

When I play the game, I get:

OK, you put the Object: key into the waste basket.

How do I get that word, "Object" out of there??


The + operator can either be used to add two numbers together, or to join two strings together.

You're using it on "OK, you put the " (which is a string) and object (which is an object).

When you treat an object as a string, it might be automatically converted into a string. This turns it into a string that looks like "Object: key".

You probably want to convert the name to a string yourself, using a function like GetDisplayAlias.

For example:

        if (GetBoolean(waste basket, "full")) {
          msg ("The waste basket is full. You cannot possibly stuff anything else into it.")
        }
        else {
          msg ("OK, you put the " + GetDisplayAlias (object) + " into the waste basket.")
          SetObjectFlagOn (waste basket, "full")
        }

GetDisplayAlias (object) gives you a string which contains the object's alias attribute if it has one, and its name otherwise. This is how almost all of Quest's built-in functions display an object.

An alternative would be GetDisplayName, which will generate a link if the object is visible.


Your suggestion worked perfectly, Mr. Angel. Now, I hate to be a pest, but I CANNOT get waste basket to behave as it should. My immediate problem is that when I put something into the waste basket, it stays in my inventory. When I type `I' there it still is.

Well, I thought I could fix this by studying the refrigerator in Code View. You put stuff in refrigerator, you don't have it anymore and it stays in refrigerator. But I can't find the code for that in Code View. (Or maybe I can find it but don't recognize it.)

My next idea was to move the object to the waste basket. And that works IF you have only one object to move AND it happens to be the one you put in the waste basket. In the code below, I move the key to the waste basket. If I do indeed put the key into the waste basket, the code works perfectly. Unfortunately, if I put something else into the waste basket, the key goes into it.

I type "Put flour in waste basket," and then "Examine waste basket," and there's the key.

So how can I make the waste basket accept whatever object I put into it and simultaneously remove that object from my inventory??

      <inherit name="editor_object" />
      <inherit name="container_open" />
      <take />
      <alt type="stringlist">
        <value>wb</value>
      </alt>
      <feature_container />
      <close type="boolean">false</close>
      <listchildren />
      <open type="boolean">false</open>
      <transparent type="boolean">false</transparent>
      <look type="script">
        if (GetBoolean(waste basket, "full")) {
          msg ("The waste basket is overflowing with putrid offal and trash.")
        }
        else {
          msg ("A normal, plastic waste basket, eighteen (or so) inches tall. It is currently empty.")
        }
      </look>
      <ontake type="script">
        msg ("You are now holding the waste basket. Big whoop.")
      </ontake>
      <addscript type="script">
        if (GetBoolean(waste basket, "full")) {
          msg ("The waste basket is full. You cannot possibly stuff anything else into it.")
        }
        else {
          msg ("OK, you put the " + GetDisplayAlias (object) + " into the waste basket.")
          SetObjectFlagOn (waste basket, "full")
          MoveObject (key, waste basket)
        }
      </addscript>
    </object>
  </object>

Log in to post a reply.

Support

Forums