Movement of a monster on a level different from the party. Diagram
Interesting things learned:

- When the party enters a level of the dungeon all the creatures on that level are put to sleep by removing their timer entries. They are stuck and will never move again. Then each monster is reawakened by creating for it a timer entry of type ?????? with a delay of ??????.
- Each monster type has a characterisitc 'Time-per-move'. When a monster is on a different level from the party the time between moves is the larger of two values, namely: a) 16 times the difference in levels and b) 2 times the characteristic 'Time-Per-Move'. I imagine that this was implemented so that monsters would move more slowly and monsters far from the party would move more slowly yet, thus saving precious CPU time on the rather overworked Atari.
- Type 37 Timer messages are used to keep the monsters active.
- At each opportunity to move, the monster attempts to move in a random direction. If movement in that direction is not possible then the move is skipped.
- The function PossibleMove() is called to determine if movement in a particular direction is possible.
- All the code for moving monsters not on the party level is contained in the function InitialChecks() which is the very first thing that is done when a monster movement Timer expires.

The following was the result of a Monster AI trace. I entered the DM dungeon, went downstairs and opened the Mummy door, went back upstairs, enabled the Monster AI trace, and waited about 50 seconds. Then I exited and edited the trace to remove all but the Mummy. So the difference in levels was one because I was on level zero and the mummy was on level 1.
MonsterAI 01(06,02)@145 Perform Initial Checks-timeFunc=37, timeUntilNextUpdate=0
MAI Not on party level. PossibleMove(Random()=EAST) returned false.
MAI No attempt to move monster. Que 37 timer
MAI Setting timer 37. Time equals:
MAI 16 * difference in levels = 16
MAI 2*MonsterType->timePerMove = 34
MAI The larger number.....equals 34
MonsterAI 01(06,02)@179 Perform Initial Checks-timeFunc=37, timeUntilNextUpdate=0
MAI Not on party level. PossibleMove(Random()=NORTH) returned true.
MAI MoveObject to (06,01) returned 0
MAI Setting timer 37. Time equals:
MAI 16 * difference in levels = 16
MAI 2*MonsterType->timePerMove = 34
MAI The larger number.....equals 34
MonsterAI 01(06,01)@213 Perform Initial Checks-timeFunc=37, timeUntilNextUpdate=0
MAI Not on party level. PossibleMove(Random()=NORTH) returned true.
MAI MoveObject to (06,00) returned 0
MAI Setting timer 37. Time equals:
MAI 16 * difference in levels = 16
MAI 2*MonsterType->timePerMove = 34
MAI The larger number.....equals 34
MonsterAI 01(06,00)@247 Perform Initial Checks-timeFunc=37, timeUntilNextUpdate=0
MAI Not on party level. PossibleMove(Random()=EAST) returned true.
MAI MoveObject to (07,00) returned 0
MAI Setting timer 37. Time equals:
MAI 16 * difference in levels = 16
MAI 2*MonsterType->timePerMove = 34
MAI The larger number.....equals 34
MonsterAI 01(07,00)@281 Perform Initial Checks-timeFunc=37, timeUntilNextUpdate=0
MAI Not on party level. PossibleMove(Random()=SOUTH) returned false.
MAI No attempt to move monster. Que 37 timer
MAI Setting timer 37. Time equals:
MAI 16 * difference in levels = 16
MAI 2*MonsterType->timePerMove = 34
MAI The larger number.....equals 34
MonsterAI 01(07,00)@315 Perform Initial Checks-timeFunc=37, timeUntilNextUpdate=0
MAI Not on party level. PossibleMove(Random()=WEST) returned true.
MAI MoveObject to (06,00) returned 0
MAI Setting timer 37. Time equals:
MAI 16 * difference in levels = 16
MAI 2*MonsterType->timePerMove = 34
MAI The larger number.....equals 34
MonsterAI 01(06,00)@349 Perform Initial Checks-timeFunc=37, timeUntilNextUpdate=0
MAI Not on party level. PossibleMove(Random()=SOUTH) returned true.
MAI MoveObject to (06,01) returned 0
MAI Setting timer 37. Time equals:
MAI 16 * difference in levels = 16
MAI 2*MonsterType->timePerMove = 34
MAI The larger number.....equals 34