Conflicts with Informal Questions code

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

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

Conflicts with Informal Questions code

Post by Bainespal »

The code for Informal Questions on Hugo by Example would be useful in my project. I was just adding it to my source file, but some conflicts with the optional VERBSTUBS library came up.

The routines DoYes and DoNo are already defined in Verbstubs.h. Unfortunately, simply changing "routine" from the code on the website to "replace" doesn't work; it produces a bunch of compiler errors.

Here's the first error that appears in my compiler window when I try to "replace" the Verbstubs routines with the once from Informal Questions:

Code: Select all

D:\Users\Paul\IF\Hugo\Projects\Holiday\holiday.hug:279:  Error:  Syntax error:  doyes
D:\Users\Paul\IF\Hugo\Projects\Holiday\holiday.hug:279:  Error:  Not an object or routine:  doyes
Many other errors follow, because the Compiler has been thrown off. These errors do not appear when I have "routine DoYes" and "routine DoNo" instead of "replace" -- only two errors for the routines already having been defined come up.

I'm wondering if Verbstubs.h isn't replaceable, for some reason.

By the way, the Informal Questions code is great; I appreciate the effort in putting up on HxE.

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

Post by Roody_Yogurt »

My first guess is that you have the "Informal questions" code before verbstubs.h is included. If it is after "#include verbstubs.h" in holiday.hug, "replace DoYes" and "replace DoNo" should work.

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

Post by Roody_Yogurt »

The only other issue that I can think of is, a game that uses verbstub.g won't need the grammar at the top of the Informal Questions page:

Code: Select all

verb "yes","y"
	*					DoYes
verb "no"
	*					DoNo
I will be curious if the problem ends up being neither of these things.

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

Post by Bainespal »

I don't have the line "#include verbstubs.h" in my code. Instead, my code has "#set VERBSTUBS" near the top of my source file, above where I've typed in the Informal Questions code.

I started by modifying the "shell.hug" file, so near the top of my code it says this:

Code: Select all

! Uncomment the following to use a precompiled version of the Hugo Library:
! #set PRECOMPILED_LIBRARY

! Uncomment the following to include the HugoFix Debugging Library:
#set DEBUG

! Uncomment the following to include verb stub routines:
#set VERBSTUBS

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

Post by Roody_Yogurt »

verblib.g has this bit of code:

Code: Select all

#ifset VERBSTUBS
#include "verbstub.g"
#endif
hugolib.h has this:

Code: Select all

#ifset VERBSTUBS
#include "verbstub.h"
#endif
So, yeah, those files are included by setting "#set VERBSTUBS" and is why you can't have the "replace DoYes" before "#include hugolib.h". I guess it's unlikely that you are defining routines that far up in the source file, though.

If you need to, send the troublesome file to roodyyogurt at gmail.com.

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

Post by Bainespal »

I had been defining verb routines directly under the verb grammar definitions. I rearranged the code, and now it works fine.

Thank you. For the Informal Questions code, as well.

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

Post by Roody_Yogurt »

No problem. Learning where it's not ok to define things is not very clear. Only within the last handful of months have I realized that I could define globals, arrays, and (some) constants pretty much anywhere I wanted. Maybe this whole thing calls for a HxE page.

Also, glad to hear that somebody is using the Informal Questions code! It was one of those things where I thought it was very possible I'd be the only one who likes those kinds of things.

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

Post by Bainespal »

Roody_Yogurt wrote:Also, glad to hear that somebody is using the Informal Questions code! It was one of those things where I thought it was very possible I'd be the only one who likes those kinds of things.
I originally decided to look up the code on HxE because I wanted the parser to ask the player a question in a certain game state to clarify what the player meant, taking advantage of the situation to insert some conventional parser sarcasm. But now that I've included the extension, I want to clean up some of my NPC interactions with it. In a couple cases, I used the cumbersome YesOrNo routine, which has a very artificial effect. I also think I can integrated it with my ASK/TELL conversation system to make dialogue a little more natural; I can Perform a DoYes/DoNo from TELLing.

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

Post by Roody_Yogurt »

