4e2239396a7e74285e9371157f2f2c721eb5d31f
[platform/upstream/bash.git] / examples / scripts / adventure.sh
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
89 ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; }
90 ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; }
91 ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; }
92
93 # enable history, bang history expansion, and emacs editing
94 set -o history
95 set -o histexpand
96 set -o emacs
97
98 cd
99 LIM=.limbo                      # $HOME/$LIM contains "destroyed" objects
100 mkdir $LIM >&- 2>&-
101 KNAP=.knapsack                  # $HOME/$KNAP contains objects being "carried"
102 if [ ! -d $KNAP ]
103 then    mkdir $KNAP >&- 2>&-
104         if [ $? = 0 ]
105         then    echo 'You found a discarded empty knapsack.'
106         else    echo 'You have no knapsack to carry things in.'
107                 exit 1
108         fi
109 else    echo 'One moment while I peek in your old knapsack...'
110 fi
111
112 kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\``
113
114 if ask 'Welcome to the Adventure shell!  Do you need instructions?'
115 then
116         ash_inst
117         echo -n 'Type a newline to continue: '
118         read
119 fi
120
121 wiz=false
122 cha=false
123 prev=$LIM
124 while :
125 do      room=`pwd`
126         if [ $room != $prev ]
127         then    if [ $room = $HOME ]
128                 then    echo 'You are in your own home.'
129                 else    echo "You have entered $room."
130                 fi
131                 exs=
132                 obs=
133                 hexs=
134                 hobs=
135                 f=false
136                 for i in `ls -a`
137                 do      case $i in
138                         .|..)   ;;
139                         .*)     if [ -f $i ]
140                                 then    hobs="$hobs $i"
141                                 elif [ -d $i ]
142                                 then    hexs="$hexs $i"
143                                 else    f=true
144                                 fi
145                                 ;;
146                         *)      if [ -f $i ]
147                                 then    obs="$obs $i"
148                                 elif [ -d $i ]
149                                 then    exs="$exs $i"
150                                 else    f=true
151                                 fi
152                                 ;;
153                         esac
154                 done
155                 if [ "$obs" ]
156                 then    echo 'This room contains:'
157                         ash_pr $obs
158                 else    echo 'The room looks empty.'
159                 fi
160                 if [ "$exs" ]
161                 then    echo 'There are exits labeled:'
162                         ash_pr $exs
163                         echo 'as well as a passage overhead.'
164                 else    echo 'There is a passage overhead.'
165                 fi
166                 if sh -c $f
167                 then    echo 'There are shadowy figures in the corner.'
168                 fi
169                 prev=$room
170         fi
171
172         read -e -p '-advsh> ' verb obj x        # prompt is '-advsh> '
173         if [ $? != 0 ]
174         then    verb=quit               # EOF
175         fi
176
177         case $verb in
178         change)         if [ "$obj" ]
179                         then    if ash_lk "$obs $hobs" "$obj"
180                                 then    set -- $x
181                                         case "$1" in
182                                         to)     if [ "$2" ]
183                                                 then    if [ -f $2 ]
184                                                         then    echo "You must destroy $2 first."
185                                                                 set --
186                                                         fi
187                                                         if [ "$2" ]
188                                                         then    if mv $obj $2 >&- 2>&-
189                                                                 then    echo "The $obj shimmers and turns into $2."
190                                                                         obs=`ash_rm "$2 $obs" "$obj"`
191                                                                 else    echo "There is a cloud of smoke but the $obj is unchanged."
192                                                                 fi
193                                                         fi
194                                                 else    echo 'To what?'
195                                                 fi
196                                                 ;;
197                                         *)      echo "Change $obj to what?"
198                                                 ;;
199                                         esac
200                                 else    if ash_lk "$kn" "$obj"
201                                         then    echo 'You must drop it first.'
202                                         else    echo "I see no $obj here."
203                                         fi
204                                 fi
205                         else    echo 'Change what?'
206                         fi
207                         ;;
208         clone)          if [ "$obj" ]
209                         then    if ash_lk "$obs $hobs" "$obj"
210                                 then    if [ ! -r $obj ]
211                                         then    echo "The $obj does not wish to be cloned."
212                                         else    set -- $x
213                                                 case "$1" in
214                                                 as)     if [ "$2" ]
215                                                         then    if [ -f $2 ]
216                                                                 then    echo "You must destroy $2 first."
217                                                                 else    if cp $obj $2 >&- 2>&-
218                                                                         then    echo "Poof!  When the smoke clears, you see the new $2."
219                                                                                 obs="$obs $2"
220                                                                         else    echo 'You hear a dull thud but no clone appears.'
221                                                                         fi
222                                                                 fi
223                                                         else    echo 'As what?'
224                                                         fi
225                                                         ;;
226                                                 *)      echo "Clone $obj as what?"
227                                                         ;;
228                                                 esac
229                                         fi
230                                 else    if ash_lk "$kn" "$obj"
231                                         then    echo 'You must drop it first.'
232                                         else    echo "I see no $obj here."
233                                         fi
234                                 fi
235                         else    echo 'Clone what?'
236                         fi
237                         ;;
238         drop)           if [ "$obj" ]
239                         then    for it in $obj $x
240                                 do      if ash_lk "$kn" "$it"
241                                         then    if [ -w $it ]
242                                                 then    echo "You must destroy $it first."
243                                                 else    if mv $HOME/$KNAP/$it $it >&- 2>&-
244                                                         then    echo "$it: dropped."
245                                                                 kn=`ash_rm "$kn" "$it"`
246                                                                 obs=`echo $it $obs`
247                                                         else    echo "The $it is caught in your knapsack."
248                                                         fi
249                                                 fi
250                                         else    echo "You're not carrying the $it!"
251                                         fi
252                                 done
253                         else    echo 'Drop what?'
254                         fi
255                         ;;
256         enter|go)       if [ "$obj" ]
257                         then    if [ $obj != up ]
258                                 then    if ash_lk "$exs $hexs" "$obj"
259                                         then    if [ -x $obj ]
260                                                 then    if cd $obj
261                                                         then    echo 'You squeeze through the passage.'
262                                                         else    echo "You can't go that direction."
263                                                         fi
264                                                 else    echo 'An invisible force blocks your way.'
265                                                 fi
266                                         else    echo 'I see no such passage.'
267                                         fi
268                                 else    if cd ..
269                                         then    echo 'You struggle upwards.'
270                                         else    echo "You can't reach that high."
271                                         fi
272                                 fi
273                         else    echo 'Which passage?'
274                         fi
275                         ;;
276         examine)        if [ "$obj" ]
277                         then    if [ $obj = all ]
278                                 then    $obj=`echo $obs $exs`
279                                         x=
280                                 fi
281                                 for it in $obj $x
282                                 do      if ash_lk "$obs $hobs $exs $hexs" "$it"
283                                         then    echo "Upon close inspection of the $it, you see:"
284                                                 ls -ld $it 2>&-
285                                                 if [ $? != 0 ]
286                                                 then    echo "-- when you look directly at the $it, it vanishes."
287                                                 fi
288                                         else    if ash_lk "$kn" "$it"
289                                                 then    echo 'You must drop it first.'
290                                                 else    echo "I see no $it here."
291                                                 fi
292                                         fi
293                                 done
294                         else    echo 'Examine what?'
295                         fi
296                         ;;
297         feed)           if [ "$obj" ]
298                         then    if ash_lk "$obs $hobs" "$obj"
299                                 then    set -- $x
300                                         case "$1" in
301                                         to)     if [ "$2" ]
302                                                 then    shift
303                                                         if PATH=$OPATH $* <$obj 2>&-
304                                                         then    echo "The $1 monster devours your $obj."
305                                                                 if rm -f $obj >&- 2>&-
306                                                                 then    obs=`ash_rm "$obs" "$obj"`
307                                                                 else    echo 'But he spits it back up.'
308                                                                 fi
309                                                         else    echo "The $1 monster holds his nose in disdain."
310                                                         fi
311                                                 else    echo 'To what?'
312                                                 fi
313                                                 ;;
314                                         *)      echo "Feed $obj to what?"
315                                                 ;;
316                                         esac
317                                 else    if ash_lk "$kn" "$obj"
318                                         then    echo 'You must drop it first.'
319                                         else    echo "I see no $obj here."
320                                         fi
321                                 fi
322                         else    echo 'Feed what?'
323                         fi
324                         ;;
325         get|take)       if [ "$obj" ]
326                         then    if [ $obj = all ]
327                                 then    obj="$obs"
328                                         x=
329                                 fi
330                                 for it in $obj $x
331                                 do      if ash_lk "$obs $hobs" "$it"
332                                         then    if ash_lk "$kn" "$it"
333                                                 then    echo 'You already have one.'
334                                                 else    if mv $it $HOME/$KNAP/$it >&- 2>&-
335                                                         then    echo "$it: taken."
336                                                                 kn="$it $kn"
337                                                                 obs=`ash_rm "$obs" "$it"`
338                                                         else    echo "The $it is too heavy."
339                                                         fi
340                                                 fi
341                                         else    echo "I see no $it here."
342                                         fi
343                                 done
344                         else    echo 'Get what?'
345                         fi
346                         ;;
347         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.'
348                         cat | mail $MAINT -s 'ash bug'
349                         echo 'Thank you!'
350                         ;;
351         help)           ash_help
352                         ;;
353         inventory|i)    if [ "$kn" ]
354                         then    echo 'Your knapsack contains:'
355                                 ash_pr $kn
356                         else    echo 'You are poverty-stricken.'
357                         fi
358                         ;;
359         kill|destroy)   if [ "$obj" ]
360                         then    if [ $obj = all ]
361                                 then    x=
362                                         if ask "Do you really want to attempt to $verb them all?"
363                                         then    obj=`echo $obs`
364                                         else    echo 'Chicken!'
365                                                 obj=
366                                         fi
367                                 fi
368                                 for it in $obj $x
369                                 do      if ash_lk "$obs $hobs" "$it"
370                                         then    if mv $it $HOME/$LIM <&- >&- 2>&-
371                                                 then    if [ $verb = kill ]
372                                                         then    echo "The $it cannot defend himself; he dies."
373                                                         else    echo "You have destroyed the $it; it vanishes."
374                                                         fi
375                                                         obs=`ash_rm "$obs" "$it"`
376                                                 else    if [ $verb = kill ]
377                                                         then    echo "Your feeble blows are no match for the $it."
378                                                         else    echo "The $it is indestructible."
379                                                         fi
380                                                 fi
381                                         else    if ash_lk "$kn" "$it"
382                                                 then    echo "You must drop the $it first."
383                                                         found=false
384                                                 else    echo "I see no $it here."
385                                                 fi
386                                         fi
387                                 done
388                         else    echo 'Kill what?'
389                         fi
390                         ;;
391         look|l)         obs=`echo $obs $hobs`
392                         hobs=
393                         if [ "$obs" ]
394                         then    echo 'The room contains:'
395                                 ash_pr $obs
396                         else    echo 'The room is empty.'
397                         fi
398                         exs=`echo $exs $hexs`
399                         hexs=
400                         if [ "$exs" ]
401                         then    echo 'There are exits plainly labeled:'
402                                 ash_pr $exs
403                                 echo 'and a passage directly overhead.'
404                         else    echo 'The only exit is directly overhead.'
405                         fi
406                         ;;
407         magic)          if [ "$obj" = mode ]
408                         then    if sh -c $cha
409                                 then    echo 'You had your chance and you blew it.'
410                                 else    if ask 'Are you a wizard?'
411                                         then    echo -n 'Prove it!  Say the magic word: '
412                                                 read obj
413                                                 if [ "$obj" = armadillo ]
414                                                 then    echo 'Yes, master!!'
415                                                         wiz=true
416                                                 else    echo "Homie says: I don't think so"
417                                                         cha=true
418                                                 fi
419                                         else    echo "I didn't think so."
420                                         fi
421                                 fi
422                         else    echo 'Nice try.'
423                         fi
424                         ;;
425         open|read)      if [ "$obj" ]
426                         then    if ash_lk "$obs $hobs" "$obj"
427                                 then    if [ -r $obj ]
428                                         then    if [ -s $obj ]
429                                                 then    echo "Opening the $obj reveals:"
430                                                         $CAT < $obj
431                                                         if [ $? != 0 ]
432                                                         then    echo '-- oops, you lost the contents!'
433                                                         fi
434                                                 else    echo "There is nothing inside the $obj."
435                                                 fi
436                                         else    echo "You do not have the proper tools to open the $obj."
437                                         fi
438                                 else    if ash_lk "$kn" "$obj"
439                                         then    echo 'You must drop it first.'
440                                                 found=false
441                                         else    echo "I see no $obj here."
442                                         fi
443                                 fi
444                         else    echo 'Open what?'
445                         fi
446                         ;;
447         quit|exit)      if ask 'Do you really want to quit now?'
448                         then    if [ "$kn" ]
449                                 then    echo 'The contents of your knapsack will still be there next time.'
450                                 fi
451                                 rm -rf $HOME/$LIM
452                                 echo 'See you later!'
453                                 exit 0
454                         fi
455                         ;;
456         resurrect)      if [ "$obj" ]
457                         then    for it in $obj $x
458                                 do      if ash_lk "$obs $hobs" "$it"
459                                         then    echo "The $it is already alive and well."
460                                         else    if mv $HOME/$LIM/$it $it <&- >&- 2>&-
461                                                 then    echo "The $it staggers to his feet."
462                                                         obs=`echo $it $obs`
463                                                 else    echo "There are sparks but no $it appears."
464                                                 fi
465                                         fi
466                                 done
467                         else    echo 'Resurrect what?'
468                         fi
469                         ;;
470         steal)          if [ "$obj" ]
471                         then    if ash_lk "$obs $hobs" "$obj"
472                                 then    echo 'There is already one here.'
473                                 else    set -- $x
474                                         case "$1" in
475                                         from)   if [ "$2" ]
476                                                 then    shift
477                                                         if PATH=$OPATH $* >$obj 2>&-
478                                                         then    echo "The $1 monster drops the $obj."
479                                                                 obs=`echo $obj $obs`
480                                                         else    echo "The $1 monster runs away as you approach."
481                                                                 rm -f $obj >&- 2>&-
482                                                         fi
483                                                 else    echo 'From what?'
484                                                 fi
485                                                 ;;
486                                         *)      echo "Steal $obj from what?"
487                                                 ;;
488                                         esac
489                                 fi
490                         else    echo 'Steal what?'
491                         fi
492                         ;;
493         throw)          if [ "$obj" ]
494                         then    if ash_lk "$obs $hobs" "$obj"
495                                 then    set -- $x
496                                         case "$1" in
497                                         at)     case "$2" in
498                                                 daemon) if sh -c "lpr -r $obj"
499                                                         then    echo "The daemon catches the $obj, turns it into paper,\nand leaves it in the basket."
500                                                                 obs=`ash_rm "$obs" "$obj"`
501                                                         else    echo "The daemon is nowhere to be found."
502                                                         fi
503                                                         ;;
504                                                 *)      echo 'At what?'
505                                                         ;;
506                                                 esac
507                                                 ;;
508                                         *)      echo "Throw $obj at what?"
509                                                 ;;
510                                         esac
511                                 else    if ash_lk "$kn" "$obj"
512                                         then    echo 'It is in your knapsack.'
513                                                 found=false
514                                         else    echo "I see no $obj here."
515                                         fi
516                                 fi
517                         else    echo 'Throw what?'
518                         fi
519                         ;;
520         u|up)           if cd ..
521                         then    echo 'You pull yourself up a level.'
522                         else    echo "You can't reach that high."
523                         fi
524                         ;;
525         wake)           if [ "$obj" ]
526                         then    echo "You awaken the $obj monster:"
527                                 PATH=$OPATH $obj $x
528                                 echo 'The monster slithers back into the darkness.'
529                         else    echo 'Wake what?'
530                         fi
531                         ;;
532         w|where)        echo "You are in $room."
533                         ;;
534         xyzzy)          if cd
535                         then    echo 'A strange feeling comes over you.'
536                         else    echo 'Your spell fizzles out.'
537                         fi
538                         ;;
539         *)              if [ "$verb" ]
540                         then    if sh -c $wiz
541                                 then    PATH=$OPATH $verb $obj $x
542                                 else    echo "I don't know how to \"$verb\"."
543                                         echo 'Type "help" for assistance.'
544                                 fi
545                         else    echo 'Say something!'
546                         fi
547                         ;;
548         esac
549 done