Skip to content

Instantly share code, notes, and snippets.

@CTimmerman
Last active November 29, 2021 18:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CTimmerman/275278abeea166a74fd3cf759a239b7e to your computer and use it in GitHub Desktop.
Save CTimmerman/275278abeea166a74fd3cf759a239b7e to your computer and use it in GitHub Desktop.
Demonstrates how a Lisp adventure game from the book "Casting SPELs in LISP" is more readable in Python. See also https://gist.github.com/CTimmerman/34b7b9d7b161442a5c5da7b4afbba163
"""
Casting SPELs with LISP demo code ported to Python
By Cees Timmerman
2017-07-04 v1.0
"""
from __future__ import print_function
'''
(setf *objects* '(whiskey-bottle bucket frog chain))
(setf *map* '((living-room (you are in the living-room of a wizards house. there is a
wizard snoring loudly on the couch.)
(west door garden)
(upstairs stairway attic))
(garden (you are in a beautiful garden. there is a well in front of you.)
(east door living-room))
(attic (you are in the attic of the wizards house. there is a giant
welding torch in the corner.)
(downstairs stairway living-room))))
(setf *object-locations* '((whiskey-bottle living-room)
(bucket living-room)
(chain garden)
(frog garden)))
(setf *location* 'living-room)
(defun describe-location (location map)
(second (assoc location map)))
(describe-location 'living-room *map*)
(defun describe-path (path)
`(there is a ,(second path) going ,(first path) from here.))
(describe-path '(west door garden))
(defun describe-paths (location map)
(apply #'append (mapcar #'describe-path (cddr (assoc location map)))))
(describe-paths 'living-room *map*)
(defun is-at (obj loc obj-loc)
(eq (second (assoc obj obj-loc)) loc))
(is-at 'whiskey-bottle 'living-room *object-locations*)
(defun describe-floor (loc objs obj-loc)
(apply #'append (mapcar (lambda (x)
`(you see a ,x on the floor.))
(remove-if-not (lambda (x)
(is-at x loc obj-loc))
objs))))
(describe-floor 'living-room *objects* *object-locations*)
(defun look ()
(append (describe-location *location* *map*)
(describe-paths *location* *map*)
(describe-floor *location* *objects* *object-locations*)))
(look)
(defun walk-direction (direction)
(let ((next (assoc direction (cddr (assoc *location* *map*)))))
(cond (next (setf *location* (third next)) (look))
(t '(you cant go that way.)))))
(walk-direction 'west)
(defmacro defspel (&rest rest) `(defmacro ,@rest))
(defspel walk (direction)
`(walk-direction ',direction))
(walk east)
(defun pickup-object (object)
(cond ((is-at object *location* *object-locations*) (push (list object 'body) *object-locations*)
`(you are now carrying the ,object))
(t '(you cannot get that.))))
(defspel pickup (object)
`(pickup-object ',object))
(pickup whiskey-bottle)
(defun inventory ()
(remove-if-not (lambda (x)
(is-at x 'body *object-locations*))
*objects*))
(defun have (object)
(member object (inventory)))
(setf *chain-welded* nil)
(defun weld (subject object)
(cond ((and (eq *location* 'attic)
(eq subject 'chain)
(eq object 'bucket)
(have 'chain)
(have 'bucket)
(not *chain-welded*))
(setf *chain-welded* 't)
'(the chain is now securely welded to the bucket.))
(t '(you cannot weld like that.))))
(weld 'chain 'bucket)
(setf *bucket-filled* nil)
(defun dunk (subject object)
(cond ((and (eq *location* 'garden)
(eq subject 'bucket)
(eq object 'well)
(have 'bucket)
*chain-welded*)
(setf *bucket-filled* 't) '(the bucket is now full of water))
(t '(you cannot dunk like that.))))
(defspel game-action (command subj obj place &rest rest)
`(defspel ,command (subject object)
`(cond ((and (eq *location* ',',place)
(eq ',subject ',',subj)
(eq ',object ',',obj)
(have ',',subj))
,@',rest)
(t '(i cant ,',command like that.)))))
(game-action weld chain bucket attic
(cond ((and (have 'bucket) (setf *chain-welded* 't))
'(the chain is now securely welded to the bucket.))
(t '(you do not have a bucket.))))
(weld chain bucket)
(game-action dunk bucket well garden
(cond (*chain-welded* (setf *bucket-filled* 't) '(the bucket is now full of water))
(t '(the water level is too low to reach.))))
(game-action splash bucket wizard living-room
(cond ((not *bucket-filled*) '(the bucket has nothing in it.))
((have 'frog) '(the wizard awakens and sees that you stole his frog.
he is so upset he banishes you to the
netherworlds- you lose! the end.))
(t '(the wizard awakens from his slumber and greets you warmly.
he hands you the magic low-carb donut- you win! the end.))))
'''
FIRST = 0
SECOND = 1
THIRD = 2
CDR = "[1:]"
CAR = "[0]"
OBJECTS = "whiskey-bottle bucket frog chain".split(' ')
MAP = {
'living-room': [
'You are in the living-room of a wizards house. there is a wizard snoring loudly on the couch.',
'west door garden',
'upstairs stairway attic'],
'garden': [
'You are in a beautiful garden. there is a well in front of you.',
'east door living-room'],
'attic': [
'''You are in the attic of the wizards house. there is a giant
welding torch in the corner.''',
'downstairs stairway living-room']
}
OBJECT_LOCATIONS = {
'whiskey-bottle': 'living-room',
'bucket': 'living-room',
'chain': 'garden',
'frog': 'garden'
}
LOCATION = 'living-room'
def describe_location(location, map):
return map[location][0]
#print(describe_location('living-room', MAP))
def describe_path(path):
return 'There is a {} going {} from here.'.format(path.split()[1], path.split()[0])
#print(describe_path('west door garden'))
def describe_paths(location, map):
return ' '.join(describe_path(path) for path in map[location][1:])
#print(describe_paths('living-room', MAP))
def describe_floor(loc, objs, obj_loc):
return ' '.join(['You see a {} on the floor.'.format(k) for k in obj_loc if obj_loc[k] == loc])
print(describe_floor('living-room', OBJECTS, OBJECT_LOCATIONS))
def look():
return '\n'.join([
describe_location(LOCATION, MAP),
describe_paths(LOCATION, MAP),
describe_floor(LOCATION, OBJECTS, OBJECT_LOCATIONS)
])
print(look())
def walk_direction(direction):
global LOCATION
try:
#next = MAP[LOCATION][direction]
directions = MAP[LOCATION][1:]
next = [d.split() for d in directions if d.split()[0] == direction][0]
#(let ((next (assoc direction (cddr (assoc LOCATION MAP)))))
LOCATION = next[2]
return look()
except:
return 'You cant go that way.'
#walk_direction('west')
#wtf? def defspel(&rest rest) `(defmacro ,@rest))
def walk(direction):
return walk_direction(direction)
#walk('east')
def pickup_object(object):
if OBJECT_LOCATIONS[object] == LOCATION: OBJECT_LOCATIONS[object] = 'body'
else: return 'You cannot get that.'
def pickup(object):
return pickup_object(object)
#pickup('whiskey-bottle')
def inventory():
return [k for k in OBJECTS if OBJECT_LOCATIONS[k] == 'body']
def have(object):
return OBJECT_LOCATIONS[object] == 'body' #object in inventory()
CHAIN_WELDED = None
def weld(subject, object):
global CHAIN_WELDED
if LOCATION == 'attic' \
and subject == 'chain' \
and object == 'bucket' \
and have('chain') \
and have('bucket') \
and not CHAIN_WELDED:
CHAIN_WELDED = True
return 'The chain is now securely welded to the bucket.'
else:
return 'You cannot weld like that.'
#weld('chain', 'bucket')
BUCKET_FILLED = None
def dunk(subject, object):
if LOCATION == 'garden' \
and subject == 'bucket' \
and object == 'well' \
and have('bucket') \
and CHAIN_WELDED:
BUCKET_FILLED = True
return 'The bucket is now full of water'
else:
return 'You cannot dunk like that.'
def game_action(command, subj, obj, place, rest):
code ="""
global {command}
def {command}(subject, object):
if LOCATION == '{place}' \
and subject == '{subj}' \
and object == '{obj}' \
and have('{subj}'):
exec(\"\"\"{rest}\"\"\")
else: print("I cant {command} like that.")
""".format(command=command, subj=subj, obj=obj, place=place, rest=rest)
#print(code)
exec(code)
game_action('weld', 'chain', 'bucket', 'attic',
"""
if have('bucket'):
global CHAIN_WELDED
CHAIN_WELDED = True
print('The chain is now securely welded to the bucket.')
else: print('You do not have a bucket.')
"""
)
#weld('chain', 'bucket')
game_action('dunk', 'bucket', 'well', 'garden',
"""if CHAIN_WELDED: global BUCKET_FILLED; BUCKET_FILLED = True; print('The bucket is now full of water')
else: print('The water level is too low to reach.')""")
game_action('splash', 'bucket', 'wizard', 'living-room',
"""
if not BUCKET_FILLED: print('The bucket has nothing in it.')
elif have('frog'): print('''The wizard awakens and sees that you stole his frog.
He is so upset he banishes you to the
Netherworlds- you lose! the end.''')
else: print('''The wizard awakens from his slumber and greets you warmly.
he hands you the magic low-carb donut- you win! the end.''')
""")
while 1:
try:
a = raw_input().split()
if a[0] == "exit": break
if len(a) > 1:
cmd = "{}('{}')".format(a[0], "', '".join(a[1:]))
#print(cmd)
msg = eval(cmd)
if(msg): print(msg)
else: print(eval("{}()".format(a[0])))
except Exception as ex:
print(ex, "\nTry look, pickup, dunk, splash, weld, walk, inventory, have, or exit.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment