Patch-ID: bash41-003
[bash.git] / examples / scripts / adventure.sh
blob169445014cdeb6023837050082dcb9f66733ef9f
1 #!/bin/bash
2 # ash -- "Adventure shell"
3 # last edit: 86/04/21 D A Gwyn
4 # SCCS ID: @(#)ash.sh 1.4
6 OPATH=$PATH
8 ask()
10 echo -n "$@" '[y/n] '
11 read ans
13 case "$ans" in
14 y*|Y*)
15 return 0
18 return 1
20 esac
23 CAT=${PAGER:-more}
25 ash_inst()
27 cat <<- EOF
29 Instructions for the Adventure shell
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
46 There are UNIX monsters lurking in the background. These are also
47 known as "commands with arguments".
49 Good luck!
50 EOF
53 ash_help()
55 echo "I understand the following commands (synonyms in parentheses):"
56 echo ""
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"
81 MAINT=chet@ins.cwru.edu
83 PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin:.
84 export PATH
86 trap 'echo Ouch!' 2 3
87 #trap '' 18 # disable Berkeley job control
89 #ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; }
90 ash_lk(){ echo " $1 " | fgrep -q " $2 " >/dev/null 2>&1 ; }
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/ $//'; }
94 # enable history, bang history expansion, and emacs editing
95 set -o history
96 set -o histexpand
97 set -o emacs
100 LIM=.limbo # $HOME/$LIM contains "destroyed" objects
101 mkdir $LIM || {
102 echo "ash: cannot mkdir $LIM: exiting"
103 exit 1
105 KNAP=.knapsack # $HOME/$KNAP contains objects being "carried"
106 if [ ! -d $KNAP ]
107 then mkdir $KNAP >/dev/null 2>&1
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
113 else echo 'One moment while I peek in your old knapsack...'
116 kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\``
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
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."
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
150 *) if [ -f $i ]
151 then obs="$obs $i"
152 elif [ -d $i ]
153 then exs="$exs $i"
154 else f=true
157 esac
158 done
159 if [ "$obs" ]
160 then echo 'This room contains:'
161 ash_pr $obs
162 else echo 'The room looks empty.'
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.'
170 if sh -c $f
171 then echo 'There are shadowy figures in the corner.'
173 prev=$room
176 read -e -p '-advsh> ' verb obj x # prompt is '-advsh> '
177 if [ $? != 0 ]
178 then verb=quit # EOF
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 --
191 if [ "$2" ]
192 then if mv $obj $2 # >&- 2>&-
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."
198 else echo 'To what?'
201 *) echo "Change $obj to what?"
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."
209 else echo 'Change what?'
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."
221 else if cp $obj $2 # >&- 2>&-
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.'
227 else echo 'As what?'
230 *) echo "Clone $obj as what?"
232 esac
234 else if ash_lk "$kn" "$obj"
235 then echo 'You must drop it first.'
236 else echo "I see no $obj here."
239 else echo 'Clone what?'
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."
247 else if mv $HOME/$KNAP/$it $it # >&- 2>&-
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."
254 else echo "You're not carrying the $it!"
256 done
257 else echo 'Drop what?'
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."
268 else echo 'An invisible force blocks your way.'
270 else echo 'I see no such passage.'
272 else if cd ..
273 then echo 'You struggle upwards.'
274 else echo "You can't reach that high."
277 else echo 'Which passage?'
280 examine) if [ "$obj" ]
281 then if [ $obj = all ]
282 then $obj=`echo $obs $exs`
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:"
288 ls -ld $it 2>/dev/null
289 if [ $? != 0 ]
290 then echo "-- when you look directly at the $it, it vanishes."
292 else if ash_lk "$kn" "$it"
293 then echo 'You must drop it first.'
294 else echo "I see no $it here."
297 done
298 else echo 'Examine what?'
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
307 if PATH=$OPATH $* <$obj 2>/dev/null
308 then echo "The $1 monster devours your $obj."
309 if rm -f $obj # >&- 2>&-
310 then obs=`ash_rm "$obs" "$obj"`
311 else echo 'But he spits it back up.'
313 else echo "The $1 monster holds his nose in disdain."
315 else echo 'To what?'
318 *) echo "Feed $obj to what?"
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."
326 else echo 'Feed what?'
329 get|take) if [ "$obj" ]
330 then if [ $obj = all ]
331 then obj="$obs"
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.'
338 else if mv $it $HOME/$KNAP/$it # >&- 2>&-
339 then echo "$it: taken."
340 kn="$it $kn"
341 obs=`ash_rm "$obs" "$it"`
342 else echo "The $it is too heavy."
345 else echo "I see no $it here."
347 done
348 else echo 'Get what?'
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!'
355 help) ash_help
357 inventory|i) if [ "$kn" ]
358 then echo 'Your knapsack contains:'
359 ash_pr $kn
360 else echo 'You are poverty-stricken.'
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=
372 for it in $obj $x
373 do if ash_lk "$obs $hobs" "$it"
374 then if mv $it $HOME/$LIM # <&- >&- 2>&-
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."
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."
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."
391 done
392 else echo 'Kill what?'
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.'
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.'
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
423 else echo "I didn't think so."
426 else echo 'Nice try.'
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!'
438 else echo "There is nothing inside the $obj."
440 else echo "You do not have the proper tools to open the $obj."
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."
448 else echo 'Open what?'
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.'
455 rm -rf $HOME/$LIM
456 echo 'See you later!'
457 exit 0
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."
464 else if mv $HOME/$LIM/$it $it # <&- >&- 2>&-
465 then echo "The $it staggers to his feet."
466 obs=`echo $it $obs`
467 else echo "There are sparks but no $it appears."
470 done
471 else echo 'Resurrect what?'
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
481 if PATH=$OPATH $* >$obj 2>/dev/null
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."
485 rm -f $obj # >&- 2>&-
487 else echo 'From what?'
490 *) echo "Steal $obj from what?"
492 esac
494 else echo 'Steal what?'
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."
508 *) echo 'At what?'
510 esac
512 *) echo "Throw $obj at what?"
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."
521 else echo 'Throw what?'
524 u|up) if cd ..
525 then echo 'You pull yourself up a level.'
526 else echo "You can't reach that high."
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?'
536 w|where) echo "You are in $room."
538 xyzzy) if cd
539 then echo 'A strange feeling comes over you.'
540 else echo 'Your spell fizzles out.'
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.'
549 else echo 'Say something!'
552 esac
553 done