This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

LPMUD, games, etc (Re: About modules)


> And that's exactly what i need for my game 'Naos' , a mechanism to 
> provide an game-internal package system to maintain code that is
> randomly accessed and altered at runtime, by independant authors
> and the gamedriver itself. That situation is similar to those of
> certain networked games called LPMUDs, but all in all very peculiar
> and not really useful outside, except some ideas. So it is really
> application specific. A form of eval will be needed there in any case,
> unless K. Wright can convince me not to do so :)
> Runtime in this case also includes the downtime of the game engine 
> between two game sessions, especially parsing the savefiles I can't
> imagine without doing a lot of calls to eval.

This is a farily peculiar application. Remember that the LPMUD
people wrote their own language to support the features that they
wanted. However, if guile really is going to be ubiquitous then it
should even support applications such as this.

Looking at other interpretive languages, most of them support
an environment as an extra parameter to an eval call but most of
them also link all the sub-environments (e.g. the local environment
of a function) back to the root environment and there is n way
to prevent such linkage. Your problem is fundamentally security
related because you don't want some code within a game object to be
able to modify the root environment and indirectly achieve control
over other game objects.

Thinking about this and the current state of guile, I would have
to say that achieving this level of security is still a long way off.
Consider that Java is still trying to iron out security issues and
it was built from the ground up with that purpose in mind.

I suggest you consider one of these options:

- writing your own evaluator which can process scheme lists and
  which provides a subset of full functionality so that only secure
  access is possible. This will run a bit slow but is easy to debug 
  and you can always (eventually) rewrite your evaluator in C as
  a guile extension, if you are careful it will still be compatible
  with normal guile.

- write your own evaluator but make it very simple in that it
  just does a check on each function then invokes the normal
  evaluator. One possible method is using something like:

      (set-object-property! + 'OK #t)
      (set-object-property! - 'OK #t)
      (set-object-property! * 'OK #t)  ; and any other safe functions

      (if (object-property FUNC 'OK) (apply FUNC ARGS) (my-error whatever))

  obviously some thought needs to go into getting recursion correct.

- write a mini-compiler using lambda expressions that produces
  something that can safely be put through eval.

This is a very small example of using lambda as a mini-compiler:

(define (const X) (lambda (ARG) X))
(define (plus A B) (lambda (ARG) (+ (A ARG) (B ARG))))
(define (times A B) (lambda (ARG) (* (A ARG) (B ARG))))
(define (arg1) (lambda (ARG) (car ARG)))
(define (arg2) (lambda (ARG) (cadr ARG)))
(define (top FN) (lambda ARG (FN ARG)))

; Note that this expression uses no macros or special whatsits,
; just ordinary functions and it returns a lambda type.

(define Z (top (times (plus (arg1) (const 4)) (plus (arg2) (const 5)))))

; Now you have a function Z which you can evaluate like normal:

(Z 1 2)
(Z 3 4)
 
For your purposes you would implement it differently and do some
checks at the compilation stage to ensure that everything fits
together nicely, you may even be able to compile internally into
native scheme rather than lambda expressions which should be a bit
faster but this gives some rough idea of how to achieve arbitrary
levels of abstraction from very no-frills scheme.

Also, this passes ARG through the tree but if you do one big define
(so it all falls under the same scope) then you can get the lambdas
to compile in the pointers to a single local variable ARG location
which is faster but still allows you a lot of control over what can
be accessed.

	- Tel

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]