[plt-scheme] How to use Eval for a MUD

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Tue Jan 26 07:47:21 EST 2010

Sounds like a cool project. I've always wanted to make an awesome MUD
engine with Scheme.

As far as technique, I think you're going to have to experiment and
find out what is cleanest in your context. I doubt that you'll get
much value from being totally functional, but I think it might be
simpler to manage the namespace creation in a functional way...
creating it fresh everytime the user changes context. Another simple
idea to do is have a stack of namespaces (global -> user -> area ->
room -> "mode" [fighting, shop, etc]) that are extracted from the
environment objects as the user inputs other commands. Then when you
want to use 'eval' you first eval in the tightest namespace, falling
back if the compilation fails, etc.


On Mon, Jan 25, 2010 at 10:30 PM, Synx <plt at synx.us.to> wrote:
> I am working on a text based interactive world in scheme. One important
> aspect of that for me is to enable dynamic scripting. I want to make it
> so people (perhaps only privileged users) can make objects, rooms and
> environments from within the game itself, such that when the game
> restarts, the programming they have done with these things remains
> intact. I'd also like it sandboxed, so one person's broken program
> doesn't take down the whole world, obviously.
> I have a persistent database of some form, of "objects" that make up
> this world, each object has "properties", and some of those properties
> must somehow be programs. The obvious way to do that is to store the
> s-expression of the program into the property. I figured out how to make
> an evaluator, but populating its namespace is something of a puzzle to
> me. I'm not sure what strategy to take, since the concept of a game like
> this has a rather unusual way of handling context.
> The idea is this: players control a player object that is treated as
> "them" for purposes of user interaction. That object carries with it a
> certain context or namespace, that relates what actions are valid while
> being that player. For instance a player might have a procedure that
> runs when they type "scan Zymorgian". That procedure only runs for that
> player, when they type that syntax in. Other players would not see
> anything special happen with the syntax "scan ____" when they type it,
> unless they also had a similar procedure in their own personal context.
> Rooms can have a context as well though, rooms being not much more than
> a collection of objects that are all considered to be in the same
> general in-game vicinity. Any player whose player object is in a given
> room must be able to access the room's procedures, such as "pull the red
> lever" becoming (pull 'red) where pull is a procedure unique to that
> room. So there needs to be some context that not only many players share
> for having been in the same room, but a context that changes when a
> player object moves from one room to another. Dare I say mutates?
> There's also the notion of a general environmental context, like "swim"
> might be a valid procedure for objects in all rooms that are categorized
> as being flooded, while it would not work, or have different
> functionality on rooms designated as on a cruise ship. And of course a
> global environmental context that applies everywhere like "quit" or
> "home" or "reset".
> I've gotten as far at studying scheme/sandbox to figure out how to make
> a module evaluator, that I can load up with identifiers and modules, and
>  evaluate stuff with it. But some of the subtleties of the above system
> I'm still puzzling about. When going from room to room, do I somehow
> "delete" all the identifiers only relevant to the previous room, while
> "defining" the ones relevant to the next room? Do I just set! the old
> identifiers to #f or something, and wouldn't that eventually accumulate
> every possible identifier in the game into one namespace? Should I have
> a namespace for every room, environment, and player object, and somehow
> recombine those into one namespace every time either the player or the
> room changes? When a player defines some new procedure, how could I make
> that procedure persistent? Do I have to have a set of properties in each
> environment, room and player that get evaluated every time the player
> changes rooms? What if the player changes rooms, but remains in the same
> environment? Couldn't the properties on the player object, that govern
> the player's personal actions, not be re-evaluated every time they move?
> I'm really puzzled how to handle this. Something tells me that searching
> through the player, room, and all environments for the name of every
> procedure on the left of an s-expression, is a bad idea. Yet that's how
> say FuzzballMUCK does it, or TinyMUSH. They just do a recursive search
> through all the properties and objects relevant to the current player,
> on up to the root object #0. Would it be better to do that search
> pre-emptively, and have s-expression evaluation be as simple as an
> (eval)? Is there some way to compile these procedures such that they'd
> be noticeably quicker than evaluating the source expression of the
> procedure?
> _________________________________________________
>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme

Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University

"The glory of God is Intelligence" - D&C 93

Posted on the users mailing list.