Page 1 of 1

Ask About / Tell About and objects

Posted: Thu Jan 26, 2012 12:37 am
by Ice Cream Jonsey
For the first time, I am gonna use ask about and tell about in a game. I am sure I could find this if I looked, but.... what's the industry-standard way of avoiding having to code objects for conversational topics?

So if I want to mention the weather in the game's text, and let Hugroid ask Nimroid about the weather, how do you guys set that up? I looked at Taleslinger's code for Clockwork Boy, but it seems everything you can talk about is an actual in-game object.

I'll update HxE if I get the answer!

Posted: Thu Jan 26, 2012 12:38 am
by Ice Cream Jonsey
Whoa! And this page answers my next question, which is "keeping track of the number of times asked!"

http://hugo.gerynarsabode.org/index.php?title=DoAsk

Posted: Thu Jan 26, 2012 3:55 am
by Roody_Yogurt
As far as the first question goes, I think the industry standard is making an object for the topic. I think Merk actually rewrote his conversation code to work strictly off of strings, so you could look at that if you want to go that route (EDIT: this is wrong. Merk didn't do this.). Part of the reason I gravitated to Hugo in the first place, though, was being able to use objects in my conversation code, since for whatever reason, it offended me that I had to type an object's nouns and adjectives twice.

If you do end up using the object route, the most important thing is to use the known attribute. DoAsk/DoTell use the anything grammar token, so objects being referenced do not need to be in scope but they do need to be known.

Code: Select all

object weather "weather"
{
    article "the"
    noun "weather"
    is known
}
The nice thing about using objects- besides inheriting nouns and adjectives and such- is that you can attach whatever other properties to it. Actually, while writing this reply, it occurs to me that my 'timesasked' system would be much better off if I put the properties in every object to be asked about and not in the characters themselves, using a character-numbering system like phototalk.hug.

My 'timesasked' code is the basis that I used for my take on 'the king of shreds and patches' conversation system. I haven't polished it up for any kind of release, but you can look at it here: http://roody.gerynarsabode.org/JC/doasktopics.hug

In the next day or so, I think I will try swapping around the properties and see if it makes it that much easier to set-up (I think it might!).

Hmm, I was going to finish up this post with going over how Merk handled it with his games, but it seems like I was wrong. He has some string-y stuff in there, but for the most part, it's just the regular way.

Anyhow, you could change the DoAsk grammar to just expect a word instead of 'anything' or something, but it's going to be a big can of worms if some of your topics have two or three word names, I think. Probably not worth it.

Actually, that gives me an idea.

Posted: Thu Jan 26, 2012 4:15 am
by Roody_Yogurt
Well, no. I was thinking you could have:

Code: Select all

verb "ask"
* living "about" word        DoAskWord
line defined before DoAsk, but that'd both require all of your non-object topics to be one word and you'd have to recreate everything that'd normally be handled by DoAsk.

Anyhow, I will be interested in hearing where you go with this.

Posted: Thu Jan 26, 2012 4:54 am
by Roody_Yogurt
Well, even though it's less than ideal, I threw together a DoAskWord routine to go with the above. It first checks to make sure that the word isn't an adjective or noun (originally was going to only do the latter but thought I'd let it be more receptive) before doing its thing:

Code: Select all

object can "tin can"
{
	adjective "tin"
	noun "can"
	in STARTLOCATION
}

character fred "Fred"
{
	noun "fred"
	in startlocation
	after
		{
		object DoAsk
			{
			select xobject
				case can : "yay can!"
			   case else : "I dunno!"
			}
		object DoAskWord
			{
			select xobject
				case "weather" : "Yay weather!"
				case else : return false
			}
		}
}

routine DoAskWord
{
	local i
	                            ! the 29th object is either the last
   for &#40;i=29; i <=objects;i++&#41; ! hugolib-defined object or the first
	&#123;                           ! non-hugolib object, depending on whether
	if ObjWord&#40;xobject, i&#41;      ! HugoFix is on
		return Perform&#40;&DoAsk, object, i&#41;
	&#125;

	speaking = object

	if object is unfriendly
	&#123;
		if not object.ignore_response
			Message&#40;&Speakto, 4&#41;    ! "X ignores you."
		speaking = 0
	&#125;
	elseif object = player
	&#123;
		VMessage&#40;&DoAsk, 2&#41;             ! "Talking to yourself..."
		return false
	&#125;
	else
	&#123;
		if not object.after
		&#123;
		  	! "Doesn't seem to know anything..."
				VMessage&#40;&DoAsk, 6&#41;
		&#125;

#ifclear NO_SCRIPTS
		SkipScript&#40;object&#41;
#endif
	&#125;
	return true
&#125;

Posted: Thu Jan 26, 2012 5:31 am
by Flack
I don't know if this can be applied to Hugo or not, but in "A Game of Chance" (Inform 6) I did the following with my NPCs:

life [;
Ask: switch (second) {
'slot', 'machine', 'slot machine':
"~Yeah, you did a number on that one, didn't you. I've never seen quite so much drool on a machine before.
Impressive.~";
'clock', 'time':
"~Yes sir, it's half-past time for you to go.~";
'carpet':
"~Matches the drapes, thanks.~";
'drapes':
"~Matches the carpet, duh.~";
'drink', 'drinks', 'alcohol', 'beer', 'beers', 'shot', 'shots':
"~Oh no my friend, you've had quite enough.~";
'poker', 'liquor':
"~Poker in the front, liquor in the rear. Er, wait ...~";
'weather':
"~Partly cloudy, with a chance of you being really hung over tomorrow.~";
};
Kiss: "Although the Pit Boss appreciates your offer, alas, he is on the clock.";
Attack, ThrowAt: Pit_Death();
],
before [;
Talk: Pit_Speak();
],


For objects that the player could interact with I set up actual objects, but for one-line retorts, I did them this way.

Posted: Thu Jan 26, 2012 8:26 am
by Ice Cream Jonsey
Just a quick reply before work and before I've had coffee: thanks for all the code samples! You guys are the best.

I figured out what was wrong. I didn't have a noun attached to the object I wanted to ask or tell about. I just had the definition like so:

npc blahblah "blahblah"
{
}

Once I threw a noun in there, it worked.

I am going to throw in the code you wrote, Roody, and see if I can get that to work though!

Posted: Thu Jan 26, 2012 6:29 pm
by Roody_Yogurt
I updated my take on 'shreds and patches' to keep times-asked quantities in object properties (instead of the characters). Initially, I was hoping I could do something like this:

Code: Select all

property timesasked #5
where it'd then give every object 5 empty elements, the way that the size property declaration gives every object a default value of 10. Unfortunately, that isn't possible so one still has to manually add the properties to every object. On the plus side, this makes the element-application a lot less wasteful (as there are going to be lots of non-topic objects), and I made adding the properties a little bit easier by making a couple object classes and then using the "inherit" function to quickly add those properties to objects (got this idea by looking at Merk's code recently).

Anyhow, I think the code is a bit more readable now. You can take a look at: http://roody.gerynarsabode.org/JC/reversetopics.hug . Anyhow, the topics-listing aspect is completely optional; you can also just make use of its time-asked-counting scheme.

Also, again going back to the original issue, if the problem is that you want to avoid responses like >GET WEATHER "You don't see that.", you could make a topic object class that has default responses like the following:

Code: Select all

class topic_object
&#123;
	found_in &#123;return location&#125;
	before
		&#123;
		object
			&#123;
			"Don't be silly."
			&#125;
		xobject
			&#123;
			if verbroutine = &DoAsk,&DoAskQuestion,&DoTell,&DoTalk
				return false
			"Don't be silly."
			&#125;
		&#125;
	is known
&#125;

topic_object weather "weather"
&#123;
	article "the"
	noun "weather"
	before
		&#123;
               ! because it is feasible that someone might type
               ! >EXAMINE WEATHER
		object DoLook
			&#123;
			"The weather sure is nice."
			&#125;
		&#125;
&#125;

Posted: Sat Jan 28, 2012 8:15 pm
by Roody_Yogurt
I turned this ask/tell-counting system into a library extension. You can pick it up here.

Posted: Sat Jan 19, 2013 1:55 pm
by Roody_Yogurt
I was thinking recently about how any game with ASK/TELL should have some way of telling the player what he can ask about even if it isn't doing the fancy "times-asked"-counting I've tried to do in the posts above. I thought I'd throw together a quick example of how you can put such a thing in your game!

Code: Select all

property ask_topics ! property to hold list of objects that can be asked about

character don "Don Rogers"
&#123;
	in startlocation
	noun "don"
	ask_topics paul producer slash
	after
	&#123;
		object DoAsk
		&#123;
		select xobject
			case paul&#58; "\"I have a better idea. I'll talk over you.\""
			case producer &#58; "\"I have a better idea. I'll play 'The Spirit of
			Radio' again.\""
			case slash &#58; "\"He thinks \Ihe\i knows radio!\""
			case else &#58; "Don cuts your mic."
		&#125;
	&#125;
&#125;

replace DoTalk
&#123;
	print "You can ask "; The&#40;object&#41;; " about ";
	NewPropertyList&#40;object, ask_topics&#41;
	"."
&#125;

routine NewPropertyList&#40;obj, prop, artic&#41;
&#123;
	local a, b, n, total

	for &#40;a=1; a<=obj.#prop; a++&#41;
	&#123;
		if obj.prop #a ~= 0 &#58;  total++
	&#125;

	for &#40;a=1; a<=obj.#prop; a++&#41;
	&#123;
		b = obj.prop #a
		if b
		&#123;
			n++
			if artic
				The&#40;b&#41;
			else
				Art&#40;b&#41;

			if n <total> 2
				print ", ";
			elseif n = total - 1&#58;  print " ";

			if n = total - 1
				print AND_WORD; " ";

		&#125;
	&#125;
&#125;