Of course, the same idea can be applied to things other than "YES" and "NO" answers in the game. Looking at HxE and my own files, I am reminded that I still haven't polished a library contribution I meant to add at some point. It's called "opportune.h", and it's basically a simplified version of "Informal Questions" (in fact, some of the IQ code has been left in there as someone might still want it).

The point of this library is for all of the times you want to have a 1 turn window open for somebody to do something. Of course, there are other ways to handle it, but the purpose of this method is to keep your code clean and easy to read.

The code so far:

Code: Select all


global current_opp

! A fuse so that each question is only answerable for one turn
! opp_window = short for "opportunity window"
! changed the name of the fuse so it'd sound more
! dual-purpose
fuse opp_window
{}
 
event opp_window
{
	if not self.tick
		current_opp = 0
}

!\    ! the old code in case someone wants any questions
! a question class so to help organize our questions
class Question
{}
 
question egress
{
	long_desc
		"Are you sure you're mentally and otherwise prepared to meet up with an egress?"
}

Started like:
NewQuestion(egress)
\!

routine NewQuestion(question)
{
	current_opp = question
	run question.long_desc
	Activate (opp_window, 2)
}

routine NewOpp(opportunity)
{
	current_opp = opportunity
	Activate (opp_window, 2)
}

class opp
{}

! some sample opportunities
opp busted
{}

opp takealook
{}
So, in my WIP, it is possible to have an object hit you in the face (I think I say "chin"). I set the "busted" opportunity, then in my chin object, I have this code:

Code: Select all

object chin "chin"
{
     article "your"
     noun "chin"
     part_of you
     long_desc
        {
	if current_opp = busted
		"Aw, it'll be okay."
	else
	"It is your chin."
	return true
	}
}
Now, after somebody does the chin-smashing action, if they look at their chin right away, they get the reassuring "Aw, it'll be okay."

So yeah, there are a lot of uses for something like this (I hope).

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

Post by Bainespal »

I like that code!

I'm keeping track of sequences of interactions using a property called "room_state", which I've given to most of the rooms in the game. I increment room_state to reflect the current position in an interaction with an NPC or to keep track of changes that the PC has made on the environment. Its been working for me, but it gets messy and chaotic some times, especially when trying to account for alternate actions that shouldn't advance room_state to a value reserved for the sequence that actually moves the game forward.

I don't think this code could replace my room_state system, but it could make certain portions of interaction sequences that I've implemented much cleaner and easier to debug.

What if I wanted to make an "opp" that lasted for more than one turn? Maybe the NewOpp routine could be written with an additional local variable, allowing for the length of the fuse to be customized:

Code: Select all

routine NewOpp(opportunity, length)
{
   current_opp = opportunity
   Activate (opp_window, length)
}
Just an untested spur-of-the-moment thought.

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

Post by Roody_Yogurt »

I haven't yet run into a situation where I'd need something like that. You could do something like this, though:

Code: Select all

routine NewOpp(opportunity)
{
	current_opp = opportunity
	Activate (opp_window, (2 + opportunity.extra_turns))
}

property extra_turns alias size ! just picked a random property to alias to

class opp
{}

opp busted
{
	extra_turns 1 ! would run for 2 turns total
}

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

Post by Roody_Yogurt »

I did end up turning this whole thing into a library extension afterall, which you can find here.

It's always rough figuring out how much explanation I should put inside the file in comments, and how much I should put externally. As you can see, I opted mainly for the former this time around.

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

Post by Roody_Yogurt »

Instead of working on my game, I've been cleaning up code on an older game (Baby Uncle New Year) so I can upload the source to Hugo By Example. When possible, I'm trying to delete messy code and replace them with library contribution inclusions. One such library contribution is opportune.h.

Anyhow, it turns out there were a couple big-ish bugs in it, so a new version has been uploaded.

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

Post by Roody_Yogurt »

I recently update "opportune.h" to allow for multiple opportunities with varying lengths of time. It's called Multiopportune.h. In doing so, I realized that most of the things this could be applied to would be better off handled by regular fuses, so I reverted opportune.h to its original one-turn window.

So, in review: Multiopportune, bad. Fuses, good. Opportune, good.

Post Reply