FAQ Search Memberlist Usergroups
Jolt Country Forum Index
Register Profile Log in to check your private messages Log in
Log in Log in

Recursion problem

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Jolt Country Forum Index -> Hugo's House of Horrors
View previous topic :: View next topic  
Author Message
Bainespal



Joined: 09 Jul 2010
Posts: 151

PostPosted: Wed Sep 28, 2011 3:39 pm    Post subject: Recursion problem Reply with quote

There's an object in my game that needs to be listened to. I implemented this in the before property of the object with "object DoListen", and that works right. However, I want the simple command "LISTEN" to have the same affect only after the aforementioned object has been moved into the room where this scene is happening (and the object representing the sound to be listened to is not present when the player first enters the room).

I thought this would be a simple matter of blocking "location DoListen" from the room object's before property and telling it to "Perform" the Listen command on the sound object if that object is in the location. When I tried this, the Hugo Engine crashed. I think I know why -- the "location DoListen" rule runs the "DoListen" verbroutine through the Perform() routine, which is caught again by the same "location DoListen" rule. So I have a problem with recursion.

I almost corrected this problem using PreParse (in the player object's before property). The right code is triggered, advancing the game state in the way that I want, but then the default response for an empty "LISTEN" command is printed after my response for listening to the correct object ("Be a little more specific about exactly what you'd like to listen to.")

I don't know how to suppress the library message here. I'll copy my PreParse code below, but I think this code is pretty workable.

Code:
actor PreParse
    {
      if (word[1] = "listen") and Contains (crypt, player)
      {
        if voices in crypt
        {
          Perform(&DoListen, voices)
        }
        else
        {
          return false
        }
      }
      else
      {
        return false
      }
}


Thank you.
Back to top
View user's profile Send private message
Tdarcos



Joined: 16 May 2008
Posts: 4441
Location: University Park, Maryland

PostPosted: Wed Sep 28, 2011 4:39 pm    Post subject: Re: Recursion problem Reply with quote

Bainespal wrote:
There's an object in my game that needs to be listened to. I implemented this in the before property of the object with "object DoListen", and that works right. However, I want the simple command "LISTEN" to have the same affect only after the aforementioned object has been moved into the room where this scene is happening (and the object representing the sound to be listened to is not present when the player first enters the room).

I thought this would be a simple matter of blocking "location DoListen" from the room object's before property and telling it to "Perform" the Listen command on the sound object if that object is in the location. When I tried this, the Hugo Engine crashed. I think I know why -- the "location DoListen" rule runs the "DoListen" verbroutine through the Perform() routine, which is caught again by the same "location DoListen" rule. So I have a problem with recursion.

I almost corrected this problem using PreParse (in the player object's before property). The right code is triggered, advancing the game state in the way that I want, but then the default response for an empty "LISTEN" command is printed after my response for listening to the correct object ("Be a little more specific about exactly what you'd like to listen to.")

I don't know how to suppress the library message here. I'll copy my PreParse code below, but I think this code is pretty workable.

Code:
actor PreParse
    {
      if (word[1] = "listen") and Contains (crypt, player)
      {
        if voices in crypt
        {
          Perform(&DoListen, voices)
        }
        else
        {
          return false
        }
      }
      else
      {
        return false
      }
}


Thank you.


Hint. Don't return false. This fails the command. What you might do is set up your own fail for the word listen in the verb section, or have two versions of the verb table, something like this (just off the top of my head, not necessarily right):

Verb "listen"
* DoBlankListen
* object DoListen

So that a "naked" listen goes to one routine, a listen followed by an object goes to the processor. Then you can handle the naked listen as you choose, and handle "listen mailbox" separately.
_________________
The lessons of history teach us - if they teach us anything - that no one learns the lessons of history.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Bainespal



Joined: 09 Jul 2010
Posts: 151

PostPosted: Wed Sep 28, 2011 4:42 pm    Post subject: Reply with quote

I have a little more information.

First of all, I've now tried putting a "return true" beneath "Perform(&DoListen, voices)" in the code above, but there's no noticeable change.

It seems like two LISTEN commands are being triggered for some reason. I suspect the default response when I type "LISTEN" by itself is the result of a second command. When I type "LISTEN TO VOICES", I get my own response twice (and no default response).

Finally, the "AGAIN" command makes another little annoying problem, since the intercepted "LISTEN" command isn't registered as the last command. Is there a variable I can set to make the Engine know what I want the previous verbroutine and object to be, so "AGAIN"/"G" will work right?
Back to top
View user's profile Send private message
Bainespal



Joined: 09 Jul 2010
Posts: 151

PostPosted: Wed Sep 28, 2011 5:24 pm    Post subject: Reply with quote

Tdarcos wrote:
Hint. Don't return false. This fails the command. What you might do is set up your own fail for the word listen in the verb section, or have two versions of the verb table, something like this (just off the top of my head, not necessarily right):

Verb "listen"
* DoBlankListen
* object DoListen

So that a "naked" listen goes to one routine, a listen followed by an object goes to the processor. Then you can handle the naked listen as you choose, and handle "listen mailbox" separately.

Oh, I didn't see your reply. You must have been writing it at the same time I was composing my own follow-up post. Thank you! :)

I think I understand what you're saying. In the thread I started about using a LookIn command on a window object, Roody pointed out that I could use a special verb token just for that one object. So, what I will try in this case when I'm on my laptop again will look something like this:

Code:

verb "listen"
* voices DoListenVoices


I'll tell you if it works.
Back to top
View user's profile Send private message
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Wed Sep 28, 2011 6:46 pm    Post subject: Reply with quote

Hugo's default DoListen routine isn't designed with both object and room noises in mind (just typing >LISTEN asks you to specify what you want to listen to). I did not like this, either, so I wrote a replacement DoListen routine some months ago: http://hugo.gerynarsabode.org/index.php?title=Replace_DoListen

To save you the time clicking on that:
Code:

replace DoListen
{
   if not object
      {
         if &location.after
            return true
         else
            {
            VMessage(&DoListen, 1)  ! "Be a little more specific..."
            return false
            }
      }
   elseif not object.after
      VMessage(&DoListen, 2)   ! "Not making any sound..."
   ! we have to clear verbroutine or else location.after.DoListen will run again
   verbroutine = ""
   return true
}


If you have that, you could have a room like this:
Code:

room the_important_room "The Room Where You Listen"
{
after
        {
        location DoListen
                    {
                    if FindObject(voices,location)
                          Perform(&DoListen,voices)
                    else
                          return false
                    }
         }
}

This code is untested, but it should work! Let me know!

Also, I didn't read this thread too closely so I may have missed an important detail.
Back to top
View user's profile Send private message AIM Address
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Wed Sep 28, 2011 6:55 pm    Post subject: Reply with quote

Ok, reading back, Tdarcos is also right. Another reasonable way to handle it is to split Listen into two verb routines like he suggested.
Back to top
View user's profile Send private message AIM Address
Roody_Yogurt



Joined: 29 Apr 2002
Posts: 1993
Location: Milwaukee

PostPosted: Thu Sep 29, 2011 12:30 am    Post subject: Reply with quote

Lastly, if you look at that replacement DoListen routine (or the original), you'll notice that it's one of those verb routines that work off an after routine, so like that room object example up above, you'd want your voices object to have something like:
Code:

object voices "voices"
{
noun "voices"
article "the"
after
      {
      object DoListen
             {
              ! Listening code and responses
             }
       }
}


Having it be a before routine would probably work the same (I can't think of any situations where it'd break something), so it's really just a matter of putting things where the code expects them to be.
Back to top
View user's profile Send private message AIM Address
Tdarcos



Joined: 16 May 2008
Posts: 4441
Location: University Park, Maryland

PostPosted: Thu Sep 29, 2011 7:56 am    Post subject: Reply with quote

Roody_Yogurt wrote:
Ok, reading back, Tdarcos is also right. Another reasonable way to handle it is to split Listen into two verb routines like he suggested.


I'm glad to see that 34 years of programming in twelve different programming languages transfers to ones I'm new at. Some people have the knack that they can really do this stuff fantastically. I have my own heroes of people I knew when I was younger who were wizards then.
_________________
The lessons of history teach us - if they teach us anything - that no one learns the lessons of history.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Bainespal



Joined: 09 Jul 2010
Posts: 151

PostPosted: Thu Sep 29, 2011 6:03 pm    Post subject: Reply with quote

Now that it's been mentioned, I do feel that the library's treatment of the command to listen is inadequate -- it should definitely provide for just listening in a room. I think I noticed this a while ago, but I forgot.

That replacement for DoListen looks elegant and comprehensive, but I went with two verb routines instead because I think that approach is more compatible with my existing code. Instead of just making a verb token for the command of listening specifically to the one object like I said I would do, I added a general verb token for "listen" with no other words and assigned it to a routine called DoListenVague. I was pleasantly surprised when the game gave precedence to the new DoListenVague over the library's DoListen when I just typed the command "LISTEN." It was a simple matter to block DoListenVague from the before property of the room object and have the Perform routine trigger DoListen(voices).

So, thank you, both of you. I'm sorry that I took so long to get back.
Back to top
View user's profile Send private message
Tdarcos



Joined: 16 May 2008
Posts: 4441
Location: University Park, Maryland

PostPosted: Thu Sep 29, 2011 7:30 pm    Post subject: Reply with quote

Bainespal wrote:
Now that it's been mentioned, I do feel that the library's treatment of the command to listen is inadequate


Let's consider that Hugo is a general purpose text-based adventure game processor. As such, the routines are going to be general purpose and targeted for the lowest common denominator, with the ability to override as needed.

So for most actions the default probably works right, but occasionally you need something better. When that happens you write the code that handles the special cases.

As a system, if done correctly, the base installation should hit at least the 95th percentile and hopefully 98th. This means that for 95 to 98% of all games, or 95-98% of even complicated games, the default library is adequate to do the job unchanged.

That means, given, say, that the library (objlib.h, resource.h, system.h, verblib.g, verblib.h, verbstub.g, verbstub.h, window.h, hugofix.g, hugofix.h, hugolib.h) is perhaps 20,000 lines, that at most you shouldn't have to code more than a couple hundred lines of replacement code.
_________________
The lessons of history teach us - if they teach us anything - that no one learns the lessons of history.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Jolt Country Forum Index -> Hugo's House of Horrors All times are GMT - 7 Hours
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001 phpBB Group

Theme by Kage Musha - RPG Garden

Copyrights and trademarks are all of the belonging company. No copyright Infringement intended