-
Notifications
You must be signed in to change notification settings - Fork 0
/
wumpus.lisp
307 lines (245 loc) · 7.56 KB
/
wumpus.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
;;; Global variable declaration
(setf bat1 0)
(setf bat2 0)
(setf pit1 0)
(setf pit2 0)
(setf hunter 0)
(setf wumps 0)
(setf arrow 0)
(setf arrwnum 5)
(setf win nil)
(setf gameon nil)
(setf same nil)
(defvar resp 0)
(defvar resp2 0)
(defvar dist 0)
;;; Seed for random generator
(let* ((state (make-random-state t))
(copy (make-random-state state)))
;;; Init game plot
(setf cave (make-array '(20 3) :initial-contents '((2 5 8)(1 3 10)(2 4 12)(3 5 14)(1 4 6)
(5 7 15)(6 8 17)(1 7 9)(8 10 18)(2 9 11)(10 12 19)
(3 11 13)(12 14 20)(4 13 15)(6 14 16)(15 17 20)
(7 16 18)(9 17 19)(11 18 20)(13 16 19)) ))
(defun init()
(setq bat1 (random-gen) bat2 (random-gen)
pit1 (random-gen) pit2 (random-gen)
hunter (random-gen) wumps (random-gen) arrwnum 5)
(if (= hunter wumps) (init) ))
;;; Random number generator
(defun random-gen()
(if (equal same nil)
(1+ (random 20 state))
(1+ (random 20 copy)))))
;;; Take user input
(defun userint ()
(let ((x (read)))
(values
(if (not (typep x 'number))
(progn (print "Please enter an integer input") (userint)))
(if (typep x 'number)
(progn
(if (or (> x 20) (< x 0)) (progn (print "Choose among room 1-20") (userint))
(setq resp x) ))))))
(defun userYN()
(setq resp2
(with-output-to-string (s)
(format s "~s" (read))))
(if (not (or (equal resp2 "Y") (equal resp2 "N")))
(progn
(print "PLEASE ENTER A VALID INPUT: ")
(userYN) )))
(defun userSM()
(setq resp2
(with-output-to-string (s)
(format s "~s" (read))))
;;; Check user input
(if (not (or (equal resp2 "S") (equal resp2 "M")))
(progn
(print "PLEASE ENTER A VALID INPUT: ")
(userSM) )))
;;; Check Hunter's next move
(defun move ()
(print "WHERE TO?")
(userint)
;;; Move hunter
(if (or (= resp (aref cave (- hunter 1) 0))
(= resp (aref cave (- hunter 1) 1))
(= resp (aref cave (- hunter 1) 2)))
(setq hunter resp) (progn (print "You can only move to an adjacent room") (move) ))
;;; Check hazard on the way
(if (or (= hunter bat1) (= hunter bat2))
(progn
(print "ZAP--SUPERBAT SNATCH! ELSEWHEREVILLE FOR YOU. You are now in a random room")
(setq hunter (random-gen))))
(if (or (= hunter pit1) (= hunter pit2))
(progn
(print "YYYIIIEEEEEEE. . . FELL IN A PIT")
(setq gameon nil)
(setq win nil)
(gameover)
)))
;;; Decide Wumpus' behavior when disturbed
(defun wmps()
(if (= hunter wumps)
(progn
(if (> (random-gen) 5)
(setq wumps (aref cave (- wumps 1) (mod (random-gen) 3)))
(progn
(setq win nil)
(setq gameon nil)
(print "You are eaten by the wumpus! YOU LOST!")
(gameover)))))
(if (= arrow wumps)
(progn
(if (> (random-gen) 5)
(setq wumps (aref cave (- wumps 1) (mod (random-gen) 3)))
(progn
(setq win t)
(setq gameon nil)
(print "You just shoot the wumpus! You won!")
(gameover))))))
;;; Shoot arrow to an adjacent room
(defun shoot()
(setq arrow hunter)
(decf arrwnum)
(print "You can shoot through 5 rooms. How many rooms do you want to shoot through?")
(userint)
(if (> resp 5)
(progn
(loop
(when (and (> resp 0)(< resp 6)) (return))
(print "Choose between 1-5. How many rooms?")
(userint)
) ) )
(setq dist resp)
(loop
(when (< dist 1) (return))
(print "Where to?")
(userint)
(if (not (or (= resp (aref cave (- arrow 1) 0))
(= resp (aref cave (- arrow 1) 1))
(= resp (aref cave (- arrow 1) 2)) ) )
(progn
(print "You can only shoot to an adjacent room.")
(print "Your arrow ended up at a random room.")
(setq arrow (random-gen))
(wmps)
(suicide)
(return) )
(progn
(setq arrow resp)
(wmps)
(suicide)
(decf dist)
) ) )
(if (equal gameon t)
(print "Sorry! You missed!"))
(if (= arrwnum 0)
(progn
(print "Sorry, You just used up all of your arrows.")
(print "You lost")
(setq gameon nil)
(setq win nil)
(gameover))))
;;; Check if the player shoot himself in the back
(defun suicide()
(if (= hunter arrow)
(progn
(print "HAHAHA- You just shoot yourself in the back")
(print "YOU DIED")
(setq gameon nil)
(setq win nil)
(gameover))))
;;; Decide the result of the game
(defun gameover()
(if (equal win t) (print "GAME ENDS-YOU WON") (print "GAME ENDS-YOU LOST"))
(print "Do you want to quit? Y-N")
(userYN)
(if (equal resp2 "Y") (print "BYE BYE")
(progn
(print "same setup? Y-N")
(userYN)
(if (or (equal resp2 "N"))
(progn
(setq same nil)
(wumpus) )
(progn
(setq same t)
(wumpus) ) ) ) ) )
;;; Instruction
(defun instruction()
(print "WELCOME TO HUNT THE WUMPUS!!
THE WUMPUS LIVES IN A CAVE OF 20 ROOMS.
EACH ROOM HAS 3 TUNNELS LEADNG TO OTHER ROOMS'
LOOK AT A DODECAHEDRON TO SEE HOW IT WORKS-
IF YOU DONNOT KNOW WHAT A DODECAHEDRON IS,
ASK SOMEONE
HAZARDS:
BOTTEMLESS PITS: TWO ROOMS HAVE BOTTOMLESS PITS
IF YOU GO THERE, YOU FALL INTO THE PIT AND LOSE
SUPER BATS: TWO OTHER ROOMS HAVE SUPER BATS
IF YOU GO THERE, A BAT WILL MOVE YOU TO A RANDOM ROOM
WUMPUS:
THE WUMPUS ONLY BOTHERED BY YOU ENTERING HIS ROOM OR
YOUR ARROW SHOOTS INTO HIS ROOM
IF HE IS BOTHERED, HE MAY MOVE TO ANOTHER ROOM,
OR CHOOSE TO STAY IN THE SAME ROOM
IF YOU ARE IN THE SAME ROOM WITH THE WUMPUS,
HE WILL EAT YOU UP, AND YOU LOSE.
YOU:
EACH TURN YOU CAN MOVE OR SHOOT A CROOKED ARROW.
MOVE: YOU CAN MOVE ONE ROOM (THROUGH ONE TUNNEL.)
SHOOT: YOU HAVE 5 ARROWS. YOU LOSE WHEN YOU RUN OUT
EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING
THE COMPUTER THE ROOM #S YOU WANT THE ARROW TO GO TO.
IF THE ARROW CANNOT GO THAT WAY,
IT MOVES AT RANDOM TO THE NEXT ROOM.
IF THE ARROW HITS THE WUMPUS, YOU WIN.
IF THE ARROW HITS YOU, YOU LOSE.
WARNINGS:
WHEN YOU ARE ONE ROOM AWAY FROM WUMPUS OR HAZARD,
THE COMPUTER SAYS
WUMPUS: I SMELL A WUMPUS
BAT: BATS NEARBY
PIT: I FEEL A DRAFT
*****
HUNT THE WUMPUS") )
;;; Hazard Detector for the player
(defun detect()
(if (or (equal pit1 (aref cave (- hunter 1) 0)) (equal pit1 (aref cave (- hunter 1) 1))
(equal pit1 (aref cave (- hunter 1) 2)) )
(print "I feel draft..."))
(if (or (equal pit2 (aref cave (- hunter 1) 0)) (equal pit2 (aref cave (- hunter 1) 1))
(equal pit2 (aref cave (- hunter 1) 2)) )
(print "I feel draft..."))
(if (or (equal bat1 (aref cave (- hunter 1) 0)) (equal bat1 (aref cave (- hunter 1) 1))
(equal bat1 (aref cave (- hunter 1) 2)) )
(print "BATs near you"))
(if (or (equal bat1 (aref cave (- hunter 1) 0)) (equal bat1 (aref cave (- hunter 1) 1))
(equal bat1 (aref cave (- hunter 1) 2)) )
(print "BATs near you"))
(if (or (equal wumps (aref cave (- hunter 1) 0)) (equal wumps (aref cave (- hunter 1) 1))
(equal wumps (aref cave (- hunter 1) 2)) )
(print "I smell a wumpus")) )
;;; Mainframe of the game
(defun wumpus()
(print "WELCOME TO HUNT THE WUMPUS WORLD!")
(print "DO YOU WANT TO READ THE INSTRUCTION?")
(userYN)
(if (equal resp2 "Y") (instruction))
(init)
(setq gameon t)
(loop
(when (equal gameon nil) (return))
(detect)
(print "You are in room:")
(print hunter)
(print "Which is connected to:")
(print (aref cave (- hunter 1) 0))
(print (aref cave (- hunter 1) 1))
(print (aref cave (- hunter 1) 2))
(print "Do you want to shoot or move?")
(userSM)
(if (equal resp2 "S") (shoot) (move) )
))