Dynamic Names

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

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

Dynamic Names

Post by Roody_Yogurt »

Hey, Tdarcos, I noticed you found our Hugo by Example site. Today's additions were interesting, and I am curious as to what we'll see in the future.

I thought you might like to know that what you suggested in the "dynamic names" entry can be done without the creation of a new property. Try the following:

Code: Select all

room corner
{
name    {
	! _temp_string is a temporary string array defined by hugolib.h
	! the "text to" command writes to it
	text to _temp_string
        if street_number < 1  
		print "East "; 
        else&#58; print "West "; 
        print number abs&#40;street_number&#41;; ordinal&#40; street_number &#41; ;"St. ";
	text to 0   ! stop writing to the string
	return StringPrint&#40;_temp_string&#41; ! return the string as our room name
        &#125;
&#125;
Like in the other thread, this is another case like the noun and adjective property where the compiler is expecting a dictionary entry, so we return the string itself. something like a e_to property is expecting an object value, hence the different behaviors.

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

Post by Bainespal »

That looks to be about the cleverest Hugo code I've ever seen! It helps me to understand how string arrays work a little better; that's something I've never understood. The array "_temp_string" must be like the attribute "special" -- generic value holders for the programmer/implementor to use during the course of coding so he/she doesn't have to code up tons of unique variables.

I never imagined you change the context of standard directives like "print". The "text to" construction seems very alien to me. Hugo is deeper than I thought.

I'm assuming Hugo doesn't let you simply return the value of an array, then, because you had to use StringPrint at the end to display the text that you stored. You can return a property, but not an array... I get it; arrays often don't contain a single string of text or a single value. They might contain a list of lots of values.

Interesting.

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

Post by Roody_Yogurt »

Yeah, "text to" is only slightly touched upon in the Hugo Book and is one of the triumphs of Hugo By Example; I only looked into its existence while perusing stuff for HxE. It is great for whenever you want a string but different variables affect what it'll be.

The HxE page uses a PrintStatusLine replacement as an example. In that example, we want the score and moves to always be so many spaces from the edge of the screen. Of course, as the game progresses and moves and score take up more digits, we need to move the text left so it appears the same. "Text to" allows us to write the entire thing to one string array where we can use StringLength to count the digits so we can get it right every time.

loafingcoyote
Posts: 89
Joined: Wed Jan 04, 2012 2:57 pm
Location: Texas

Post by loafingcoyote »

The above code works fine if the player isn't able to directly refer to the room. However, If you assign the room the noun "corner" and the player types "X CORNER", the interpreter will freeze.

This isn't a problem for most games, since it's rare to be able to refer to the room you're in, but my latest project involves assigning random names to characters. Using the above as an example, I coded something similar to this:

Code: Select all

character char1
&#123;
	in startlocation
	name
	&#123;
		text to _temp_string
			print capital self.adjective
			print " ";
			print capital self.noun
		text to 0
		
		return StringPrint&#40;_temp_string&#41;
	&#125;
	
	adjective "amanda"
	noun "huginkis"
&#125;
The name is printed correctly but the interpreter freezes if you refer to the character at all.

My second attempt was simpler but also a failure:

Code: Select all


	name
	&#123;
		return capital self.noun
	&#125;
This prints a lot of garbled text. I suppose it's returning the address of the capital modifier. The name property is very picky about what it returns.

If I didn't need to capitalize the characters name then this solution would work. I finally gave up and just made a new property. Here is a simplified version:

Code: Select all

property last_name

character char1
&#123;
	name
	&#123;
		return self.last_name
	&#125;
	last_name 0

	! more character code
&#125;

array lastnames&#91;1&#93; = "Huginkis"

routine AssignName&#40;char&#41;
&#123;
	char.last_name = lastnames&#91;0&#93;
&#125;
The array is necessary because if you just put "Huginkis" in the last_name property directly then it wont capitalize properly.

This works but isn't very elegant. I would really like to do it without the extra property. I'm sure there's a way but it's beyond me right now. Any ideas?

-lc

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

Post by Roody_Yogurt »

Hey, thanks for catching that error. It looks like I was trying hard to do dynamic names without adding to the dictionary table, and as you've pointed out, that looks like a really bad idea.

I think, in both cases, we're going to want to use the dict command to add new strings to the dictionary table during game play.

First thing in your source, you need to raise your MAXDICTEXTEND limit:

Code: Select all

$MAXDICTEXTEND = 200
How much you raise it depends on how many possible strings (and their lengths) there are. You need a bit open for every letter and one for the empty bit finishing off each string. So, if you're making space for five strings with an (exact) average of 10 letters, you'd need to to set $MAXDICTEXTEND to 55.

Now, this is how I'd do the dynamic street name thing:

Code: Select all

property street_number alias misc

player_character you "you"
&#123;
	before
	&#123;
		actor MovePlayer
		&#123;
			! _temp_string is a temporary string array defined by hugolib.h
			! the "text to" command writes to it
			text to _temp_string
			if object.street_number < 1
			print "East ";
			else&#58; print "West ";
			print number abs&#40;object.street_number&#41;;
			print ordinal&#40; object.street_number &#41; ;" St.";
			text to 0   ! stop writing to the string
			object.name = dict&#40;_temp_string,100&#41;
			return false
		&#125;
	&#125;
&#125;

! not the original ordinal routine. just something to print something.
routine ordinal&#40;street_num&#41;
&#123;
	print "st";
&#125;

! this will end up being "West 1st street"
room startlocation
&#123;
	street_number 1
	e_to east_room
&#125;

! this will end up being "East 1st Street"
room east_room
&#123;
	street_number -1
	w_to startlocation
&#125;
Now, the nice thing about dict is that when the above code is run for a second time on a room, it'll return the same address as it did before so you don't have to worry about using up all of your dictionary table space on the same objects.

Maybe you can do the same thing for your problem.

loafingcoyote
Posts: 89
Joined: Wed Jan 04, 2012 2:57 pm
Location: Texas

Post by loafingcoyote »

Thank you Roody, this solution works perfectly.
Roody_Yogurt wrote: Now, the nice thing about dict is that when the above code is run for a second time on a room, it'll return the same address as it did before so you don't have to worry about using up all of your dictionary table space on the same objects.
Okay, I understand this now. You set $MAXDICTEXTEND to 200 because there are two rooms and the address will be the same each time the player enters the room. For each room that is added you would need to add 100 to $MAXDICTEXTEND(or whatever amount you set the maxlen to in dict. Awesome, thanks!

You know, I was wondering if it might be possible to manage dictionary addresses to the point where you could replace one with another? I'm imagining a situation where the maxlen is always a standard number of bytes, say 20, and I would like to reuse that space after it's no longer needed. Is this possible?

On the other hand, what are the reasonable limits of $MAXDICTEXTEND? The manual doesn't seem to have any particular guidelines but there must be some danger to setting it too high.

-lc

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

Post by Roody_Yogurt »

loafingcoyote wrote:Thank you Roody, this solution works perfectly.

Okay, I understand this now. You set $MAXDICTEXTEND to 200 because there are two rooms and the address will be the same each time the player enters the room. For each room that is added you would need to add 100 to $MAXDICTEXTEND(or whatever amount you set the maxlen to in dict. Awesome, thanks!
Yeah, although I only really needed to set it to 26, as "East 1st St." and "West 1st St." are both 12 characters each, so you add the extra two end bits. In Tdarcos game, assuming there's like a 100 streets in either direction, he'd need like 14 characters (since most of the streets would be two digits) times 200.
loafingcoyote wrote:You know, I was wondering if it might be possible to manage dictionary addresses to the point where you could replace one with another? I'm imagining a situation where the maxlen is always a standard number of bytes, say 20, and I would like to reuse that space after it's no longer needed. Is this possible?
This is not possible. Once dictionary addresses are set, they are set in stone. I once had the idea that, in a game, I could restart the game without the player knowing, using the word array and configuration files to keep things in play, but it turned out that there's an obscure bug where the dictionary table wasn't being reset like it should be.
loafingcoyote wrote:On the other hand, what are the reasonable limits of $MAXDICTEXTEND? The manual doesn't seem to have any particular guidelines but there must be some danger to setting it too high.
Yeah, who knows. I wouldn't worry about it until you run into that danger, at which point, hey, we'll all learn something.

User avatar
Flack
Posts: 9090
Joined: Tue Nov 18, 2008 3:02 pm
Location: Oklahoma
Contact:

Post by Flack »

So in theory, could you make a game with random location names, in random directions, with random people and random objects? Obviously it would be difficult to build puzzles that relied on specific objects, but it would be interesting or at least a challenge to create a game that was so random that each person who played it would have a completely unique experience. It would make a walk-thru impossible. One person might have to walk north to the library to find an object while another person might have to walk south to the foyer to do the same thing. Kind of like a randomized version of IF Clue.
"I failed a savings throw and now I am back."

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

Post by Roody_Yogurt »

Yeah, it's completely possible, and I would imagine that there are games out there that do that, to varying degrees.

As far as "IF Clue" goes, there was a game the other year called An Act of Murder where the murderer and weapon is randomized from game to game. Names weren't randomized, but like I said, I'm sure stuff is out there.

Similarly, another holy grail of IF is dynamic object creation, where the game can create more objects on the fly as they are needed. Personally, I've always been on the side that it was overkill; as an author, there are enough tips and tricks to give the illusion of multitudes well enough. Just the same, people have been working towards it for a while. I think TADS 3 officially supports it these days. Not sure about Inform 7.

loafingcoyote
Posts: 89
Joined: Wed Jan 04, 2012 2:57 pm
Location: Texas

Post by loafingcoyote »

I found the limit tonight. If you set the $MAXDICTEXTEND too high the compiler gives an error message like this.
Error: Limit exceeds maximum of 32768: $maxdictextend=32769
I created enough new dictionary addresses to use all those bytes with a simple loop that creates random, non-repeating strings. I'm happy to say that setting $MAXDICTEXTEND to the limit and using all those extra bytes didn't seem to affect the program at all. I was worried about not being able to reuse dictionary addresses but, with all that extra space, it hardly matters.
Flack wrote:So in theory, could you make a game with random location names, in random directions, with random people and random objects? Obviously it would be difficult to build puzzles that relied on specific objects, but it would be interesting or at least a challenge to create a game that was so random that each person who played it would have a completely unique experience.
What you're describing here is my dream game...the game I was born to write. My idea for this was actually my original Hugo Comp game. Once I started coding I realized that there was no way to do it justice in the time allowed and shelved it.

I'm not sure how long it will take but I'm pretty certain it will be my first major work of IF. It's a bit of a departure from traditional IF, due to the randomization, but if I can pull it off it should surprise you every time you play it.

Also, I think Roody's right about not needing dynamic objects to create a game like this. We're only limited by our imagination in this area, particularly when it's possible to make potentially thousands of new dictionary addresses.

-lc

Post Reply