-
Notifications
You must be signed in to change notification settings - Fork 0
/
wizards_game.lisp
136 lines (108 loc) · 4.96 KB
/
wizards_game.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
(defparameter *nodes* '((living-room (you are in the living-room.
a wizard is snoring loudly on the couch.))
(garden (you are in a beautiful garden.
there is a well in front of you.))
(attic (you are in the attic.
there is a giant welding torch in the corner.))))
(defun describe-location (location nodes)
(cadr (assoc location nodes)))
(defparameter *edges* '((living-room (garden west door)
(attic upstairs ladder))
(garden (living-room east door))
(attic (living-room downstairs ladder))))
(defun describe-path (edge)
`(there is a ,(caddr edge) going ,(cadr edge) from here.))
(defun describe-paths (location edges)
(apply #'append (mapcar #'describe-path (cdr (assoc location edges)))))
(defparameter *objects* '(whiskey bucket frog chain))
(defparameter *object-locations* '((whiskey living-room)
(bucket living-room)
(chain garden)
(frog garden)))
(defun objects-at (loc objs obj-loc)
(labels ((is-at (obj)
(eq (cadr (assoc obj obj-loc)) loc)))
(remove-if-not #'is-at objs)))
(defun describe-objects (loc objs obj-loc)
(labels ((describe-obj (obj)
`(you see a ,obj on the floor.)))
(apply #'append (mapcar #'describe-obj (objects-at loc objs obj-loc)))))
(defparameter *location* 'living-room)
(defun look ()
(append (describe-location *location* *nodes*)
(describe-paths *location* *edges*)
(describe-objects *location* *objects* *object-locations*)))
(defun walk (direction)
(labels ((correct-way (edge)
(eq (cadr edge) direction)))
(let ((next (find-if #'correct-way (cdr (assoc *location* *edges*)))))
(if next
(progn (setf *location* (car next))
(look))
'(you cannot go that way.)))))
(defun pickup (object)
(cond ((member object (objects-at *location* *objects* *object-locations*))
(push (list object 'body) *object-locations*)
`(you are now carrying the ,object))
(t '(you cannot get that.))))
(defun inventory ()
(cons 'items- (objects-at 'body *objects* *object-locations*)))
(defun have (object)
(member object (cdr (inventory))))
(defun game-repl ()
(let ((cmd (game-read)))
(unless (eq (car cmd) 'quit)
(game-print (game-eval cmd))
(game-repl))))
(defun game-read ()
(let ((cmd (read-from-string (concatenate 'string "(" (read-line) ")"))))
(flet ((quote-it (x)
(list 'quote x)))
(cons (car cmd) (mapcar #'quote-it (cdr cmd))))))
(defparameter *allowed-commands* '(look walk pickup inventory weld))
(defun game-eval (sexp)
(if (member (car sexp) *allowed-commands*)
(eval sexp)
'(i do not know that command.)))
(defun tweak-text (lst caps lit)
(when lst
(let ((item (car lst))
(rest (cdr lst)))
(cond ((eql item #\space) (cons item (tweak-text rest caps lit)))
((member item '(#\! #\? #\.)) (cons item (tweak-text rest t lit)))
((eql item #\") (tweak-text rest caps (not lit)))
(lit (cons item (tweak-text rest nil lit)))
(caps (cons (char-upcase item) (tweak-text rest nil lit)))
(t (cons (char-downcase item) (tweak-text rest nil nil)))))))
(defun game-print (lst)
(princ (coerce (tweak-text (coerce (string-trim "() " (prin1-to-string lst)) 'list) t nil) 'string))
(fresh-line))
(defparameter *chain-welded* nil)
(game-action weld chain bucket attic
(if (and (have 'bucket) (not *chain-welded*))
(progn (setf *chain-welded* 't)
'(the chain is now securely welded to the bucket.))
'(you do not have a bucket.)))
(defparameter *bucket-filled* nil)
(game-action dunk bucket well garden
(if *chain-welded*
(progn (setf *bucket-filled* 't)
'(the bucket is now full of water))
'(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.))))
(pushnew 'dunk *allowed-commands*)
(defmacro game-action (command subj obj place &body body)
`(progn (defun ,command (subject object)
(if (and (eq *location* ',place)
(eq subject ',subj)
(eq object ',obj)
(have ',subj))
,@body
'(i cant ,command like that.)))
(pushnew ',command *allowed-commands*)))