Issue with path finding

how do you get an NPC to path find through an unlocked closed door? the documentation reads:

“The computed path only includes visited rooms, and doesn’t pass through closed doors. But it is straightforward to modify the library to relax those conditions.”

Ha! not straightforward to me.

in this test the NPC will head from one office to another then to a conference room.

#player
(current player *)
(* is #in #office1)

(*(room $) is visited)

#office1
(name *)    the first office
(room *)
(look *)    It's an office.
            (line)(try [exits])
(from * go #south to #hallway1)

#hallway1
(name *)    hallway outside the first office
(room *)
(look *)    It's a hallway.
            (line)(try [exits])
(from * go #north to #office1)
(from * go #east to #hallway2)

#office2
(name *)    the second office
(room *)
(look *)    It's an office.
            (line)(try [exits])
(from * go #south to #hallway2)
(from * go #east through #door to #conference_room)

#door 
(name *)    conference room door
(descr *)   It's a door, currently (open or closed *).
(* is open)
(door *)
(openable *)

#hallway2
(name *)    hallway outside the second office
(room *)
(look *)    It's a hallway.
            (line)(try [exits])
(from * go #west to #hallway1)
(from * go #north to #office2)

#conference_room
(name *)     conference room
(room *)
(look *)    It's a conference room.
            (line)(try [exits])
(from * go #west through #door to #office2)

#johnson
(name *)    Mr. Johnson
(animate *)
(* is #in #office1)
(appearance *) 
            Mr. Johnson is here
(on every tick)
            (#johnson is in room $Here)
            (log){he's in $Here}
            (if)(first step from $Here to #conference_room is $Dir)(then)
            (let * go $Dir)
            (log){he moves $Dir}
            (endif)

it only works, of course, if the door is open.

in stdlib.dg i have tried commenting out:
~($Door blocks passage) in the (elaborate paths from $RoomList) predicate.

this ALMOST works. he’ll start to move but will STOP at the door and won’t go through it to the destination.

can somebody help with this apparently straightforward problem?

1 Like

You have to let the NPC open the door if there is a closed but unlocked one on the path. Also instead of commenting out ~($Door blocks passage), modifying it might be better, otherwise the NPC will try to move towards a locked door, but will not be able to unlock it.

(on every tick)
            (#johnson is in room $Here)
            (log){he's in $Here}
            (if)(first step from $Here to #conference_room is $Dir)(then)
            {
				(let * go $Dir)
			(or)
				(from $Here through $Door to #conference_room)
				($Door is closed)
				($Door is unlocked)
				(let * open $Door)
			}
            (log){he moves $Dir}
            (endif)

(elaborate paths from $RoomList) (just)
	(nonempty $RoomList)
	(collect $R)
		*($Here is one of $RoomList)
		{
			*(from $Here go $ to $R)
			(room $R)
		(or)
			*(from $Here through $Door to $R)
			{ ~($Door blocks passage) (or) ($Door is unlocked) }
		}
		($R is visited)
		~(last hop before $R is $)
		(now) (last hop before $R is $Here)
	(into $NextGen)
	(elaborate paths from $NextGen)

Edit: Or don’t change your (on every tick) code but override the (let $ go $) rule like this:

(let $NPC go $Dir) (just)
	($NPC is in room $OldRoom)
	(if)
		(from $OldRoom through $Door to $NewRoom)
		($Door is closed)
		($Door is unlocked)
	(then)
		(let * open $Door)
	(else)
		(from $OldRoom go $Dir to room $NewRoom)
		(if) (player can see $NPC) (then)
			(narrate $NPC leaving $OldRoom $Dir to $NewRoom)
		(endif)
		(now) ($NPC is #in $NewRoom)
		(if) (player can see $NPC) (then)
			(narrate $NPC entering $NewRoom from $OldRoom)
		(endif)
	(endif)

You still need the override for the (elaborate paths from $) rule.

2 Likes

thanks much.

i used the second way. one small edit.

(let * open $Door) 

should be

(let $NPC open $Door) 

but we’ll let that ride due to your general dialog brilliance.

Good catch! The perils of copy–paste, I fall for that quite often. Since I override the rule right under the #johnson current topic in my code, it works here and I have overlooked it.

Oops, there is another problem with that code, the NPC will open the first door it finds in the room. If there are multiple doors and they pick the wrong door, they can’t continue. This change is needed to fix this (also swapped the order of the if–else logic):

(let $NPC go $Dir) (just)
	($NPC is in room $OldRoom)
	(if)
		(from $OldRoom go $Dir to room $NewRoom)
	(then)
		(if) (player can see $NPC) (then)
			(narrate $NPC leaving $OldRoom $Dir to $NewRoom)
		(endif)
		(now) ($NPC is #in $NewRoom)
		(if) (player can see $NPC) (then)
			(narrate $NPC entering $NewRoom from $OldRoom)
		(endif)
	(else)
		(from $OldRoom go $Dir to $Door)
		(door $Door)
		($Door is closed)
		($Door is unlocked)
		(let $NPC open $Door)
	(endif)
1 Like