Hugo Homework

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

Hugo Homework

Post by Roody_Yogurt »

It occurs to me that there are things that'd be nice to have in Hugo but aren't enough of a priority for me to do right away. Also, hey, why should I get all the fun coding challenges?

This'll be our thread for requesting Hugo code for this or that.

I'll start us off with two requests. First off, Inform and TADS both have "bag of holding" objects- containers that the player automatically stuffs things into when picking stuff up when already carrying a full load. A lot of time, this container can hold an endless amount of stuff, making inventory management a lot easier. Inform 6 called it the SACK_OBJECT, Inform 7 calls it the player's holdall, and TADS calls it the BagOfHolding.

Now, I've never written a game with a lot of takeable objects, and Hugo authors often just give the player a huge capacity, but just the same, it'd be good if we had our own version of this functionality.

So, who wants to write a bag of holding object class??

The other coding challenge would be to do a keyring object like in Anchorhead that automates a lot of key-related messages. Here's a clip from Anchorhead:
>get key
(the old-fashioned iron key)
(slipping the keyring into the pocket of your trenchcoat to get a hand free)
You pick up the old-fashioned iron key. It's an old key, the kind with a round
barrel about a quarter-inch in diameter and flat, square teeth.

Your score has just gone up by one point.

>put key on keyring
(the old-fashioned iron key on the keyring)
The old-fashioned iron key is now on the keyring.
If we wanted, our version might put new keys on the keyring automatically. Just a thought.

Anyhow, no worries if these examples don't sound appealing to anyone else. If no one wants to do it, I'll get to them eventually.

EDIT: I forgot to add that there is most definitely Inform code out there for the bag of holding stuff if you want to see how others do it, and I wouldn't be surprised if there is keyring code out there, too.

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

Post by Roody_Yogurt »

I forgot to say that it's kind of interesting with the bag of holding issue, you'd have to decide that when the player automatically puts stuff in the bag of holding to make room for things, does it choose the eldest/youngest child? Does it choose the first by object number? Does it choose randomly? Can some items be safe from being chosen?

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

Post by Roody_Yogurt »

Actually, I was meaning to write some object-children-sorting for Roodylib anyway (to go along with my ListChildren routine which uses objest hierarchy for lists), so these are a bunch I threw together tonight (and the TakeRandom one could easily be used towards the bag-of-holding problem), in case someone wants them:

Code: Select all

object temp_bowl
{}


!\ MovePosition - moves object "obj" in parent "par" to position "pos"
( pos = 1 makes it the oldest child, bigger numbers make it younger) \!
routine MovePosition(obj,par,pos)
{
	local n = 1
	while child(par)
	{
		move child(par) to temp_bowl
	}

	while child(temp_bowl)
	{
		if n++ = pos
			move obj to par
		elseif child(temp_bowl) = obj
			move obj to temp_bowl
		else
			move child(temp_bowl) to par
	}
}

! MixObjects - Randomizes order of children of parent "par"
routine MixObjects(par)
{
	local n, obj

	while child(par)
	{
		move child(par) to temp_bowl
	}

	while child(temp_bowl)
	{
		n = children(temp_bowl)
		n = random(n)
		n--
		obj = child(temp_bowl)
		while n
		{
			obj = sibling(obj)
			n--
		}
		move obj to par
	}
}

! ReverseOrder - Reverses the order of parent's (par's) children
routine ReverseOrder(par)
{
	while child(par)
	{
		move child(par) to temp_bowl
	}

	while child(temp_bowl)
	{
		move youngest(temp_bowl) to par
	}
}

! TakeRandom - returns a random child from parent "par"
routine TakeRandom(par)
{
	local n, obj
	n = children(par)
	n = random(n)
	n--
	obj = child(par)
	while n
	{
		obj = sibling(obj)
		n--
	}
	return obj
}

!\ "floats" objects in parent "par" to the top as determined by rules
   returned by routine "arg" (see sample below)  \!
routine Float(par,arg)
{
	local obj, qualify
	while child(par)
	{
		move child(par) to temp_bowl
	}

	obj = youngest(temp_bowl)

	while elder(obj)
	{
		qualify = call arg(obj)
		if qualify
		{
			move obj to par
			obj = youngest(temp_bowl)
		}
		else
			obj = elder(obj)
	}

	while child(temp_bowl)
	{
		move child(temp_bowl) to par
	}
}

