I was only a lowly content builder and quest manager, so I can't speak much to how the server mechanics worked.
But essentially, each entity (usually a mob) would have a set of event scripts (attached to some kind of internal lookup table), and each time an event happened, it would call the appropriate scripts/function/macro.
So what I did was logic such as "game tick -> wander one step in a random direction" or "player enters room -> attack", but also slightly more complex ones such as "combat round -> if low health, flee".
The cool feature of the server was that you could specify multiple options in the template, and it would randomly pick one for a newly created instance, giving some variety to behaviors (eg, some guards flee and some fight to the death). Each instance could also be given a specific one after instantiated, which was how we constructed special events. (That is, use an existing template, tweak a couple behaviors of the instance, and then redecorate it.) This is mostly just a benefit of first-class functions and LISP's ability to switch strings to code.
LISP was mostly just nice in that you could often one-line fairly complex behavior, so you could build in-game over telnet.
Honestly, I really miss text MUDs, but does anyone actually want to read anymore?
I too was a mobprogs builder, but I hung around diku-based muds, and none of those used lisp. I loved the SMAUG codebase in particular. There was a NO_FLOOR property, and I discovered that there was an brief input delay on hitting the floor, during which your commands would be completely thrown out of the buffer. If you made an On Entry script in the destination room to immediately teleport the player back to the room with no floor, you'd trap them in an infinite loop that didn't buffer overflow, and completely ignored their commands. They would fall, hit the floor, and before their input block had ended, they would be falling again.
Now, did you know that SMAUG's mudprogs ignored level restrictions, but could be activated by any IMM's force command? So when you force the mob to mpteleport a player, it doesn't check that you're only level 55 and the mpteleport target is level 65... so I called that a prison for gods.
I think I spent more time trying to break the code than actually producing content.
For anyone reading: this is basically how all hacking works and why security is hard -- you have to think out every way several components might interact.
I love text games. Looking forward to taustation which is going into alpha soon and written by a prolific perl author. Good stuff. Check out the blog articles.
This may not be what you're looking for, but it's a nifty example of building a small text adventure system in Racket and then leveraging its language building tools.