react_before question

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

Isxek
Posts: 10
Joined: Sat Aug 15, 2009 11:08 am
Contact:

IMO I think it's correct

Post by Isxek »

From what I've understood of Hugo so far, what you did was essentially correct.

"react_before" is similar to Inform 6's property in that it's supposed to trap actions (and/or provide messages) before any other object's "before" property. If the "react_before" property you have is attached to the mechanic character object, then it will be run before the room's "before" property. (Did that make sense?)

The only caveat here is that the player object has to be within the mechanic's scope to make it actually work.

Hopefully I explained it correctly. Otherwise, let's wait for ICJ or Merk to come in.

Isxek
Posts: 10
Joined: Sat Aug 15, 2009 11:08 am
Contact:

Re: IMO I think it's correct

Post by Isxek »

Sca wrote:Still, like I said, the code is working fine now as it is, so maybe I shouldn't really be worrying about elegance. (I guess the main reason I'm at all concerned about this is because, even though for this one example it doesn't make much difference, if I end up using react_befores for other objects with more verbroutines involved, if there's a more elegant approach it could save me a significant amount of typing.) But, again, not a big deal.

Anyway, I appreciate your response; I guess I may not have been entirely clear about my question. Thanks for your reply.
Your question was pretty clear to me. However, I didn't see any other way it can be written.

I'd like to see a more elegant way to do this as well.

Merk
Posts: 192
Joined: Mon Nov 22, 2004 3:19 pm
Location: Wichita, KS
Contact:

Post by Merk »

That's a pretty common thing to need to do, and I'm aware of two different ways. I'm not sure I've ever used "react_before" though. You can add any before { } or after { } block to any object for handling specific verbs, such as &DoGo.

Way #1:

In the room where the player can't go west, change this:

w_to newroom

to this:

Code: Select all

w_to {
    if (your_condition_goes_here) {
        "You can't go that way."
        !Alternately, you could customize cant_go.
        return false
    } else {
        return newroom
    }
}
Way #2:

In your "player" object, add this:

Code: Select all

before {
    actor DoGo {
        if (location = whatever) and \
           (object = w_obj) and \
           (your_condition_goes_here) {
           "You can't go that way."
        } else {
            return false; !Default handling.
        }
    }
}
I've done both ways. The downside to #1 is that it doesn't lend itself to automatic room exit listing, because if you attempted to get the value of the various room exit properties, you'd end up executing the code inside the w_to block. The downside to #2 is that you have to specific what room and direction *inside* the player object, and if you do this quite a bit, you'll have lots of code that would probably be better placed in each room/direction where it belongs.

There may be a third way, but I forget.

I'm a fan of using the MISC property on an object as special flags, rather than creating a bunch of extra variables. And you can use multiple properties (MISC #1, #2, #3, etc, as long as you set defaults on the object for however many you will use). In my WIP, the player is initially stopped from going East, and a message is shown. When that happens, location.misc #1 is set to true. That's checked when attempting to go "east" so if the player was already warned once, it's allowed the second time.

Good luck!

Merk
Posts: 192
Joined: Mon Nov 22, 2004 3:19 pm
Location: Wichita, KS
Contact:

Post by Merk »

And actually, you're second react_before example is good. I checked the source in hugolib.h and I think what you have there is fine. The first one probably didn't work before you were writing react_before as though it was a before (where you specify verb routines directly).

So yeah, your react_before is probably a better idea than either of the options I posted. I'd stick with that. If you have it on the room object, you're probably set. It looks like you could also put it in the player object, but then you'd be adding "(if location = whatever)" to the condition as well.

Merk
Posts: 192
Joined: Mon Nov 22, 2004 3:19 pm
Location: Wichita, KS
Contact:

Post by Merk »

Oh, and if you *never* want the player to be able to go west from that room, the ideal thing is probably to not add an exit to the west as part of the room, and then handle the message in cant_go property of the room instead. This allows you to customize the default "you can't go that way" message as needed. Return "false" any time you want the default to be printed instead.

Example:

Code: Select all

cant_go {
    if (object = w_object) {
        "The mechanic stops you... etc...."
    }
    elseif (object = n_object) or (object = s_object) {
        "A wall is in your way."
    } else {
        return false
    }
}

Isxek
Posts: 10
Joined: Sat Aug 15, 2009 11:08 am
Contact:

This react_before business

Post by Isxek »

Shouldn't react_before act the same way as before routines do? I mean, shouldn't they have the same format, i.e.:

Code: Select all

react_before
{
     <usage> <verbroutine>
      &#123;
          ...
       &#125;
&#125;

Merk
Posts: 192
Joined: Mon Nov 22, 2004 3:19 pm
Location: Wichita, KS
Contact:

Post by Merk »

Well, when I looked in the Hugo Lib, that doesn't seem to be the case. It just calls "react_before" but all comparisons to the current verb have to be done with an equals.

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

Post by Roody_Yogurt »

I thought this thread was a good illustration for the usefulness of react_before, so I used the problem as an example for the react_before entry at Hugo By Example: http://hugo.gerynarsabode.org./index.ph ... act_before.

Let me know if you have any problems with that. I threw that together just now. I figure at some point, I might try to word things better or have a small section going over the order of operations or something.

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

Post by Tdarcos »

Sca wrote:what actually happens in the game is that the mechanic only stops the player the first time he tries to go west. If the player tries again, the mechanic says "Well, don't say I didn't warn you," but the player is allowed to move west. (Into an endless road (implemented by counting how many times the player tries to move west, and requiring him to go east that many times to get back)... the mechanic's warning is right.)
Why go to that much trouble? Super Mario 64 has an endless staircase when you don't have the key, no matter how much you go up it keeps on going up forever. Turn around and you're right where you started.

So just have it say the road west goes on forever, and move west just loops back to this same room saying this. Then a move east goes back to the previous room. Less trouble to implement and I think it will put the point across.
Alan Francis wrote a book containing everything men understand about women. It consisted of 100 blank pages.

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

Post by Roody_Yogurt »

Personally, I like the react_before method the best, but I thought I'd share another way to do it, using the obstacle global.

First off, we need to give the player a before routine that sets the value of the obstacle global before going anywhere:

Code: Select all

player_character you "you"
&#123;
	before
		&#123;
		actor DoGo
			&#123;
			ObstacleUpdate
			return false ! so that DoGo is still run
			&#125;
		&#125;
&#125;
Then we have our ObstacleUpdate routine to set the value of obstacle:

Code: Select all

routine ObstacleUpdate
&#123;
	if Contains&#40;location,mechanic&#41;
		&#123;
		if object = w_obj
			&#123;
			if mechanic is not special
				&#123;
				"You start to head off, but stop when the
				mechanic calls out to you.\n\n\"I wouldn't wander
				off that way.  You won't find anything but road
				for more miles than you'll want to walk.\""
				mechanic is special
				obstacle = 1
				return
				&#125;
			else
				&#123;
				"The mechanic regards your departure warily, muttering
				\"Well, don't say I didn't warn you,\" almost to himself
				as he returns to his work."
				&#125;
			&#125;
		&#125;
	obstacle = 0
&#125;
Lastly, since having an obstacle usually forces a "The [obstacle] blocks your path." message and nobody really uses obstacles anyway, we will get rid of that particular message using NewVMessages:

Code: Select all

replace NewVMessages&#40;r, num, a, b&#41;
&#123;
	select r
 
	case &DoGo
	&#123;
     
		select num
		case 1&#58;  return true ! skip obstacle messages
		case else &#58; return false ! do everything else
	&#125;
   case else &#58; return false
	return true ! this line is only reached if we replaced something
&#125;

Post Reply