Problem with Visited attribute

This is a discussion / support forum for the Hugo programming language by Kent Tessman. Hugo is a powerful programming language for making text games / interactive fiction with multimedia support.

Hugo download links: https://www.generalcoffee.com/hugo
Roody Yogurt's Hugo Blog: https://notdeadhugo.blogspot.com
The Hugor interpreter by RealNC: http://ifwiki.org/index.php/Hugor

Moderators: Ice Cream Jonsey, joltcountry

User avatar
Tdarcos
Posts: 9341
Joined: Fri May 16, 2008 9:25 am
Location: Arlington, Virginia
Contact:

Problem with Visited attribute

Post by Tdarcos »

I have a refrigerator in the kitchen. I want to show a message the first time the user issues the command "open refrigerator" (or "open fridge" or "open icebox"), and a different item thereafter, so in either the before event or the after event of the refrigerator object I have the following:

Code: Select all

object DoOpen
	    {
		if (self is not visited)
			{
				print "The refrigerator apparently hasn't been cleaned since Enron 
				was in business.  A number of items inside look like they're some sort
				of science experiment. The green cottage cheese apparently has
				become sentient, as it says to you, \"Hey, close the door, you're
				letting all the cold out!\"  You hastily close the door."
				self is not open
				self is visited
				return true
			} else {
				print "The green cottage cheese looks at you again, and says 
				\"Don't you listen? I told you to close the door, you're letting all 
				the cold out!  Leave it closed, there's nothing you want in 
				here.\"  Something else grabs the door and closes it, doing 
				something that sounds suspiciously like a bolt being thrown."
				self is not open
				self is locked
				return true
			}
		}
If placed in the "before" event, this works to show the phrases correctly, but for some reason the door isn't locked. If placed in the "after" event, it apparently sets "visited" before this is even called so the first message never gets seen. (I discovered I have to set the visited attribute when its in the before event or that attribute doesn't get set.) Maybe I need to return false instead of true, I never did understand which return means which.

I looked through the DoOpen routine and I can't see where the visited attribute is set before the "after" code is called, and i don't see why I can't set the locked attribute in the "before" event.
"I really feel that I'm losin' my best friend
I can't believe this could be the end."
- No Doubt, Don't Speak

User avatar
Tdarcos
Posts: 9341
Joined: Fri May 16, 2008 9:25 am
Location: Arlington, Virginia
Contact:

Post by Tdarcos »

Okay, so I try splitting them

Code: Select all

	before
	{
 		object DoOpen
	    {
		if (self is not visited)
			{
				print "The refrigerator apparently hasn't been cleaned since Enron was 
				in business.  A number of items inside look like they're some sort of 
				science experiment. The green cottage cheese apparently has become 
				sentient, as it says to you, \"Hey, close the door, you're letting all 
				the cold out!\"  You hastily close the door."
				self is not open
				self is visited
				return true
			} 
		}
	}
	
	after
	{
		object DoOpen
		{
			if self is not visited
			{
				print "after-self not visited"
			} else {
				print "The green cottage cheese looks at you again, and says 
					\"Don't you listen? I told you to close the door, you're letting all 
					the cold out!  Leave it closed, there's nothing you want in 
					here.\"  Something else grabs the door and closes it, doing something that
					sounds suspiciously like a bolt being thrown."
					self is not open
					self is locked
					return true
			}
		}



	}
Now, once the fridge is opened then the 'after' event never gets called at all. Apparently I can have a before event, or an after event, but not both.

So I can't seem to get this to work. Now, I can create my own attribute separate from visited and it works just fine - in the 'after' event - but I just wonder why I can't use 'visited' and why 'locked' won't stick in 'before'.
"I really feel that I'm losin' my best friend
I can't believe this could be the end."
- No Doubt, Don't Speak

User avatar
Tdarcos
Posts: 9341
Joined: Fri May 16, 2008 9:25 am
Location: Arlington, Virginia
Contact:

Post by Tdarcos »

This, works perfectly:

Code: Select all

attribute BeenHere
...

