home » builders » builder's lessons » non key doors

Non key doors

There are several doors in the mud that cannot be open simply with a key. You might have to lift a bar, push a (hidden) button, turn a dial, say a keyword, knock on the door, or do some other action.

This can generally be done with a (more or less) simple intercept or speech program. But, if you want more precise echoes, it can get a bit trickier. Let's say you want to use an intercept turn program to unlock and open a door. The two rooms connected by this door are vnums A and B (A being south from B). You might use the following program in room A:

>intercept_prog turn~
mpecho As you turn the dial, the door opens.
mpat B mpecho The door to the south opens.
mpoload keyvnum
unlock north
open north
mpjunk ikeyvnum
~

Note: You could have an intercept_prog turn in room A and a speech_prog Open! in room B if you want the door to require different actions to be opened, depending on whether the character is in room A or room B. The two programs can be different.

This program is good enough to allow characters to open the door. But, if someone opens the door (by triggering the program) then someone else comes in room A and types 'turn', they will see the 'door opens' echo again, even though the door is already open. You might have the same problem if you want to enable characters to lock the door by using the same keyword ('turn' in the example).

The only way to solve this problem is to keep track of the state of the door: is it open or not. The most obvious way to do this is with quest bits... but, since quest bits can't be kept on rooms, we need to replace the room progs with mob programs, and thus, we need to have invisible mobs in each of the rooms.

Since the door can be either open or closed and locked, we only need quest bit 0,1. Let us assume that the door is initially closed and locked and that this value is quest bit 0,1 = 0. The programs could be something like:

>intercept_prog turn~
if quest(0,1,$n) == 0
  mpecho The door to the north opens.
  mpat B mpecho The door to the south opens.
  mpoload keyvnum
  unlock north
  open north
  mpjunk ikeyvnum
  mpmset self quest 0 1 1
else
  mpecho The door to the north closes.
  mpat B mpecho The door to the south closes.
  mpoload keyvnum
  close north
  lock north
  mpjunk ikeyvnum
  mpmset self quest 0 1 0
endif
~

Unfortunately, that does not solve all the problems yet. This program allows the code to remember if the door is open or closed, but we also need to make sure that the "state" of the door is the same in room A and in room B. That is, we need to make sure that, when someone opens the door from room A, the invisible mob in room B knows that the state of the door is now 'open' (and vice versa).

As far as I know, there are 2 ways to do that. The first one is perhaps simpler, but can be a problem if the programs are complex and long (since it will double the length of the programs). The second one is a bit more difficult, but it does not add much to the length of the programs.

The first solution consists in using the fact that, if you have 2 mobs with the same vnum (two copies of the same mob), when the quest bits are changed on one of the mobs, they are also changed on the other ones (and on any other mobs with the same vnum). We can thus make 1 mob and use 2 copies of this mob (one in room A and one in room B). As soon as one of them modifies its quest bits (when the state of the door is changed), the other one will automatically have its quest bits modified as well.

That means that both programs (program for room A and program for room B) must be placed on this mob, and that inroom checks must be added. For the example, I assume that the keyword to open/close the door is 'turn' for both rooms.

>intercept_prog turn~
if inroom(self) = A
  *same program as above*
else
  *same program as above*
  *but north becomes south*
  *and south becomes north*
endif
~

If the original program is already long, by using this solution (and thus doubling the length of the program), you might get a program that is too long (I'm not sure exactly what the limit on the number of lines in a program is, but there is a limit).

For the second solution, 2 different mobs are used and we need to modify the quest bits of both mobs each time the door is opened/closed. Now, there is an additional problem: invisible mobs are... invisible. And they can't see each other. So, if AMOB and BMOB are the vnums of the mobs in rooms A and B (respectively), we cannot simply use a command like 'mpat B mpmset mBMOB quest 0 1 1'.

There is a relatively simple solution to this though... even if mob BMOB cannot be seen, it can still intercept commands from any characters or mobs, even those it cannot see. The trick consists in having a command executed in room B, having mob BMOB intercept this command and react by changing its own quest bits.

So, if we add these intercept_progs on mob BMOB

>intercept_prog doorhasbeenopened~
mpmset self quest 0 1 1
~
>intercept_prog doorhasbeenclosed~
mpmset self quest 0 1 0
~

We can modify AMOB's program into

>intercept_prog turn~
if quest(0,1,$n) == 0
  mpecho The door to the north opens.
  mpat B mpecho The door to the south opens.
  mpat B doorhasbeenopened
  mpoload keyvnum
  unlock north
  open north
  mpjunk ikeyvnum
  mpmset self quest 0 1 1
else
  mpecho The door to the north closes.
  mpat B mpecho The door to the south closes.
  mpat B doorhasbeenclosed
  mpoload keyvnum
  close north
  lock north
  mpjunk ikeyvnum
  mpmset self quest 0 1 0
endif
~

Basically, in this solution, we have mob AMOB trigger the intercept_prog of BMOB in order to have BMOB change its own quest bits.

Additional ways to handle doors is covered in the Buttons and Levers Lesson.