!\  Sample routine call and argument routine:
routine DoFloat
{
	Float(basket, &IsEdible)
}

routine IsEdible(obj)
{
	return (obj is edible)
}  \!

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

Post by loafingcoyote »

Here is my attempt at a bag of holding:

Code: Select all


attribute unstowable

class holdall
{
	type holdall
	before
	{
		xobject DoputIn
		{
			if object is unstowable
			{
				MatchPlural(object, "That", "Those")
				" wont fit in ";
				The(self)
				"."
				return true
			}
		}
	}
	capacity 300
	holding 0
	is container
}


replace Acquire(newparent, newchild)
{
	local p, i, carryall, flag

	CalculateHolding(newparent)

	if newparent.holding + newchild.size > newparent.capacity
	{
		flag = true
		
		for i in newparent
		{
			if i.type = holdall
				carryall = i
		}
	}
		
		if flag = true
		{
			if carryall
			{
				if StowObject(newparent, carryall, newchild): flag = false
			}
			 if flag = true: return false
		}

		p = parent(newchild)
		move newchild to newparent
		CalculateHolding(p)
		newchild is moved
		newchild is not hidden
		newparent.holding = newparent.holding + newchild.size
		return true
}

routine StowObject(parent_object, carryall, newchild)
{
	local i, biggest_item

	for i in parent_object
	{
		if i is not unstowable and i ~= carryall
		{
			if i.size >= biggest_item.size or not biggest_item
			{
				biggest_item = i
			}
		}
	}
	
	if biggest_item
	{
		CalculateHolding(carryall)
		if carryall.holding + biggest_item.size > carryall.capacity: return false
		
		"(first putting ";
		Art(biggest_item)
		" into ";
		The(carryall)
		")"
			
		move biggest_item to carryall
		parent_object.holding = parent_object.holding - biggest_item.size
		
		if parent_object.capacity < parent_object.holding + newchild.size
		&#123;
			StowObject&#40;parent_object, carryall, newchild&#41;
		&#125;
		return true
		

	&#125;
	
	return false
&#125;
I replaced Acquire and added one attribute and a class. Define a "holdall" object like this:

Code: Select all

holdall ruck_sack "rucksack"
&#123;
	noun "sack"
	adjective "ruck"
	article "a"
	is clothing
&#125;
Default capacity is 300. Here are a few objects to experiment with:

Code: Select all

player_character you "you
&#123;
	in startlocation
	capacity 20
	holding 0
&#125;

object coin "coin"
&#123;
	nearby
	noun "coin"
	article "a"
	size 2
&#125;

object soda "soda can"
&#123;
	nearby
	noun "can"
	adjective "soda"
	article "a"
	size 5
&#125;

object cup "cup"
&#123;
	nearby
	noun "cup"
	article "a"
	size 5
&#125;

object pillow "pillow"
&#123;
	nearby
	noun "pillow"
	article "a"
	size 7
&#125;

object rake "leaf rake"
&#123;
	nearby
	noun "rake"
	adjective "leaf"
	article "a"
	size 10
	is unstowable
&#125;
The leaf rake has the attribute "unstowable" and can't be stowed or put into the rucksack.

Notice that this chooses the largest item in the players inventory to stow. If stowing just one item will not free up enough space to pick up the intended object, then a second object will be stowed. If the player's inventory is taken up by objects that can't be stowed then they wont be able to pick up more objects, even if the intended object is stowable. You can see this behavior if you are holding(not wearing) the rucksack and the rake and attempt to pick up another object. You will not be allowed to pick up the new object even though you could stow it.

One last thing. Roodylib replaces CalculateHolding but I'm not sure it works properly. My experiments showed that the replaced CalculateHolding routine was returning the players holding property as "0", no matter what they were holding. I could be wrong about where the problem is but just be aware that it may not work with Roodylib at the moment.

-lc

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

Post by Roody_Yogurt »

Awesome, I look forward to checking this out further in depth. Good work.

As far as CalculateHolding goes, yeah, looks like there's a problem there. I took the code directly from Merk, who noticed that "worn" is aliased to "mobile", so things like ropes weren't counting towards a player's inventory capacity. So, I'm thinking it's supposed to be this:

Code: Select all

replace CalculateHolding&#40;obj&#41;
&#123;
	local i

	obj.holding = 0
	for i in obj
	&#123;
		if not &#40;i is worn and i is clothing&#41; and obj ~= player
			obj.holding = obj.holding + i.size
	&#125;
&#125;
Conditionals can be a pain in the ass, so let me know if that still doesn't solve the problem. I'll change that in Roodylib, too.

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

Post by Roody_Yogurt »

Another Hugo Homework Challenge!

I was thinking today about the annoyance of making lots of objects for certain tasks and how a good Hugo challenge would be to create a deck of cards (or, at least, a card game) that adequately represents a full deck (like, a four of clubs can only exist once, and so on), but do this with as few objects as you can.

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

Post by loafingcoyote »

Roody_Yogurt wrote:Conditionals can be a pain in the ass, so let me know if that still doesn't solve the problem. I'll change that in Roodylib, too.
Unfortunately this doesn't work either. The holding property is still not being updated properly. I played around with it a bit myself but I'm just too foggy right now to deal with it.

I was able to fix something with my holdall class. I realized that if the player removes a holdall object with a full inventory then his holding limit would be exceeded. The following replacement of the holdall class fixes that.

Code: Select all

class holdall
&#123;
	type holdall
	before
	&#123;
		xobject DoputIn
		&#123;
			if object is unstowable
			&#123;
				MatchPlural&#40;object, "That", "Those"&#41;
				" wont fit in ";
				The&#40;self&#41;
				"."
				return true
			&#125;
		&#125;
		object DoTakeOff
		&#123;
			if self is clothing and self is worn
			&#123;
				if Acquire&#40;player, self&#41;&#58; return false
				else
				&#123;
					"You'll probably have to drop something to do that."
					return true
				&#125;
			&#125;
			else
			&#123;
				VMessage&#40;&DoTakeOff, 2&#41;  ! "You're not wearing that."
				return true
			&#125;
		&#125;
	&#125;
	capacity 300
	holding 0
	is container
&#125;

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

Post by Roody_Yogurt »

Heh, you're right. Looking at it one more time, it should be:

Code: Select all

		if not &#40;i is worn and i is clothing and obj = player&#41;

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

Post by loafingcoyote »

Yeah, that did it!

This may just be end-of-the-week exhaustion talking but, after writing that last bit of holdall code I got the strong impression that writing IF is like trying to hold the world together with duct tape.

Anyway, yeah, it must be lack of sleep.

-lc

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

Post by Roody_Yogurt »

Heh, while trying to figure out the other way the CalculateHolding conditional could be expressed, I realized that, ok, the original suggested like was correct. I just had copied it wrong to Roodylib, so Roodylib had this:

Code: Select all

if i is not worn or i is not clothing and obj ~= player
when it should have been:

Code: Select all

if i is not worn or i is not clothing or obj ~= player
Having you lay the groundwork first, I took my own swing at the problem. In doing so, I especially like how your method provides an easy way to provide special messages for unstowable objects.

Code: Select all

global hold_object

! just a constant to make it easier to have unlimited-space
!  holdall objects
constant INFINITE -1

!\ I'm using after routines to set my global variable, but it's
a really unrefined way to do so.\!
class holdall
&#123;
	is container
	after
	&#123;
		object DoGet, DoTakeOff
		&#123;
			hold_object = self
			return false
		&#125;
		object DoDrop, DoPutIn
		&#123;
			hold_object = 0
			return false
		&#125;
	&#125;
	holding 0
	capacity INFINITE
&#125;

replace Acquire&#40;newparent, newchild&#41;
&#123;
	local p

	CalculateHolding&#40;newparent&#41;

	if &#40;newparent.holding + newchild.size > newparent.capacity&#41; and
		newparent.capacity ~= INFINITE
	&#123;
		if hold_object and newparent = player and parent&#40;hold_object&#41; = player
		&#123;
			if not CheckHoldAll&#40;newchild&#41;
				return false
		&#125;
		else
			return false
	&#125;
		p = parent&#40;newchild&#41;
		move newchild to newparent
		CalculateHolding&#40;p&#41;
		newchild is moved
		newchild is not hidden
		newparent.holding = newparent.holding + newchild.size
		return true
&#125;

routine CheckHoldAll&#40;newchild&#41;
&#123;
	local obj
	if &#40;hold_object is openable and hold_object is not open&#41; or
	FindObject&#40;hold_object, location&#41; ~= 1
		return false
	while &#40;player.capacity < &#40;player.holding + newchild.size&#41;&#41;
	&#123;
		if obj = youngest&#40;player&#41;
		&#123;
			return false
		&#125;
		obj = PickObject
		if obj ~= hold_object
		&#123;
			if Acquire&#40;hold_object, obj&#41;
				print "&#40;moving "; The&#40;obj&#41;;" to "; The&#40;hold_object&#41;;" to make room&#41;"
		&#125;
	&#125;
	return true
&#125;

routine PickObject
&#123;
	local obj
	obj = child&#40;player&#41;
	while true
	&#123;
		if &#40;obj ~= hold_object and not PickRules&#40;obj&#41;&#41; or
		obj = youngest&#40;player&#41;
			return obj
		else
			obj = younger&#40;obj&#41;
	&#125;
&#125;

!\ This is a routine to have it ignore certain items that you
don't want being stowed away. \!
routine PickRules
&#123;
! example&#58; key objects are ignored
!	if obj.type = key
!		return true
&#125;
So, my version takes the oldest child of the player that isn't the holdall object (or something disallowed by PickRules) and puts it in the holdall object.

It'd be cooler if I set it up so the method-of-picking could be more interchangeable, and even though I put infinite-space support in there, it'd be nice if with limited-space holdalls, I added everything the player is holding first just to make sure there will be room for the new item before I start moving stuff.

Looking at yours again, that's cool that it goes by biggest-items-first. Also, your version can technically handle multiple bags of holding, which might be very appealing to some others. I figured most games have one holdall, and I'd try to capitalize on that fact but the resulting code wasn't quite as simplified as I was hoping for.

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

Post by loafingcoyote »

Alright, I finally got a chance to check this out. It's interesting to see how different your approach was and I think the PickRules routine is a great idea. I played with this a little and noticed a couple of things.

First, without an "unstowable" attribute it's obvious that such restrictions should be implemented with PickRules. What I did was this:

Code: Select all

attribute unstowable

routine PickRules&#40;obj&#41;
&#123;
	if object is unstowable
		return true
&#125;
This works fine most of the time. However, if the only items held are restricted by PickRules and space needs to be cleared in the players inventory, then one of those objects will be stowed anyway. The only time this isn't true is if the player is holding the holdall and it was the last item to be picked up.

Another thing I noticed was that if the player is wearing the holdall object and removes it, then his inventory limit can be exceeded, since DoTakeOff doesn't check that. This made me wonder; since a worn object doesn't count against a players inventory, why doesn't it call Acquire before allowing the player to remove it? This simple fix seems to remedy that:

Code: Select all

replace DoTakeOff
&#123;
	if not Contains&#40;player, object&#41;
	&#123;
		! So >REMOVE LOCK will >TAKE LOCK, etc.
		return Perform&#40;&DoGet, object&#41;
	&#125;

	if object is not clothing
	&#123;
		VMessage&#40;&DoTakeOff, 1&#41;         ! "Can't do that..."
		return false
	&#125;

	if object is not worn
		VMessage&#40;&DoTakeOff, 2&#41;          ! "You're not wearing that."
	else
	&#123;
		if Acquire&#40;player, object&#41;
		&#123;
			object is not worn
			if not object.after
				VMessage&#40;&DoTakeOff, 3&#41;  ! "You take it off."
		&#125;
		else&#58; NewVMessages&#40;&DoTakeOff, 4, object&#41;	! You're carrying too much.
	&#125;
	return true
&#125;

replace NewVMessages&#40;r, num, a, b&#41;
&#123;
	select r
	
	case &DoTakeOff
	&#123;
		select num
		
		case 4
		&#123;
			CThe&#40;player&#41;
			MatchPlural&#40;player, "are", "is"&#41;
			" carrying too much to take off ";
			The&#40;a&#41;
			"."
			return true
		&#125;
	&#125;
	return false
&#125;

Roody_Yogurt wrote:Looking at yours again, that's cool that it goes by biggest-items-first.
Yeah, I chose the biggest item since it seemed logical. That way I could avoid the need to stow multiple items too often.

I always thought carryall items were pretty slick but never considered making one until this coding challenge. I'm sure there are even more features available that we haven't thought of. I'm definitely going to incorporate some version of PickRules into mine. It will be similar to yours, but I think that instead of restricting certain items entirely, it may just make those items less likely to be selected.

-lc

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

Post by Roody_Yogurt »

I think a lot of games have the remove-a-worn-item-despite-your-inventory-is-full loophole, and personally, I'm okay with that. Still, besides your solution above, I imagine you could provide an over-burdened state for the player, where he can't move until he drops an item, or possibly just make him drop something at random. One definitely has a lot of options for how to handle these things.

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

Post by Bainespal »

Here's a very rough, very minimal attempt at coding a keyring, based on the latest version of the Roodylib shell:

https://dl.dropbox.com/u/101625269/keytest.hug

The main code is this:

Code: Select all

player_character you "you"
&#123;
  after
  &#123;
    actor DoGet
    &#123;
      if object is keyclass
      &#123;
        if not Contains&#40;self, KEYRING_OBJ&#41;
        &#123;
          return false ! Just print default message
        &#125;
        else
        &#123;
          move object to KEYRING_OBJ
          print "&#40;adding "; The&#40;object&#41;; " to "; The&#40;KEYRING_OBJ&#41;; "&#41;"
          return false ! print defaul TAKE message
        &#125;
      &#125;
      else ! The object isn't a key
      &#123;
        return false
      &#125;
    &#125;
  &#125;
&#125;
I made "keyclass" an attribute. I know that in any real game or extension, the key objects would have a class, but I didn't have any particular code requirements for the object being taken in this example. Also, I forgot how to test for what class an object comes from.

There are at least two obvious problems. I mean for the text explaining that the key is being added to the key ring to be printed before the standard "Taken" message, but it appears after it. More importantly, it's impossible to remove a key from the key ring, because doing so triggers DoGet and re-activates the code that puts the key into the key ring container.

This strategy defines KEYRING_OBJ as a global, so I think there could only be one key ring object at a time. That is consistent with the way Inform 6 used to do the holdall, however.

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

Post by Roody_Yogurt »

Sorry, just had some time to look at this; it's been a busy day.

Funny, when I initially envisioned this problem, in my mind's eye, there were some additional steps, but you're right, combined with Roodylib's functionality, that should be fine.

On the other hand, it does draw attention to some behavior on Roodylib's behavior that I'm not entirely happy with. For instance, Roodylib's DoUnlock currently allows the usage of any key object within any parent the player is holding, but it really should only allow platforms or open containers. I should do something about that.

Also, when the player doesn't specifiy a key, it'd be nicer if DoUnlock printed a "(using the skeleton key)"-type message before it goes on to unlock the locked item.

In any case, good work, and thanks for contributing!

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

Post by Roody_Yogurt »

Ok, I updated Roodylib to do these things. Actually, it already was supposed to do the second thing, but my call to RLibMessages was messed-up argument-wise so the messages weren't getting printed.

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

Post by loafingcoyote »

Hey Bainspal! You have a nice start to a key ring object here. I got a chance to test it today and, building on your code, was able to flesh out the concept a bit:

Code: Select all

!!! be sure to include grammar before verblib.g
verb "lock"
	*                                            DoVague
	* lockable "with"/"using" object             DoLock
	* lockable                                   DoLock

verb "unlock"
	*                                            DoVague
	* lockable "with"/"using" object             DoUnlock
	* lockable                                   DoUnlock
!!!
	
global KEYRING_OBJ

object keyring "key ring"
&#123;
	in you
  is platform
    article "a"
    noun "ring", "keyring", "keys"
    adjective "key"
    long_desc
    &#123;
      "A simple, flexible metal loop.";
    &#125;
    before
    &#123;
	    xobject DoPutIn
	    &#123;
		    if object.type ~= key_class
		    &#123;
			    "You can't put ";
			    Art&#40;object&#41;
			    " on ";
			    The&#40;self&#41;
			    "."
			    return true
		    &#125;
		    
		    return false
	    &#125;
    &#125;
    
    capacity 50
    holding 0
&#125;

class key_class
&#123;
	type key_class
	before
	&#123;
		object DoGet
		&#123;
			if Contains&#40;KEYRING_OBJ, self&#41;
			&#123;
				if Contains&#40;player, KEYRING_OBJ&#41;
				&#123;
					"You don't need to take ";
					The&#40;self&#41;
					" off ";
					The&#40;KEYRING_OBJ&#41;
					"."
				&#125;
				else
				&#123;
					"&#40;taking ";
					The&#40;KEYRING_OBJ&#41;
					"&#41;"
					Perform&#40;&DoGet, KEYRING_OBJ&#41;
				&#125;
				
				return true
			&#125;
			
			return false
		&#125;
	&#125;
	after
	&#123;
		object DoGet
		&#123;
			if Contains&#40;player, KEYRING_OBJ&#41;
        	&#123;
        	  move self to KEYRING_OBJ
        	  print "&#40;adding "; The&#40;object&#41;; " to "; The&#40;KEYRING_OBJ&#41;; "&#41;"
        	&#125;
        	
        	return false ! print default TAKE message
    	&#125;
	&#125;
&#125;
Since we removed the "held" token from the verb grammar, it's necessary to replace DoLock/DoUnlock to check if the player actually has the key object. The following code should be added to each.

Code: Select all

	! This is here since we replaced the "held" token with "object"
	if xobject and not Contains&#40;player, xobject&#41;
	&#123;
		ParseError&#40;15, xobject&#41;
		return false
	&#125;
Using the DoLock/DoUnlock verb routines from Roodylib, put the preceding code in near the beginning of each, right before this:

Code: Select all

   if xobject ~= 0
   &#123;
      a = InList&#40;object,key_object,xobject&#41;
      if not a
      &#123;
         VMessage&#40;&DoUnlock, 1&#41;  ! "Doesn't seem to work..."
         return true
      &#125;
   &#125;
You'll recognize plenty of your own code here. The above modifications print the "(adding the brass key to the key ring)" message before "Taken" and keeps the player from being able to take a key and add it back to the key ring over and over. I don't think that's a big deal but, knowing the IF community, they would probably consider it a bug.

It was necessary to replace the grammar since, although the commands "lock door" and "unlock door" work fine, the command "unlock door with brass key" didn't make it past the "held" grammar token.

Something else this modification does is to redirect the command "get brass key" to the key ring if the brass key is on the key ring and the player doesn't have it. Before taking the key ring it will print "(taking the keyring)" so the player doesn't think he's only taking the key object.

The last thing this does is to allow keys to be manually added to the ring. This is only possible when the player picks up a key while not holding the key ring.

-lc

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

Post by Bainespal »

Thanks for fixing and extending that code! I think the solution strikes the right balance between a realistic implementation and meeting the IF community's standards of parser automation to make things easier for the player.

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

Post by Roody_Yogurt »

If you guys think your code is "ready for primetime", I think it'd be good to make pages for them over at Hugo By Example, in the Tips category. LC, I know you have an account, but Bainespal, if you sign up, let me know and I'll give you edit rights.

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

Post by loafingcoyote »

Roody_Yogurt wrote:If you guys think your code is "ready for primetime", I think it'd be good to make pages for them over at Hugo By Example, in the Tips category. LC, I know you have an account, but Bainespal, if you sign up, let me know and I'll give you edit rights.
Hey Roody, I just saw this and think it's an excellent idea. I've been meaning to contribute more at HbE for a long time now anyway.

It's been a few days since I've looked at my code, so I'll take a little time to make sure it's ready and then most likely put it on HbE sometime tomorrow.

-lc

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

Post by Roody_Yogurt »

Nice updates, lc.

Anyhow, I'm also writing here just to share a new "homework" idea. This next one should be fairly easy but should be kind of fun to see down in code.

Now, mazes are considered fairly passe, but one of the least-hated methods for dealing with a maze is that of the "enchanted wobblefiend." Enchanted wobblefiends are objects or characters that lead you through a maze, like the voodoo head in the Secret of Monkey Island.

So, for this assignment, code a maze (or just a maze room template) and an enchanted wobblefiend object that informs the player where to go in each room (preferably with the use of an event- not room long_desc text).

Post Reply