Nothing spectacular here at all, and as you can see, I’ve already brought across the TryUnlock() and TryOpen() methods that are virtually identical from the containers, because like in those cases, I think it is an important game feature that the game is smart enough to open a door automatically, if the player tries to walk through it while it’s closed or if he tries to open it while it’s still locked.

There is a call to a SetState() function that needs a bit of explanation, I think.

Python

1

2

3

4

5

6

defSetState(self,_state):

self.State=_state

_adjacent=rooms.theRooms[self.Target].HasExit(self.InvertDirection(self.Direction))# get the other side

_adjacent.State=_state

When you have a door in the game, the door actually appears in two rooms, technically. If in the room you’re currently in there is a door leading West, for example, it means there also has to be a door in the room it leads to, leading in the opposite direction. If I open the door in my current room, by definition, the door in the other room will also have to be opened.

That’s what this function does. It looks where the door leads to and then grabs the definition for that adjacent room. There, it searches the exits for one that leads in the opposite direction and flags it as Open as well. I hope this made sense…

The function to invert the direction, is a rather crude little bit of code. It may not be elegant, but it gets the job done, and since it’s in a method of its own, I can go back at any time and expand it to allow for more directions.

Python

1

2

3

4

5

6

7

8

9

10

11

defInvertDirection(_direction):

ifTokens.North==_direction:

returnTokens.South

ifTokens.South==_direction:

returnTokens.North

ifTokens.West==_direction:

returnTokens.East

ifTokens.East==_direction:

returnTokens.West

With all that in place, it is now time to implement the actual actions.

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

defOpen(self):

self.TryUnlock()

ifglobals.DoorStates.Open==self.State:

print("The door is already open.")

elifglobals.DoorStates.Locked==self.State:

print("The door is locked.")

else:

print("You open the door.")

self.SetState(globals.DoorStates.Open)

returnTrue

defClose(self):

ifglobals.DoorStates.Closed==self.State:

print("The door is already closed.")

else:

print("You shut the door.")

self.SetState(globals.DoorStates.Closed)

returnTrue

defLock(self):

ifself.Key:

ifglobals.DoorStates.Locked==self.State:

print("The door is already locked.")

else:

ifglobals.theInventory.Has(self.Key):

print("You lock the door.")

self.SetState(globals.DoorStates.Locked)

else:

print("You do not have a fitting key.")

else:

print("The door has no lock.")

returnTrue

defUnlock(self):

ifself.Key:

ifglobals.DoorStates.Open==self.State:

print("The door is already unlocked and standing wide open.")

elifglobals.DoorStates.Locked!=self.State:

print("The door is already unlocked.")

else:

ifglobals.theInventory.Has(self.Key):

print("With a soft click, you hear the door unlock.")

self.SetState(globals.DoorStates.Closed)

else:

print("You do not have a fitting key.")

else:

print("The door has no lock.")

returnTrue

As you can see, the logic of these actions is essentially identical to the one I used in my Container class. After all, the behavior of a lid compared to a door is not all that different.

Catching the respective actions in my Evaluate() function allowed me to make the necessary calls and before I knew it, I had doors I could open, lock and close. Neat.

One key ingredient is still missing at this point, however. Since we are talking about a type of exit, I want to make sure that player can actually walk through doors and, as I mentioned before, I want the game to automatically open doors if necessary. In order to make that happen, I had to modify the Move() function that is part of my Room class.

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

defMove(self,_dir):

""" Check if there is an exit leading a direction; If there is, change to the new room; Print the new room's description """

_exit=globals.theRoom.HasExit(_dir)

_adjacent=rooms.theRooms[_exit.Target].HasExit(_exit.InvertDirection(_exit.Direction))# get the other side

if_exit:

_exit.TryUnlock()

_exit.TryOpen()

ifglobals.DoorStates.Locked==_exit.State:

print("You can't go that way. That door is locked.")

returnTrue

globals.theRoom=rooms.theRooms[_exit.Target]

globals.theRoomID=_exit.Target

globals.theRoom.Describe()

returnTrue

returnFalse

And just like that, the player can move through doors in the game and he can manipulate doors as well, which adds further depth to the game. Throw in a couple of additional responses when the player tries to break down a door, or when he tries to put his ear to it to eavesdrop, and you have some more powerful game features your player will enjoy.