building a better DoGo, DoEnter, etc.

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: 2181
Joined: Mon Apr 29, 2002 6:23 pm
Location: Milwaukee

building a better DoGo, DoEnter, etc.

Post by Roody_Yogurt »

So, while working on Clockwork Boy 2, I had the show_commands option on my undolib extension enabled. When the player undo's, the command being undone is printed for the player, along the lines of "[ undoing >GO NORTH ]".

Anyhow, I picked up some odd behavior with DoEnter. Eventually, I noticed that DoEnter has this code:

Code: Select all

	! To prevent endless loops if the player_character class
	! automatically resets the object to in_obj if word[1] = "in"
	word[1] = ""
Now, I've done a handful of little changes to DoGo that I'm not even sure if the above is still a problem. Plus, I think parts of DoEnter and DoGo are so old that they predate hugolib additions like SetupDirectionObjects.

My feeling is that in DoEnter, DoGo, and possibly even DoExit (well, my main feeling for DoExit is that maybe in some cases, it should call DescribePlace after a successful exit) have unnecessary or unrefined code and could use a good looking-over.

Like my checkheld post, this is just a call for people to do what they can to break these routines or make suggestions.

Here is my latest version of DoEnter:

Code: Select all

replace DoEnter
{
#ifclear NO_OBJLIB
	if not object or object in direction
#else
	if not object
#endif
	{
		local i, obj, count
		for i in location
		{
			if i is enterable
			{
				obj = i
				count++
				if count = 2
					break
			}
		}
		if count = 1
		{
			object = obj
		}
		else
		{
			VMessage(&DoEnter, 1)    ! "Be a little more specific..."
			return false
		}

		return Perform(&DoEnter, object)
	}

	! To prevent endless loops if the player_character class
	! automatically resets the object to in_obj if word[1] = "in"
!	word[1] = ""    ! causing problems

	if &object.door_to
		return Perform(&DoGo, object)   ! routine
	elseif object.door_to
		return Perform(&DoGo, object)   ! object

	if object is not enterable or Contains(player, object)
		VMessage(&DoEnter, 2)    ! "You can't enter that."
	elseif player in object
		VMessage(&DoEnter, 3)    ! already in it
	elseif player not in location
		VMessage(&DoGo, 3)       ! "You'll have to get up..."
	elseif object is openable, not open
		VMessage(&DoLookIn, 1)   ! "X is closed."
	else
	{
		move player to object
		if not object.after
			VMessage(&DoEnter, 4)    ! "You get in..."
		object is not quiet
		DescribePlace(location)
		return true
	}
	return
}
(I don't think much is changed with that one)

And DoGo:

Code: Select all

replace DoGo
{
	local moveto, JumpToEnd
#ifset NO_OBJLIB
	local wordnum, m
#endif

	if player not in location               ! sitting on or in an obj.
	{
#ifclear NO_OBJLIB
		if (object ~= parent(player) and not (object in direction and
		parent(player) = location.(object.dir_to))) and
		((object ~= u_obj and parent(player) is platform) or
			(object ~= out_obj and parent(player) is container))
		{
			VMessage(&DoGo, 3)      ! "You'll have to get up..."
			return false
		}
#endif
		local b
		b = parent(player).before	! i.e., a vehicle, etc.
		if b > 1 ! is b a direction?
			return Perform(&DoExit,parent(player))
		elseif b
			return false ! so the error message doesn't take up a turn
	}
	elseif obstacle
	{
#ifclear NO_OBJLIB
		VMessage(&DoGo, 1)		! "X stops you from going..."
		return true
#endif
	}

#ifclear NO_OBJLIB
	! See if the object is one of the current direction set

	if object.type = direction and object in direction
	{
		moveto = object
		JumpToEnd = true
	}
#endif

if not JumpToEnd
{
#ifclear NO_OBJLIB
	if not moveto
	{
#else
	wordnum = 1                             ! various phrasings
	if words > 1 and word[2] ~= ""
		wordnum = 2
	if word[2] = "to", "through"
		wordnum = 3
	elseif (word[2] = "in" or word[2] = "inside") and words > 2
		wordnum = 3

	select word[wordnum]
		case "north", "n":      m = n_to
		case "south", "s":      m = s_to
		case "east", "e":       m = e_to
		case "west", "w":       m = w_to
		case "northwest", "nw": m = nw_to
		case "northeast", "ne": m = ne_to
		case "southeast", "se": m = se_to
		case "southwest", "sw": m = sw_to
		case "up", "u":         m = u_to
		case "down", "d":       m = d_to
		case "in", "inside":    m = in_to
		case "out", "outside":  m = out_to

	if not m
	{
#endif
		if not object
		{
			! ParseError(6)  ! doesn't make any sense
			VMessage(&DoGo, 4)	! "Which way...?"
			return
		}

		if not &object.door_to
		{
			if not object.door_to and object is enterable
				return Perform(&DoEnter, object)
		}

		moveto = object.door_to
		if not moveto
		{
			VMessage(&DoEnter, 2)  ! "You can't enter..."
			return
		}
		if moveto = 1
			return true
	}
}  !  if not JumpToEnd bracket

#ifclear NO_OBJLIB
	if moveto.type = direction and moveto in direction
	{
		if player not in location and object = out_obj
		{
			if parent(player) is platform
			{
				VMessage(&DoGo, 3)
				return false
			}
			else
				return Perform(&DoExit)
		}
		elseif player not in location and object = u_obj
		{
			if parent(player) is container
			{
				VMessage(&DoGo, 3)
				return false
			}
			else
				return Perform(&DoExit, parent(player))

		}

		if not object
		{
			object = moveto
			if object.before
				return true
		}
!		else:  object = moveto
		moveto = location.(moveto.dir_to)

		if &moveto.door_to or moveto.type = door
		{
			moveto = moveto.door_to
		}
		elseif moveto is enterable and
		((moveto is platform) or (moveto is container)) and
		player in location
			return Perform(&DoEnter, moveto)
	}
#else
	if m
	{
		if player not in location and m = out_to
		{
			if parent(player) is platform
			{
				VMessage(&DoGo, 3)
				return false
			}
			else
				return Perform(&DoExit)
		}
		elseif player not in location and m = u_to
		{
			if parent(player) is container
			{
				VMessage(&DoGo, 3)
				return false
			}
			else
				return Perform(&DoExit, parent(player))
		}

		moveto = location.m
		if moveto.door_to
			moveto = moveto.door_to
	}
#endif

	if moveto = false
	{
		if not location.cant_go
			VMessage(&DoGo, 2)      ! "You can't go that way."
		return false
	}

	elseif moveto = true                    ! already printed message
		return true                     ! (moveto is never 1)

	elseif player not in location           ! sitting on or in an obj.
	{
		if parent(player) = moveto
			VMessage(&DoEnter, 3)    ! already in it
		else
			VMessage(&DoGo, 3)              ! "You'll have to get up..."
	}
	else
	{
!\ Recursive call issues
		m = verbroutine                 ! check room exiting
		verbroutine = &DoExit
		if location.before
			return true
		verbroutine = m
\!
		MovePlayer(moveto)

		return true
	}
}
Most recently, I added code to properly direct to the "you're already there"-type when you type "in" while already in an enterable object. I also added some code so that having a room exit like "in_to wardrobe", where wardrobe is an enterable object and not a room, calls DoEnter and doesn't just use MovePlayer to move the player.