]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | #!/bin/bash |
2 | # ash -- "Adventure shell" | |
3 | # last edit: 86/04/21 D A Gwyn | |
4 | # SCCS ID: @(#)ash.sh 1.4 | |
5 | ||
6 | OPATH=$PATH | |
7 | ||
8 | ask() | |
9 | { | |
10 | echo -n "$@" '[y/n] ' | |
11 | read ans | |
12 | ||
13 | case "$ans" in | |
14 | y*|Y*) | |
15 | return 0 | |
16 | ;; | |
17 | *) | |
18 | return 1 | |
19 | ;; | |
20 | esac | |
21 | } | |
22 | ||
23 | CAT=${PAGER:-more} | |
24 | ||
25 | ash_inst() | |
26 | { | |
27 | cat <<- EOF | |
28 | ||
29 | Instructions for the Adventure shell | |
30 | ||
31 | Welcome to the Adventure shell! In this exploration of the UNIX file | |
32 | system, I will act as your eyes and hands. As you move around, I will | |
33 | describe whatever is visible and will carry out your commands. The | |
34 | general form of a command is | |
35 | Verb Object Extra_stuff. | |
36 | Most commands pay no attention to the "Extra_stuff", and many do not | |
37 | need an "Object". A typical command is | |
38 | get all | |
39 | which picks up all files in the current "room" (directory). You can | |
40 | find out what you are carrying by typing the command | |
41 | inventory | |
42 | The command "help" results in a full description of all commands that I | |
43 | understand. To quit the Adventure shell, type | |
44 | quit | |
45 | ||
46 | There are UNIX monsters lurking in the background. These are also | |
47 | known as "commands with arguments". | |
48 | ||
49 | Good luck! | |
50 | EOF | |
51 | } | |
52 | ||
53 | ash_help() | |
54 | { | |
55 | echo "I understand the following commands (synonyms in parentheses):" | |
56 | echo "" | |
57 | ||
58 | echo "change OBJECT to NEW_NAME changes the name of the object" | |
59 | echo "clone OBJECT as NEW_NAME duplicates the object" | |
60 | echo "drop OBJECTS leaves the objects in the room" | |
61 | echo "enter (go) PASSAGE takes the labeled passage" | |
62 | echo "examine OBJECTS describes the objects in detail" | |
63 | echo "feed OBJECT to MONSTER stuffs the object into a UNIX monster" | |
64 | echo "get (take) OBJECTS picks up the specified objects" | |
65 | echo "gripe (bug) report a problem with the Adventure shell" | |
66 | echo "help prints this summary" | |
67 | echo "inventory (i) tells what you are carrying" | |
68 | echo "kill (destroy) OBJECTS destroys the objects" | |
69 | echo "look (l) describes the room, including hidden objects" | |
70 | echo "open (read) OBJECT shows the contents of an object" | |
71 | echo "quit (exit) leaves the Adventure shell" | |
72 | echo "resurrect OBJECTS attempts to restore dead objects" | |
73 | echo "steal OBJECT from MONSTER obtains the object from a UNIX monster" | |
74 | echo "throw OBJECT at daemon feeds the object to the printer daemon" | |
75 | echo "up takes the overhead passage" | |
76 | echo "wake MONSTER awakens a UNIX monster" | |
77 | echo "where (w) tells you where you are" | |
78 | echo "xyzzy moves you to your home" | |
79 | } | |
80 | ||
81 | MAINT=chet@ins.cwru.edu | |
82 | ||
83 | PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin:. | |
84 | export PATH | |
85 | ||
86 | trap 'echo Ouch!' 2 3 | |
87 | #trap '' 18 # disable Berkeley job control | |
88 | ||
bb70624e JA |
89 | #ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; } |
90 | ash_lk(){ echo " $1 " | fgrep -q " $2 " >/dev/null 2>&1 ; } | |
726f6388 JA |
91 | ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; } |
92 | ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; } | |
93 | ||
b72432fd JA |
94 | # enable history, bang history expansion, and emacs editing |
95 | set -o history | |
96 | set -o histexpand | |
97 | set -o emacs | |
98 | ||
726f6388 JA |
99 | cd |
100 | LIM=.limbo # $HOME/$LIM contains "destroyed" objects | |
bb70624e | 101 | mkdir $LIM || { |
28ef6c31 | 102 | echo "ash: cannot mkdir $LIM: exiting" |
bb70624e JA |
103 | exit 1 |
104 | } | |
726f6388 JA |
105 | KNAP=.knapsack # $HOME/$KNAP contains objects being "carried" |
106 | if [ ! -d $KNAP ] | |
bb70624e | 107 | then mkdir $KNAP >/dev/null 2>&1 |
726f6388 JA |
108 | if [ $? = 0 ] |
109 | then echo 'You found a discarded empty knapsack.' | |
110 | else echo 'You have no knapsack to carry things in.' | |
111 | exit 1 | |
112 | fi | |
113 | else echo 'One moment while I peek in your old knapsack...' | |
114 | fi | |
115 | ||
116 | kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\`` | |
117 | ||
118 | if ask 'Welcome to the Adventure shell! Do you need instructions?' | |
119 | then | |
120 | ash_inst | |
121 | echo -n 'Type a newline to continue: ' | |
122 | read | |
123 | fi | |
124 | ||
125 | wiz=false | |
126 | cha=false | |
127 | prev=$LIM | |
128 | while : | |
129 | do room=`pwd` | |
130 | if [ $room != $prev ] | |
131 | then if [ $room = $HOME ] | |
132 | then echo 'You are in your own home.' | |
133 | else echo "You have entered $room." | |
134 | fi | |
135 | exs= | |
136 | obs= | |
137 | hexs= | |
138 | hobs= | |
139 | f=false | |
140 | for i in `ls -a` | |
141 | do case $i in | |
142 | .|..) ;; | |
143 | .*) if [ -f $i ] | |
144 | then hobs="$hobs $i" | |
145 | elif [ -d $i ] | |
146 | then hexs="$hexs $i" | |
147 | else f=true | |
148 | fi | |
149 | ;; | |
150 | *) if [ -f $i ] | |
151 | then obs="$obs $i" | |
152 | elif [ -d $i ] | |
153 | then exs="$exs $i" | |
154 | else f=true | |
155 | fi | |
156 | ;; | |
157 | esac | |
158 | done | |
159 | if [ "$obs" ] | |
160 | then echo 'This room contains:' | |
161 | ash_pr $obs | |
162 | else echo 'The room looks empty.' | |
163 | fi | |
164 | if [ "$exs" ] | |
165 | then echo 'There are exits labeled:' | |
166 | ash_pr $exs | |
167 | echo 'as well as a passage overhead.' | |
168 | else echo 'There is a passage overhead.' | |
169 | fi | |
170 | if sh -c $f | |
171 | then echo 'There are shadowy figures in the corner.' | |
172 | fi | |
173 | prev=$room | |
174 | fi | |
175 | ||
b72432fd | 176 | read -e -p '-advsh> ' verb obj x # prompt is '-advsh> ' |
726f6388 JA |
177 | if [ $? != 0 ] |
178 | then verb=quit # EOF | |
179 | fi | |
180 | ||
181 | case $verb in | |
182 | change) if [ "$obj" ] | |
183 | then if ash_lk "$obs $hobs" "$obj" | |
184 | then set -- $x | |
185 | case "$1" in | |
186 | to) if [ "$2" ] | |
187 | then if [ -f $2 ] | |
188 | then echo "You must destroy $2 first." | |
189 | set -- | |
190 | fi | |
191 | if [ "$2" ] | |
bb70624e | 192 | then if mv $obj $2 # >&- 2>&- |
726f6388 JA |
193 | then echo "The $obj shimmers and turns into $2." |
194 | obs=`ash_rm "$2 $obs" "$obj"` | |
195 | else echo "There is a cloud of smoke but the $obj is unchanged." | |
196 | fi | |
197 | fi | |
198 | else echo 'To what?' | |
199 | fi | |
200 | ;; | |
201 | *) echo "Change $obj to what?" | |
202 | ;; | |
203 | esac | |
204 | else if ash_lk "$kn" "$obj" | |
205 | then echo 'You must drop it first.' | |
206 | else echo "I see no $obj here." | |
207 | fi | |
208 | fi | |
209 | else echo 'Change what?' | |
210 | fi | |
211 | ;; | |
212 | clone) if [ "$obj" ] | |
213 | then if ash_lk "$obs $hobs" "$obj" | |
214 | then if [ ! -r $obj ] | |
215 | then echo "The $obj does not wish to be cloned." | |
216 | else set -- $x | |
217 | case "$1" in | |
218 | as) if [ "$2" ] | |
219 | then if [ -f $2 ] | |
220 | then echo "You must destroy $2 first." | |
bb70624e | 221 | else if cp $obj $2 # >&- 2>&- |
726f6388 JA |
222 | then echo "Poof! When the smoke clears, you see the new $2." |
223 | obs="$obs $2" | |
224 | else echo 'You hear a dull thud but no clone appears.' | |
225 | fi | |
226 | fi | |
227 | else echo 'As what?' | |
228 | fi | |
229 | ;; | |
230 | *) echo "Clone $obj as what?" | |
231 | ;; | |
232 | esac | |
233 | fi | |
234 | else if ash_lk "$kn" "$obj" | |
235 | then echo 'You must drop it first.' | |
236 | else echo "I see no $obj here." | |
237 | fi | |
238 | fi | |
239 | else echo 'Clone what?' | |
240 | fi | |
241 | ;; | |
242 | drop) if [ "$obj" ] | |
243 | then for it in $obj $x | |
244 | do if ash_lk "$kn" "$it" | |
245 | then if [ -w $it ] | |
246 | then echo "You must destroy $it first." | |
bb70624e | 247 | else if mv $HOME/$KNAP/$it $it # >&- 2>&- |
726f6388 JA |
248 | then echo "$it: dropped." |
249 | kn=`ash_rm "$kn" "$it"` | |
250 | obs=`echo $it $obs` | |
251 | else echo "The $it is caught in your knapsack." | |
252 | fi | |
253 | fi | |
254 | else echo "You're not carrying the $it!" | |
255 | fi | |
256 | done | |
257 | else echo 'Drop what?' | |
258 | fi | |
259 | ;; | |
260 | enter|go) if [ "$obj" ] | |
261 | then if [ $obj != up ] | |
262 | then if ash_lk "$exs $hexs" "$obj" | |
263 | then if [ -x $obj ] | |
264 | then if cd $obj | |
265 | then echo 'You squeeze through the passage.' | |
266 | else echo "You can't go that direction." | |
267 | fi | |
268 | else echo 'An invisible force blocks your way.' | |
269 | fi | |
270 | else echo 'I see no such passage.' | |
271 | fi | |
272 | else if cd .. | |
273 | then echo 'You struggle upwards.' | |
274 | else echo "You can't reach that high." | |
275 | fi | |
276 | fi | |
277 | else echo 'Which passage?' | |
278 | fi | |
279 | ;; | |
280 | examine) if [ "$obj" ] | |
281 | then if [ $obj = all ] | |
282 | then $obj=`echo $obs $exs` | |
283 | x= | |
284 | fi | |
285 | for it in $obj $x | |
286 | do if ash_lk "$obs $hobs $exs $hexs" "$it" | |
287 | then echo "Upon close inspection of the $it, you see:" | |
bb70624e | 288 | ls -ld $it 2>/dev/null |
726f6388 JA |
289 | if [ $? != 0 ] |
290 | then echo "-- when you look directly at the $it, it vanishes." | |
291 | fi | |
292 | else if ash_lk "$kn" "$it" | |
293 | then echo 'You must drop it first.' | |
294 | else echo "I see no $it here." | |
295 | fi | |
296 | fi | |
297 | done | |
298 | else echo 'Examine what?' | |
299 | fi | |
300 | ;; | |
301 | feed) if [ "$obj" ] | |
302 | then if ash_lk "$obs $hobs" "$obj" | |
303 | then set -- $x | |
304 | case "$1" in | |
305 | to) if [ "$2" ] | |
306 | then shift | |
bb70624e | 307 | if PATH=$OPATH $* <$obj 2>/dev/null |
726f6388 | 308 | then echo "The $1 monster devours your $obj." |
bb70624e | 309 | if rm -f $obj # >&- 2>&- |
726f6388 JA |
310 | then obs=`ash_rm "$obs" "$obj"` |
311 | else echo 'But he spits it back up.' | |
312 | fi | |
313 | else echo "The $1 monster holds his nose in disdain." | |
314 | fi | |
315 | else echo 'To what?' | |
316 | fi | |
317 | ;; | |
318 | *) echo "Feed $obj to what?" | |
319 | ;; | |
320 | esac | |
321 | else if ash_lk "$kn" "$obj" | |
322 | then echo 'You must drop it first.' | |
323 | else echo "I see no $obj here." | |
324 | fi | |
325 | fi | |
326 | else echo 'Feed what?' | |
327 | fi | |
328 | ;; | |
329 | get|take) if [ "$obj" ] | |
330 | then if [ $obj = all ] | |
331 | then obj="$obs" | |
332 | x= | |
333 | fi | |
334 | for it in $obj $x | |
335 | do if ash_lk "$obs $hobs" "$it" | |
336 | then if ash_lk "$kn" "$it" | |
337 | then echo 'You already have one.' | |
bb70624e | 338 | else if mv $it $HOME/$KNAP/$it # >&- 2>&- |
726f6388 JA |
339 | then echo "$it: taken." |
340 | kn="$it $kn" | |
341 | obs=`ash_rm "$obs" "$it"` | |
342 | else echo "The $it is too heavy." | |
343 | fi | |
344 | fi | |
345 | else echo "I see no $it here." | |
346 | fi | |
347 | done | |
348 | else echo 'Get what?' | |
349 | fi | |
350 | ;; | |
351 | gripe|bug) echo 'Please describe the problem and your situation at the time it failed.\nEnd the bug report with a line containing just a Ctrl-D.' | |
352 | cat | mail $MAINT -s 'ash bug' | |
353 | echo 'Thank you!' | |
354 | ;; | |
355 | help) ash_help | |
356 | ;; | |
357 | inventory|i) if [ "$kn" ] | |
358 | then echo 'Your knapsack contains:' | |
359 | ash_pr $kn | |
360 | else echo 'You are poverty-stricken.' | |
361 | fi | |
362 | ;; | |
363 | kill|destroy) if [ "$obj" ] | |
364 | then if [ $obj = all ] | |
365 | then x= | |
366 | if ask "Do you really want to attempt to $verb them all?" | |
367 | then obj=`echo $obs` | |
368 | else echo 'Chicken!' | |
369 | obj= | |
370 | fi | |
371 | fi | |
372 | for it in $obj $x | |
373 | do if ash_lk "$obs $hobs" "$it" | |
bb70624e | 374 | then if mv $it $HOME/$LIM # <&- >&- 2>&- |
726f6388 JA |
375 | then if [ $verb = kill ] |
376 | then echo "The $it cannot defend himself; he dies." | |
377 | else echo "You have destroyed the $it; it vanishes." | |
378 | fi | |
379 | obs=`ash_rm "$obs" "$it"` | |
380 | else if [ $verb = kill ] | |
381 | then echo "Your feeble blows are no match for the $it." | |
382 | else echo "The $it is indestructible." | |
383 | fi | |
384 | fi | |
385 | else if ash_lk "$kn" "$it" | |
386 | then echo "You must drop the $it first." | |
387 | found=false | |
388 | else echo "I see no $it here." | |
389 | fi | |
390 | fi | |
391 | done | |
392 | else echo 'Kill what?' | |
393 | fi | |
394 | ;; | |
395 | look|l) obs=`echo $obs $hobs` | |
396 | hobs= | |
397 | if [ "$obs" ] | |
398 | then echo 'The room contains:' | |
399 | ash_pr $obs | |
400 | else echo 'The room is empty.' | |
401 | fi | |
402 | exs=`echo $exs $hexs` | |
403 | hexs= | |
404 | if [ "$exs" ] | |
405 | then echo 'There are exits plainly labeled:' | |
406 | ash_pr $exs | |
407 | echo 'and a passage directly overhead.' | |
408 | else echo 'The only exit is directly overhead.' | |
409 | fi | |
410 | ;; | |
411 | magic) if [ "$obj" = mode ] | |
412 | then if sh -c $cha | |
413 | then echo 'You had your chance and you blew it.' | |
414 | else if ask 'Are you a wizard?' | |
415 | then echo -n 'Prove it! Say the magic word: ' | |
416 | read obj | |
417 | if [ "$obj" = armadillo ] | |
418 | then echo 'Yes, master!!' | |
419 | wiz=true | |
420 | else echo "Homie says: I don't think so" | |
421 | cha=true | |
422 | fi | |
423 | else echo "I didn't think so." | |
424 | fi | |
425 | fi | |
426 | else echo 'Nice try.' | |
427 | fi | |
428 | ;; | |
429 | open|read) if [ "$obj" ] | |
430 | then if ash_lk "$obs $hobs" "$obj" | |
431 | then if [ -r $obj ] | |
432 | then if [ -s $obj ] | |
433 | then echo "Opening the $obj reveals:" | |
434 | $CAT < $obj | |
435 | if [ $? != 0 ] | |
436 | then echo '-- oops, you lost the contents!' | |
437 | fi | |
438 | else echo "There is nothing inside the $obj." | |
439 | fi | |
440 | else echo "You do not have the proper tools to open the $obj." | |
441 | fi | |
442 | else if ash_lk "$kn" "$obj" | |
443 | then echo 'You must drop it first.' | |
444 | found=false | |
445 | else echo "I see no $obj here." | |
446 | fi | |
447 | fi | |
448 | else echo 'Open what?' | |
449 | fi | |
450 | ;; | |
451 | quit|exit) if ask 'Do you really want to quit now?' | |
452 | then if [ "$kn" ] | |
453 | then echo 'The contents of your knapsack will still be there next time.' | |
454 | fi | |
455 | rm -rf $HOME/$LIM | |
456 | echo 'See you later!' | |
457 | exit 0 | |
458 | fi | |
459 | ;; | |
460 | resurrect) if [ "$obj" ] | |
461 | then for it in $obj $x | |
462 | do if ash_lk "$obs $hobs" "$it" | |
463 | then echo "The $it is already alive and well." | |
bb70624e | 464 | else if mv $HOME/$LIM/$it $it # <&- >&- 2>&- |
726f6388 JA |
465 | then echo "The $it staggers to his feet." |
466 | obs=`echo $it $obs` | |
467 | else echo "There are sparks but no $it appears." | |
468 | fi | |
469 | fi | |
470 | done | |
471 | else echo 'Resurrect what?' | |
472 | fi | |
473 | ;; | |
474 | steal) if [ "$obj" ] | |
475 | then if ash_lk "$obs $hobs" "$obj" | |
476 | then echo 'There is already one here.' | |
477 | else set -- $x | |
478 | case "$1" in | |
479 | from) if [ "$2" ] | |
480 | then shift | |
bb70624e | 481 | if PATH=$OPATH $* >$obj 2>/dev/null |
726f6388 JA |
482 | then echo "The $1 monster drops the $obj." |
483 | obs=`echo $obj $obs` | |
484 | else echo "The $1 monster runs away as you approach." | |
bb70624e | 485 | rm -f $obj # >&- 2>&- |
726f6388 JA |
486 | fi |
487 | else echo 'From what?' | |
488 | fi | |
489 | ;; | |
490 | *) echo "Steal $obj from what?" | |
491 | ;; | |
492 | esac | |
493 | fi | |
494 | else echo 'Steal what?' | |
495 | fi | |
496 | ;; | |
497 | throw) if [ "$obj" ] | |
498 | then if ash_lk "$obs $hobs" "$obj" | |
499 | then set -- $x | |
500 | case "$1" in | |
501 | at) case "$2" in | |
502 | daemon) if sh -c "lpr -r $obj" | |
503 | then echo "The daemon catches the $obj, turns it into paper,\nand leaves it in the basket." | |
504 | obs=`ash_rm "$obs" "$obj"` | |
505 | else echo "The daemon is nowhere to be found." | |
506 | fi | |
507 | ;; | |
508 | *) echo 'At what?' | |
509 | ;; | |
510 | esac | |
511 | ;; | |
512 | *) echo "Throw $obj at what?" | |
513 | ;; | |
514 | esac | |
515 | else if ash_lk "$kn" "$obj" | |
516 | then echo 'It is in your knapsack.' | |
517 | found=false | |
518 | else echo "I see no $obj here." | |
519 | fi | |
520 | fi | |
521 | else echo 'Throw what?' | |
522 | fi | |
523 | ;; | |
524 | u|up) if cd .. | |
525 | then echo 'You pull yourself up a level.' | |
526 | else echo "You can't reach that high." | |
527 | fi | |
528 | ;; | |
529 | wake) if [ "$obj" ] | |
530 | then echo "You awaken the $obj monster:" | |
531 | PATH=$OPATH $obj $x | |
532 | echo 'The monster slithers back into the darkness.' | |
533 | else echo 'Wake what?' | |
534 | fi | |
535 | ;; | |
536 | w|where) echo "You are in $room." | |
537 | ;; | |
538 | xyzzy) if cd | |
539 | then echo 'A strange feeling comes over you.' | |
540 | else echo 'Your spell fizzles out.' | |
541 | fi | |
542 | ;; | |
543 | *) if [ "$verb" ] | |
544 | then if sh -c $wiz | |
545 | then PATH=$OPATH $verb $obj $x | |
546 | else echo "I don't know how to \"$verb\"." | |
547 | echo 'Type "help" for assistance.' | |
548 | fi | |
549 | else echo 'Say something!' | |
550 | fi | |
551 | ;; | |
552 | esac | |
553 | done |