object fridge "refrigerator"
{
...

	after
	{
		object DoOpen
		{
			if self is not BeenHere
			{
				print "The refrigerator apparently hasn't been cleaned since Enron was 
				in business.  A number of items inside look like they're some sort of 
				science experiment. The green cottage cheese apparently has become 
				sentient, as it says to you, \"Hey, close the door, you're letting all 
				the cold out!\"  You hastily close the door."
				self is not open
				self is BeenHere
				return true

			} else {
				print "The green cottage cheese looks at you again, and says 
					\"Don't you listen? I told you to close the door, you're letting all 
					the cold out!  Leave it closed, there's nothing you want in 
					here.\"  Something else grabs the door and closes it, doing something that
					sounds suspiciously like a bolt being thrown."
					self is not open
					self is locked
					return true
			}
		}

		object DoUnlock
		{
			if self is visited
			{
				print "The residents of the refrigerator will not allow the lock to be released."
				self is locked
				return true
			}	
		}
    }
...
}
But if I change if self is not beenhere to if self is not visited in the above, then the first time condition is not executed.

Note that the "unlock" code - I only want the residents to fight to keep the door closed and locked after it's been opened - works fine using the visited attribute. The user can lock or unlock the refrigerator as long as it's never been visited, so we're fine there.
"I really feel that I'm losin' my best friend
I can't believe this could be the end."
- No Doubt, Don't Speak

Bainespal
Posts: 151
Joined: Fri Jul 09, 2010 8:59 am

Post by Bainespal »

Tdarcos wrote:If placed in the "before" event, this works to show the phrases correctly, but for some reason the door isn't locked.
I think your door actually does get locked in your code from your first post, but you don't know that it's been locked because the before property gets called even before the library checks to see whether door is locked.
Tdarcos wrote:Now, once the fridge is opened then the 'after' event never gets called at all.
Hmm. Your after event is for DoOpen as well.

I've had a lot of confusion about what is checked for or not checked for in before properties, so this is just a hunch. Roody or someone might be able to give you a definitive answer, but here's my take:

I believe that once the fridge is open, trying to open again will by default fail, meaning that it returns somewhere in the deafault library code. The door can't be opened when it's already opened. Therefore, the action never passes to the "after" layer.
Tdarcos wrote:Apparently I can have a before event, or an after event, but not both.
I'm pretty sure you can have both, but if you want both to be called in the same turn, for the same action, then you have to explicitly return false in the before property in order to pass to after.
Tdarcos wrote:Now, I can create my own attribute separate from visited and it works just fine - in the 'after' event - but I just wonder why I can't use 'visited' and why 'locked' won't stick in 'before'.
Well, 'visited' is used by the Library differently from how you're using it here, in order to keep track of which rooms the player character has been to. The Library assigns lots of attribute aliases, so even though your refrigerator is not a room, it's possible that the Library could be using an alias of 'visited' on it. Whether or not that is the case, it's far safer just to use your own attribute, or else to use the generic attribute 'special' that is specifically for us to use for whatever states we want to keep track of.

Setting 'locked' should be perfectly safe and reasonable, however, since you're not using it in a way that contradicts the Library. After your 'after' event is run and the 'locked' attribute therefore applied, do you get the response for 'before' or 'after' when you try opening the fridge again? I think your problem may be that 'before' doesn't check to see if the door is locked.
Tdarcos wrote:But if I change if self is not beenhere to if self is not visited in the above, then the first time condition is not executed.
I think you're far better off with 'beenhere'.

Roody_Yogurt
Posts: 2180
Joined: Mon Apr 29, 2002 6:23 pm
Location: Milwaukee

Post by Roody_Yogurt »

visited is an alias to moved (http://hugo.gerynarsabode.org/index.php?title=Moved), so the mere act of opening it is giving it the attribute you are checking for.

Since, in the end, you aren't actually even allowing the open command to work, you could move that code to a before property instead. That way, visited/alias wouldn't get set before you wanted it, and you won't have to close the object by hand.

Post Reply