Fun with Doors

K.V.

Hello!

I am playing with doors today.

(Can you say "doors"? Good! I knew you could!!!)


First, I shall go by the docs.

I shall create a game, going by this:
http://docs.textadventures.co.uk/quest/setting_up_door.html

The code:

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Setting Up a Door">
    <gameid>ca59e082-5ff5-4efe-b0b5-253efd93432b</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <feature_advancedscripts />
    <scopebackdrop type="script">
      if (game.pov.parent = kitchen) {
        list add (items, door)
      }
    </scopebackdrop>
    <description><![CDATA[Example game.<br/><br/>Code from:  http://docs.textadventures.co.uk/quest/setting_up_door.html]]></description>
    <author>textadventures</author>
    <subtitle>(Code entered by K.V.)</subtitle>
  </game>
  <object name="lounge">
    <inherit name="editor_room" />
    <description>The lounge is very retro. The door west is {either door.isopen:open|closed}.</description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <exit name="exit to kitchen" alias="west" to="kitchen">
      <inherit name="westdirection" />
      <locked />
      <lockmessage>The door is closed.</lockmessage>
    </exit>
    <object name="door">
      <inherit name="editor_object" />
      <inherit name="openable" />
      <scenery />
      <feature_container />
      <openscript type="script">
        exit to kitchen.locked = false
        exit to lounge.locked = false
        this.isopen = true
      </openscript>
      <closescript type="script">
        exit to kitchen.locked = true
        exit to lounge.locked = true
        this.isopen = false
      </closescript>
    </object>
  </object>
  <object name="kitchen">
    <inherit name="editor_room" />
    <description>The kitchen is very small. The door east is {either door.isopen:open|closed}.</description>
    <exit name="exit to lounge" alias="east" to="lounge">
      <inherit name="eastdirection" />
      <locked />
      <lockmessage>The door is closed.</lockmessage>
    </exit>
  </object>
</asl>

Setting Up a Door - Play online


That works as intended, but...

I prefer the way doors work in the classic games.

Specifically, if a door is closed (but not locked), you automatically open it when going through it.

Inform 7 makes it quite easy to handle doors.

...and, before you say, "well, go use Inform, then," allow me to retort in advance: I don't want to. I'd rather use Quest. Hence this experiment.

I'm just showing that this is easy to do with other software.

...and anything can be done with Quest, you know. (Ahem.) I just want Quest to be all that it can be. (You know. Like the U.S. Army? (Remember that jingle?)) Anyway...

Here's an example Inform 7 game's entire code:

"Setting Up a Door" 

The Lounge is a room.  

The description of lounge is "The lounge is very retro.[paragraph break]You can go west.".

West from the lounge is a door called an exit1.  

The printed name of exit1 is "door".   

Understand "door" as exit1.

Description of exit1 is "It is [if exit1 is open]open[else]closed[end if].".

The Kitchen is west from exit1.

Description of kitchen is "The kitchen is very small.[paragraph break]You can go east.".

The output:


Lounge
The lounge is very retro.

You can go west.

You can see a door here.

>w
(first opening the door)

Kitchen
The kitchen is very small.

You can go east.

You can see a door here.

>

Setting Up a Door (gblorb)- Play online


Quest Can Do That!

Setting Up a Door (Version 2)

I changed quite a few things in the first example.

I lost the code with the locked exits, and I added scripts to the exit instead.

It's really the same script on both exits:

if (not GetBoolean(door,"locked")) {
  if (not door.isopen) {
    door.isopen = true
    msg ("(You open the door first.)")
  }
  game.pov.parent = this.to
}
else {
  msg ("The door is locked.")
}

This now behaves just like an INFOCOM game would.

Example game code:

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Setting Up a Door (Version 2)">
    <gameid>395830cf-795d-48f1-a85b-01fd3a7540cd</gameid>
    <version>2.3</version>
    <firstpublished>2018</firstpublished>
    <feature_advancedscripts />
    <description><![CDATA[Example game.<br/><br/>Code from:  http://docs.textadventures.co.uk/quest/setting_up_door.html<br/><br/>Modified by K.V.]]></description>
    <author>K.V.</author>
    <subtitle type="string"></subtitle>
    <attr name="autodescription_description" type="int">2</attr>
    <attr name="autodescription_youcango" type="int">4</attr>
    <attr name="autodescription_youcansee" type="int">3</attr>
    <attr name="autodescription_youarein_useprefix" type="boolean">false</attr>
    <autodescription_youcango_newline />
    <scopebackdrop type="script">
      if (game.pov.parent = kitchen) {
        list add (items, door)
      }
    </scopebackdrop>
  </game>
  <object name="lounge">
    <inherit name="editor_room" />
    <description><![CDATA[The lounge is very retro. <br/>]]></description>
    <usedefaultprefix type="boolean">false</usedefaultprefix>
    <alias>Lounge</alias>
    <enter type="script">
      msg ("You can see a  {object:door}.")
      door.scenery = false
    </enter>
    <beforeenter type="script">
      door.scenery = true
    </beforeenter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <exit name="exit to kitchen" alias="west" to="kitchen">
      <inherit name="westdirection" />
      <message type="string"></message>
      <runscript />
      <script type="script">
        if (not GetBoolean(door,"locked")) {
          if (not door.isopen) {
            door.isopen = true
            msg ("(You open the door first.)")
          }
          game.pov.parent = this.to
        }
        else {
          msg ("The door is locked.")
        }
      </script>
    </exit>
    <object name="door">
      <inherit name="editor_object" />
      <inherit name="openable" />
      <feature_container />
      <look>It is {either door.isopen:open|closed}.</look>
      <displayverbs type="stringlist">
        <value>Look at</value>
        <value>Open</value>
        <value>Close</value>
      </displayverbs>
      <takemsg>It's fixed in place.</takemsg>
      <attr name="enter_verb" type="script">
        if (not GetBoolean(this,"locked")) {
          if (not this.isopen) {
            this.isopen = true
            msg ("(You open it first.)")
          }
          if (game.pov.parent = lounge) {
            game.pov.parent = kitchen
          }
          else {
            game.pov.parent = lounge
          }
        }
        else {
          msg ("It is locked.")
        }
      </attr>
      <openscript type="script">
        if (not GetBoolean(this,"locked")) {
          this.isopen = true
          msg ("Opened.")
        }
        else {
          msg ("It is locked.")
        }
      </openscript>
      <closescript type="script">
        this.isopen = false
        msg ("Closed.")
      </closescript>
    </object>
  </object>
  <object name="kitchen">
    <inherit name="editor_room" />
    <description><![CDATA[The kitchen is very small. <br/>]]></description>
    <usedefaultprefix type="boolean">false</usedefaultprefix>
    <alias>Kitchen</alias>
    <enter type="script">
      msg ("You can see a  {object:door}.")
    </enter>
    <exit name="exit to lounge" alias="east" to="lounge">
      <inherit name="eastdirection" />
      <runscript />
      <script type="script">
        if (not GetBoolean(door,"locked")) {
          if (not door.isopen) {
            door.isopen = true
            msg ("(You open the door first.)")
          }
          game.pov.parent = this.to
        }
        else {
          msg ("The door is locked.")
        }
      </script>
    </exit>
  </object>
  <verb name="enter_verb">
    <pattern>enter #object#</pattern>
    <defaultexpression>"You can't enter " + object.article + "."</defaultexpression>
    <property>enter_verb</property>
  </verb>
</asl>

Setting Up a Door (Version 2) - Play online


NEXT TIME ON FUN WITH DOORS:

Making the door lockable


Could you apply this to every door in the game with a simple start script or would you need to use this for every door you have? Just curious.


Quite apart from the fact that KV's code works splendidly, I wonder why you install a door when it opens itself. OK, if the doors are locked, I can understand, there's something else you have to do with it. But doors just to walk through?


K.V.

Could you apply this to every door in the game with a simple start script or would you need to use this for every door you have?

The door would need to know which room you were in and which exit's script to run.

I wonder why you install a door when it opens itself. OK, if the doors are locked, I can understand, there's something else you have to do with it. But doors just to walk through?

This is just the base to build upon. I'll be making the door lockable tomorrow.

...but this is also just for atmosphere.

Plus, if you mention a door in a game, I believe there should be a functional door to interact with, and that everything concerning said door should make sense.

Those who grew up playing the same text adventures as yours truly are accustomed to the pointless doors, too. Anything else seems... different.

Also (as a silly example), there may be a scenario where you need to close the door to keep out an animal (or the weather). This way, you could still just exit the room without the hassle of having to open the door. But, if you didn't close it on the way out, the animal (or the weather) would creep into the room and wreak havoc.


Could you somehow put a global code in and refer to any object with the alias “door” and if “visible” that handles that? I guess that would screw stuff up if there are two doors in the same room, huh? Just thinking out loud. Perhaps I shouldn’t? Lol


I'd assume that each door would have attributes referring to the other side of the door, and to the exit.

door.changedisopen => {
  this.otherside.isopen = this.isopen
  if (this.isopen) {
    // may as well change the 
    this.exit.script = null
  }
  else {
    this.exit.script = this.exit.openandgo
  }
}
door.changedlocked => {
  this.otherside.locked = this.locked
  this.exit.locked = this.locked
}
exit_with_door.openandgo => {
  if (not GetBoolean(this.door, "isopen")) {
    TryOpenClose (true, this.door)
  }
  if (GetBoolean(this.door, "isopen")) {
    game.pov.parent = this.to
  }
}

(also, one that I've already used versions of)

door.changedparent => {
  this.exit.parent = this.parent
  this.otherside.to = this.parent
}
door.changedto => {
  this.exit.to = this.to
  this.otherside.parent = this.to
}

(just in case a wizard decides to start moving exits around; having the doors and exits move as a unit is going to save a lot of errors)

Though… I'm not sure why there's a separate door object. Can't the door and the exit be the same object? I half remember seeing code that causes an exit to be treated like a 'real' object if it has displayverbs, but I can't remember what circumstances that applies in.


Though… I'm not sure why there's a separate door object. Can't the door and the exit be the same object? I half remember seeing code that causes an exit to be treated like a 'real' object if it has displayverbs, but I can't remember what circumstances that applies in.

That would be nice!


K.V.

Could you somehow put a global code in and refer to any object with the alias “door” and if “visible” that handles that? I guess that would screw stuff up if there are two doors in the same room, huh?

I'm working on a library right now.

In order to keep from messing things up, the game creator will have a 'Door Settings' tab with a few options to set up.


I'd assume that each door would have attributes referring to the other side of the door, and to the exit.

I've done that in other games, but I'm just using a single door and adding it to the scopebackdrop in this example. It is scripted to know the two exits it could be representing, though.

I've also had one door that moved with to the adjacent room before. That worked just as well as two doors with change scripts on the necessary attributes.

I prefer the "two doors that appear to be one door" method. My plan was to kick these examples off with basic scripts, then make things more complicated as we go along.


Can't the door and the exit be the same object? I half remember seeing code that causes an exit to be treated like a 'real' object if it has displayverbs

This would be super-sweet! (At least I think it would. We wouldn't be able to just click on a link to go, though. Unless we made one directional exit and one 'door' exit with a menu when clicking the link. ...which would be as much work as creating an exit and a door... Hrmm...)

I tried adding a look script to an exit, but it says I can't see that.

Even when you make an exit "look only", you still can't examine it. That just allows you to enter your own string to print when the player enters LOOK #direction#. If you don't set up look only exits for each direction, it will just say "You look "+direction+"."

I did NOT try adding a display verb though...

I shall look into that.


Now I think about it, that's probably a neat way to avoid having excessive numbers of door objects around. You could have a couple of door objects that are placed in scope, or are moved to wherever the player is by the enterroom script. Maybe have the script clone the door as many times as is necessary for the exits in the room.

I'm imagining a 'door' tab on the exit, with a checkbox "is a door", and a space for an adjective or alias (default is the exit's alias). So your enterroom and/or scope script could create a couple of door clones and alias them "east door", "wooden west door", "metal west door". The open/locked status of the doors would be tied to that of the exit, so unlocking the door unlocks the exit too.


K.V.

I've got a library created. I only need to polish up the scripts concerning doors that can be unlocked from one side but not from the other.

Gotta run to town real quick now, but I'll be posting a link soon.


I might also go with what mrangel just suggested, making it so it keeps track of which key works which door, depending on the game.pov.parent.


going off of 'mrangel' post:

I too feel that the best design would be to have a single door object (as more doors are just redundant objects) (and this applies to all types of objects too, not just doors, lol), which handles all it uses/applications within the game, similar to my thread asking for any help/advice/feedback/code/design for a 'menu system', I've just created (I'm currently and still working on character creation, and most of that gets solved with creating/completing a menu system, so I made a thread hoping to get whatever help/advice/ideas/feedback/coding/designs/etc I can from others, as I try to get some satisfactory design for a menu system on my own in the meantime, lol).


K.V.

Here's a link to the post concerning the library.


I think my method, having given it a bit more thought, would be to have the library create door objects as they're needed. That way, any custom behaviour (like doors that are only locked in one direction) can be represented by attributes/scripts attached to the exits themselves; and checked/called by the scripts on the door objects. From the point of view of someone using the library, it acts as if the library adds features to the exit; and the door objects are entirely transparent.


K.V.

That's exactly what my library does.

(If we separately decided that would be the best method in the end, it can't be wrong! (Can it?))


image

image

http://textadventures.co.uk/forum/samples/topic/zhv4fj1xvks2s5poao3c2a/doorlib#ec9281a5-c607-4600-8b49-eb3f7a6adcda

https://gist.github.com/KVonGit/fff1a46e758d5b3859075256a5253ec2


PS

I just fixed the typo in the note under "Locking".

If anyone sees any other errors (or notices something I've left out), please let me know.


"this will overwrite any existing exit script" :p

I always try to avoid those cases. How about…

Before you set exit.script => { etc, have exit.script_after_door_open = exit.script. And then in the exit script, replace game.pov.parent = this.to with:

  if (HasScript(this, "script_after_door_open")) {
    do(this, "script_after_door_open")
  }
  else {
    game.pov.parent = this.to
  }

That way, any existing exit scripts still get run.


K.V.

Hot damn! That's a good idea!

(Pardon my French.)

I thought about something along those lines for a second, but decided any existing exit scripts may coincide with the replacement.

I can't think of any possible paradoxes now, though...


EDIT

What if there was an exit script set up that moved the player before (or after) the door's exit script moved the player?

I think it might be safer to add the message:

"If you wish to do fancy things in your exit script, create your own door object and set up the exit's script manually."


ANOTHER EDIT:

Or I could put all of that on a type, and have the exit inherit the type when selecting 'Has a door' from a drop-down menu.

Then, they could go into the attributes and change those attributes once the exit has inherited them.

Nah...

I think putting a note that you need to set up a door object and code the exit script yourself if you want things to behave differently is the best option.

I'm setting up all sorts of things that work together to make these doors and exits work together without offering an easy way to add some unknown script into the mix.


the same is done with 'templates' in Pixie's libraries and chase's 'wearables' (equipment) library (pixie used some of this for his equipment library):

pseudocode (I've not studied template usage/coding yet):

if has template, do template message/whatever
else, do normal/custom message/whatever

and also with some of quest's built-in stuff using (pseudocode):

if script, run script
else, do normal message/response: msg/look/etc-verbs-commands (string)


K.V.

This is the current exit script when you have an 'opening door' message:

(EDITED)

  if (GetBoolean (exit,"hasdoormsg")){
	exit.runscript = true
	exit.doormsg = "(You open the door first.)"
	if (HasString(exit,"customdoormsg")){
	  if (not exit.customdoormsg = "") {
		exit.doormsg = exit.customdoormsg
	  }
	}
	exit.script => {
	  if (not GetBoolean(this.door,"locked")) {
		if (not this.door.isopen) {
		  this.door.isopen = true
		   msg (this.doormsg)
		   if (HasAttribute(this.door,"otherside")){
			 if(GetBoolean(this.door.otherside,"locked")){
			   msg("The door closes behind you.")
			   this.door.isopen = false
			 }
		   }
		}
		game.pov.parent = this.to
	  }
	  else {
		msg ("The door is locked.")
	  }
	}
  }


What if there was an exit script set up that moved the player before (or after) the door's exit script moved the player?

The door's exit script is the one that is called first. The exit's original exit script is called after the door has been opened (if it isn't locked). If there is an original exit script, then it is responsible for moving the player.


K.V.

Oh!!!

Sorry. You explained it perfectly the first time, with attached code. I was just reading too quickly, and that isn't actually reading, is it?

So, like this?

EDITED

if (HasScript(exit,"script")) {
  exit.script_bak = exit.script
}
exit.script => {
  if (not GetBoolean(this.door,"locked")) {
    if (not this.door.isopen) {
      this.door.isopen = true
      msg (this.doormsg)
      if (HasAttribute(this.door,"otherside")) {
        if (GetBoolean(this.door.otherside,"locked")) {
          msg ("The door closes behind you.")
          this.door.isopen = false
        }
      }
    }
    if (HasAttribute(this,"script_bak")) {
      do (this, "script_bak")
    }
    else {
      game.pov.parent = this.to
    }
  }
  else {
    msg ("The door is locked.")
  }
}

Wouldn't the creator still need to add the door message script to the exit's script if altering it during play? (If so, I could change my note in the editor to convey that message.)


Yeah; there should be a note that if you need to modify the exit's script during play, you need to modify script_bak instead. But the majority of cases, at least, it works transparently.

... now my brain's coming up with something quite silly:

exit.exit_with_door => {
  [...] the exit script
}
exit.changedscript => {
  if (not this.script = this.exit_with_door) {
    if (HasScript(this, "script")) {
      this.script_bak = this.script
    }
    else {
      this.script_bak = null
    }
    this.script = this.exit_with_door
  }
}
do (exit, "changedscript")

K.V.

That is a good idea!

// Script in progress
// This is where the script begins to deal with the exit script
//<!--
// 1. Back up any existing script first (this runs at startup, so any exit script set up during editing will still run)
//-->
if (HasAttribute(exit,"script")){
  exit.script_bak = exit.script
}
//<!--
// 2. Set up the required exit script as 'exit_with_door' so it can be accessed if the script is changed during play
//-->
exit.exit_with_door => {
  if (GetBoolean(this.door,"locked")) {
    msg ("The door is locked.")
  }
  else {
    if (not this.door.isopen) {
      this.door.isopen = true
      msg (this.doormsg)
      if (HasAttribute(this.door,"otherside")) {
        if (GetBoolean(this.door.otherside,"locked")) {
          msg ("The door closes behind you.")
          this.door.isopen = false
        }
      }
    }
    // If the user created an exit script, run it instead of just moving the player.
    if (HasAttribute(this,"script_bak")) {
      do (this, "script_bak")
    }
    else {
      game.pov.parent = this.to
    }
  }
}
//<!--
// 3. Set the 'exit_with_door' script up as the actual exit script
//-->
exit.script = exit.exit_with_door
//<!--
// 4. Safety control: if the player changes the exit script during play, this will restore the exit_with_door script, and run the new script after dealing with doors.
// NOTE: The original script_bak will be lost, but this would happen if this was just a normal script that was changed during play.
//-->
exit.changedscript => {
  if (not this.script = this.exit_with_door) {
    if (HasScript(this, "script")) {
      this.script_bak = this.script
    }
    else {
      this.script_bak = null
    }
    this.script = this.exit_with_door
  }
}

K.V.

This is just to keep from running into an error if the script attribute is changed to something other than a script; correct?

if (HasScript(this, "script")) {
      this.script_bak = this.script
    }
    else {
      // This is not a script!  DELETE IT!!!
      this.script_bak = null
    }

This is just to keep from running into an error if the script attribute is changed to something other than a script; correct?

Yep. It also means that the final line do (exit, "changedscript") will set up the initial values of both script and script_bak correctly whether or not the exit already has a script. Though I think you've chosen to do that manually instead.

(I've been poking a library for my own use that provides AddScriptAttribute and RemoveScriptAttribute functions. If there's already a script there it puts the scripts into a list and then sets the actual script attribute to its own script that iterates over them. This is probably why I rarely finish anything)


K.V.

the final line do (exit, "changedscript") will set up the initial values of both script and script_bak correctly whether or not the exit already has a script.

I was going to ask about that. I see now, though. I was thinking about what that would do during play, but that's just going to run during the door creation process.


Though I think you've chosen to do that manually instead.

I see why I was confused now.

I think I recently added the bit where it backs up the exit's script early on in the door creation process.


AddScriptAttribute and RemoveScriptAttribute functions.

If there's already a script there it puts the scripts into a list and then sets the actual script attribute to its own script that iterates over them.

> steal mrangel's functions
Stolen.


This is probably why I rarely finish anything

You and me both!

At least you finish your short stories! (Or at least some of them. You probably have some 'trunk novels', abandoned projects, etc.)

I've got around 50 unfinished tales. (I do plan to finish about ten of them, though.)

(Maybe I should start outlining a story before I begin writing. Nah! Then I'd know how it was going to end, so I'd have no reason to finish!)

Getting stuck while writing one of my stories is actually what made me get into creating text adventures.

I created the world, then dropped all the players into it, exactly where the story trailed off, and I (almost literally) dove into the story.

I know what happens in that particular tale now. If I can ever stop playing with Quest, I shall write the rest of it! (Bwahahahaha!)


At least you finish your short stories! (Or at least some of them. You probably have some 'trunk novels', abandoned projects, etc.)

Starting October 2nd 2014 (I think; could have been 2015) I started a short story every day for 444 days. Finished about half of them, and probably only half of those were finished the same day. That's why I'm managing to put out so many short story collections. (New one uploaded this morning, on pre-order for next week. Still drawing on the same pool of stories)


In re-implementing an old game that mentioned doors in almost every location, I had to insert over 100 scenery door objects. They mostly had the same description "A plain internal door with no lock". Copy and paste meant that the objects could be added quickly but I implemented 'open' and 'use' to take the player automatically through the doors which meant setting up the target location in each case. It would have been nice if I'd been able to describe an 'exit' as a 'door' so that 'go east', 'open east door' and 'use east door' all had the same effect...but oh well, it's done now!

In following this discussion, I remembered that rooms can be described as 'room and/or object' and was expecting that if, for example, I was in the 'old kitchen' (name of the room), and said it was a 'room and/or object' I would be able to 'examine kitchen' and get the description set up for it. Alas, it just says the usual 'I can't see that'! What is this feature for?


K.V.

I believe it's for enterable objects which are found in a room.

The look attribute is for when you examine it from outside.

The description is for the inside (or room) description.


I have thought about adding a scenery object with the same alias as the room to each room. The look script would just call ShowRoomDescription.

(I've seen quite a few people playing text adventures who tried to X KITCHEN while they were in the kitchen. It is a logical thing to try.)


I've seen quite a few people playing text adventures who tried to X KITCHEN while they were in the kitchen. It is a logical thing to try.

I agree but adding a scenery object for each room feels unsatisfactory when effectively there is already an object describing the room. The modern expectation seems to be that every item mentioned should be examinable, which would include the room and any exits mentioned.


K.V.

every item mentioned should be examinable, which would include the room and any exits mentioned

I try to make this happen.

"I can't see that."

Grrr...

Back in the day, they didn't have enough space to fit all of that text into the game, but it's just laziness nowadays.

I would make a gamebook if I didn't feel like creating every object I mentioned in the prose.

...but I've been called unpleasant things for paying too much attention to the details my whole life, so... there's that.


adding a scenery object for each room feels unsatisfactory when effectively there is already an object describing the room.

This is where the plot thickens.

We have a new feature which allows us to control the scope of a command.

This modified lookat command will show the room description, objects list, and exits list.

  <command name="lookat">
    <pattern>look at #object#; look #object#; x #object#; examine #object#; exam #object#; ex #object#</pattern>
    <script>
      if (GetBoolean(object, "hidechildren")) {
        object.hidechildren = false
      }
// START OF FIRST SECTION ADDED 
      if (object = game.pov.parent) {
        bak = game.autodescription_youarein
        game.autodescription_youarein = 0
        ShowRoomDescription
        game.autodescription_youarein = bak
      }
//  END OF FIRST SECTION (CHANGED NEXT LINE TO ELSE IF)
      else if (TypeOf(object, "look") = "script") {
        do (object, "look")
      }
      else {
        lookdesc = ""
        if (HasString(object, "look")) {
          lookdesc = object.look
        }
        if (LengthOf(lookdesc) = 0) {
          lookdesc = Template("DefaultObjectDescription")
        }
        if (GetBoolean(object, "switchedon")) {
          if (HasString(object, "switchedondesc")) {
            lookdesc = lookdesc + " " + object.switchedondesc
          }
        }
        else {
          if (HasString(object, "switchedoffdesc")) {
            lookdesc = lookdesc + " " + object.switchedoffdesc
          }
        }
        isDark = CheckDarkness()
        if (isDark and not GetBoolean(object, "lightsource")) {
          lookdesc = DynamicTemplate("LookAtDarkness", object)
        }
        msg (lookdesc)
      }
      ListObjectContents (object)
    </script>
<!-- START OF SECOND SECTION ADDED -->
    <changecommandscope type="script">
      list add (items, game.pov.parent)
    </changecommandscope>
<!-- END OF SECOND SECTION ADDED -->
  </command>

http://docs.textadventures.co.uk/quest/advanced_scope.html


You could (I think) even allow things like "examine room" without having an object for each... have a regex pattern something like ^(look ?(at)?|x|exam|examine)\s+((?<text>around|room|self|floor|sky|pockets|ceiling|busy|)|(?<object>.+))$
Then the script...

if (IsDefined("text")) {
  switch(Trim(LCase(text))) {
    case ("", "room", "around") {
      object = game.pov.parent
    }
    case ("self") {
      object = game.pov
    }
    case ("pockets") {
      do (inventory, "script")
    }
    case ("busy") {
      msg ("Why? Is the boss coming?")
    }
    default {
      if (HasString(game.pov.parent, text+"desc")) {
        msg (GetString(game.pov.parent, text+"desc"))
      }
      else if (HasScript(game.pov.parent, text+"desc")) {
        do (game.pov.parent, text+"desc")
      }
      else {
        msg ("The "+text+" here looks pretty ordinary")
      }
    }
  }
}
if (IsDefined("object")) {
  [...] everything else here
}

Thanks guys, I'll experiment!


...sorry, struggling to fit this together! Can you put the code into a complete game and send it to me at ...?
Thanks!!


K.V.

<game name="You Can X the Room!">

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="You Can X the Room!">
    <gameid>eb50d167-bd03-4f23-9908-48369a7083f5</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
  </game>
    <command name="lookat">
    <pattern>look at #object#; look #object#; x #object#; examine #object#; exam #object#; ex #object#</pattern>
    <script>
      if (GetBoolean(object, "hidechildren")) {
        object.hidechildren = false
      }
// START OF FIRST SECTION ADDED 
      if (object = game.pov.parent) {
        bak = game.autodescription_youarein
        game.autodescription_youarein = 0
        ShowRoomDescription
        game.autodescription_youarein = bak
      }
//  END OF FIRST SECTION (CHANGED NEXT LINE TO ELSE IF)
      else if (TypeOf(object, "look") = "script") {
        do (object, "look")
      }
      else {
        lookdesc = ""
        if (HasString(object, "look")) {
          lookdesc = object.look
        }
        if (LengthOf(lookdesc) = 0) {
          lookdesc = Template("DefaultObjectDescription")
        }
        if (GetBoolean(object, "switchedon")) {
          if (HasString(object, "switchedondesc")) {
            lookdesc = lookdesc + " " + object.switchedondesc
          }
        }
        else {
          if (HasString(object, "switchedoffdesc")) {
            lookdesc = lookdesc + " " + object.switchedoffdesc
          }
        }
        isDark = CheckDarkness()
        if (isDark and not GetBoolean(object, "lightsource")) {
          lookdesc = DynamicTemplate("LookAtDarkness", object)
        }
        msg (lookdesc)
      }
      ListObjectContents (object)
    </script>
<!-- START OF SECOND SECTION ADDED -->
    <changecommandscope type="script">
      list add (items, game.pov.parent)
    </changecommandscope>
<!-- END OF SECOND SECTION ADDED -->
  </command>
  <object name="room">
    <inherit name="editor_room" />
    <description><![CDATA[This is the main room's description.<br/><br/>I would have written something funny here, but I couldn't come up with anything.<br/>]]></description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <exit alias="north" to="second room">
      <inherit name="northdirection" />
    </exit>
  </object>
  <object name="second room">
    <inherit name="editor_room" />
    <description><![CDATA[This is the description of the second room. <br/><br/>(If you can read this, you must be bored.)<br/>]]></description>
    <exit alias="south" to="room">
      <inherit name="southdirection" />
    </exit>
  </object>
</asl>

I emailed it, too (for some reason; I'm crazy).

If I were you, I'd edit my email address out of that post before Google takes a snapshot of this page. All the spam-bots will share your info with each other!

(I advise only sharing email addresses via PM. This is just based on my experience.)


Thanks KV. I've edited out my email address and copied the code into one of my games to see if there are any unexpected side effects. Will report back later...


K.V.

Thanks KV. I've edited out my email address and copied the code

Word up.

Let us know, please, sir.


I seriously got a butt-load of emails when I dropped my old address in a post one time.

If anyone else wishes to share some code with you via email, I'm thinking they'll just shoot you a PM, asking for your address.


You could (I think) even allow things like "examine room" without having an object for each... have a regex pattern something like ^(look ?(at)?|x|exam|examine)\s+((?<text>around|room|self|floor|sky|pockets|ceiling|busy|)|(?<object>.+))$

Hey, this is a neat idea!

You don't even have to alter the existing lookat for this one. You can just add this with a different name, with a slightly modified RegEx pattern and script.

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="lookat (lookat code by mrangel)">
    <gameid>de34b7f4-5295-481e-b035-e7ed252fc0c1</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="placeholder">
      <inherit name="editor_object" />
    </object>
  </object>
  <command name="newlookat">
    <pattern type="string"><![CDATA[^(look ?(at)?|x|exam|examine)\s+(?<text>around|room|self|floor|sky|pockets|ceiling|busy|)$]]></pattern>
    <script>
      switch (Trim(LCase(text))) {
        case ("", "room", "around") {
          object = game.pov.parent
        }
        case ("self") {
          object = game.pov
        }
        case ("pockets") {
          do (inventory, "script")
        }
        case ("busy") {
          msg ("Why? Is the boss coming?")
        }
        default {
          if (HasString(game.pov.parent, text+"desc")) {
            msg (GetString(game.pov.parent, text+"desc"))
          }
          else if (HasScript(game.pov.parent, text+"desc")) {
            do (game.pov.parent, text+"desc")
          }
          else {
            msg ("The "+text+" here looks pretty ordinary")
          }
        }
      }
    </script>
  </command>
</asl>

Will report back later...

That seemed to work well in my game. The only 'problem' was a few name clashes which brought up the menu but that is what would have happened anyway if I'd added a new object for each location.

It feels wrong to be redefining 'examine' so perhaps there is a case for making this code the new default?


...sorry, there a problem! The room really needs to be a recognisable object regardless of the operation applied to it:

You are in an old kitchen.
: x kitchen
You are in an old kitchen.
:search kitchen
I can't see that. (kitchen)


K.V.

It feels wrong to be redefining 'examine'

That's what Quest is all about!

Modify those scripts! Make your game stand out!

(Why am I yelling?!?!)

Just be sure to include the instructions when entering HELP (or something like that).


perhaps there is a case for making this code the new default?

I'm not in charge of anything (just a Quest user), but I have created a few pull requests with code that changed the way the default commands worked and have been enlightened a bit as to how things may effect game creators...

One scenario:

You have been writing a game for months (maybe even years).

You have gone through the trouble of adding a scenery object in each room with an alias which matches the room's alias, just so people can X the room.

You've also gone out of the way to make sure no items which could be in scope simultaneously have similar aliases, hence avoiding the player ever seeing the disambiguation menu.

You open Quest. It says there's an updated version of Quest. So, you update.

Now, when you load your game, press 'Play', and enter X ROOM, it says:

Which do you mean?
1. a room
2. a room


It's also important to note here that any published game (meaning a .quest file as opposed to an .aslx file) which was published before an update to Quest would not be effected by any changes made to a built-in command.

When you compile the game, Quest adds all the functions to your game's code.

This is also the case if you have copied a default command into your game.

So, if you had this modified lookat command in a game right now, then Pixie updated the lookat command in Quest, you could open that game in the updated version of Quest and your modified lookat command would still be what your game used.

Alternatively, any existing .aslx files without a lookat command copied to the main game's code would use Quest's built-in command.

So... to avoid all of this possible confusion, it seems that the default stuff is only altered when:
A. It's a bug fix
B. It wouldn't effect games people are currently editing

...and, to make it so we can still pretty much do whatever we wish to our own games, we can modify (or add) whatever code we wish on our end.

(NOTE: I'm not just explaining this to you. You probably already know most (if not all) of this. This is just for any new folks who may be reading this. (I'm really bored today.))


Now that I've rambled on incessantly (sorry), I'll share this:

LookAtRoomLib.aslx

It's almost as much work to include this library as it would be to just copy the code into full code view, but not quite.


mrangel's method is pretty nice, too.

You'd have to custom tailor it a little, but not much.

Plus, you can add an attribute to the room on the fly, and his script will either print the string value of that attribute, or run its script, depending on its type.


I guess the conclusion here is that while exits and rooms look like objects to modern players, when Quest was first developed that probably wasn't the case. At this stage, rather than modify Quest, it is probably easier to just add objects for these items, and it does have the advantage of providing greater control. I'll do that in my next game updates. Thanks for the discussion!


K.V.

>search kitchen
I can't see that. (kitchen)

I missed this post.

When you say:

it is probably easier to just add objects for these items, and it does have the advantage of providing greater control.

You are correct.

Letting us examine things we can't interact with otherwise is extremely confusing.

If one were to add non-existent things to scope in the lookat command, they'd need to add most of said things to take and all the other commands like that, too. (Except for busy. Who would try to TAKE BUSY? Not me! (I like "look busy"! That is FUNNY!))


Finally added the DoorLib to my game. Excellent. I too had always added a door object and added a script to exit that would first check if door was locked or opened. Sooo much easier with the lib. Glad it has the 'look' as well.


oh, I added this to the 'this.openscript =>

if (HasScript(this.exit,"onopen")){
  do (this.exit,"onopen")
}

an attribute 'onopen' script should be added to the exit as well and will then run when the door is opened.

In my case a woman will see you and scream. Of course doing this will/may require the women's scope to be added to the 'items' list in case the player wants to interact with her. Another can of worms...but I like to be able to look through openings and open doors to see whats up ahead before moving. Many games will move you to the next room when you open a door. A assume this is to avoid a mess of player commands being dealt with, but I'm doing the extra work cause' thats how I roll


K.V.

Hey! Nice!

I just updated the library. There is now an option to run a script on the "Door Settings" tab.

https://github.com/KVonGit/QuestStuff/blob/master/libraries/DoorLib.aslx

image


How about letting the creator enter a description to the"Look" message. Right now it just says if it is locked or open. being able to add a description would be nice. Perhaps to describe the door then you can have the locked or open script run.


K.V.

Damn, you keep thinking of good stuff!

image


Updated again:

https://github.com/KVonGit/QuestStuff/blob/master/libraries/DoorLib.aslx


Looks much more clean and neat now too!


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums