#!/bin/bash
#
# TAplay --- the automagical text adventure (aka. Interactive Fiction)
#            playing session launcher.
#            
# copyleft 10Apr2006 by Valerie Winter
# copyleft/maintenance since 2008 by Ren Kuligowski
#
#
# DISCLAIMER:
#  TAPLAY WILL *ONLY* RUN ON A UNIX SYSTEM, OR A SYSTEM USING PORTS OF
# UNIX LIBRARIES AND UTILITIES AS WELL AS A UNIX-CONFORMANT FILESYSTEM
# HIERARCHY.  IT WILL *NOT*  RUN ON MICROSOFT "OPERATING SYSTEMS".  IT
# *DOES* RUN ON MACOS X, AMIGAOS 2.x+ THRU 4.x, OS/2 OR ECS, BEOS, AND
# QNX.
#
# --------------------------------------------------------------------
#
#  PREAMBLE / LEGAL NOTICE
#
#  1. terms of use
#
#   This software,  its documentation and all of  its associated files
# come  under the  terms  of  the "GNU  General  Public License"  (see
# gnu.org)  and   can  be  freely  used  and/or   distributed  in  any
# NON-COMMERCIAL and  PROFIT-LESS manner  by anyone for  personal use,
# with the  exception of those  persons and/or institutions  stated in
# paragraph 2.
#
#
#  2. non-profit distribution
#
#   You  require the  explicit permission  of the  author to  use this
# script in  a compilation  or any other  kind of  publicly accessible
# media,  including websites; with  the only  exception of  a download
# area that  is free of charge and  does not require a  person that is
# wanting to download to register and/or contribute in any way.
#
#
#---------------------------------------------------------------------
#
# TAplay ---  a helper script to  automagically find and launch a text
#             adventure  storyfile on a  tty/vc or  in a  detached X11
#             process.
#
#  "One script to find them all,  to bring them forth and in a process
#   bind them, in tty or X app, just where preference lies."
#    ---the author (imitating another author)
#
# copyleft 10Apr2006 by Valerie Winter
#
#         TAplay can be  used as a central backend to  a GUI where the
#       user can choose  the game he wants to play  from a list (using
#       -f parameter and  database contents) and launch it.   I use it
#       mainly as  a shell utility (I  am a lazy  text console junkie)
#       and as a backend launcher  from X11 menus which simply contain
#       an entry  like '+"game" exec taplay  story.file' (example from
#       fvwm2).
#
#   TAPLAY  IS PROVIDED "AS-IS"  WITHOUT ANY  GUARANTEES except  1) it
# works on any unix-alike system and  2) if it doesn't, you either are
# missing standard  utilities or  you simply messed  it up,  being the
# thoughtless code twiddler  that you are.  By nature,  TAplay can and
# will  only do  what it  is intended  for, and  that's a  very single
# purpose: to aid  you in finding and launching  your if games, either
# as   a  detached   X11   process  or   "locally"   on  the   current
# vc/tty/pty/whatever terminal you use.
#
# Feel free to use, distribute and tailor to your needs as long as you
# state me as the original author and also state what you modified.
#
# usage:     run "taplay" without parameters for usage information
#            --- or browse this script
#
# description:
#              Currently,  TAplay   works  with  ZCode/Infocom,  Scott
#            Adams,  Magnetic Scrolls,  Level9, AGT,  Adrift, ALan2/3,
#            TADS2/3,  Hugo,  and  Adventure System  interpreters  and
#            finds   storyfiles  in   all   common  unix   directories
#            (including ./,  $HOME and $HOME{<codetype>}, $ZCODE_PATH,
#            $INFOCOM_PATH, $AGT_PATH and $LEVEL9DIR) as well as files
#            with given full name.   TAplay can make some good guesses
#            on  the type  of  the  game file  and  chooses the  right
#            interpreter based on  its internal substitution lists, or
#            quits  with an  error message  if no  interpreter  can be
#            found on your system.
#              TAplay compiles and runs  source code on the fly, given
#            that an appropriate compiler is properly installed and in
#            your  path.  See  "taplay  -li" for  supported and  found
#            compilers.   Any  code will  be  generated using  default
#            settings, ZCode  always to v8 --- you'll  have to compile
#            manually if you want other settings.
#              TAplay uses internal  checks, blorb iFiction records or
#            informational chunks  and its own  databases to determine
#            the file type and to give  an xterm the game title as its
#            own  window  name.  The  database  either  has  to be  in
#            /usr/lib/games/taplay or in the same directory as taplay.
#            to edit  it, just open  it in your favourite  text editor
#            (or type "taplay -db" and enter "v" to use your $EDITOR).
#
#
# TAplay has been tested on:
#   - debian GNU/Linux 3.0 "woody" and 3.1 "sarge" (ix86, powerpc)
#     -->ought to run on any LFS/FHS compliant Linux distrib
#   - FreeBSD 5.2 (ix86) and NetBSD 2.1 (m68k+ppc)
#     ought to run on any BSD spawn (including MacOS X and QNX)
#   - MacOS X 10.4.x "Tiger"  with BSD, X11 and development subsystems
#     fully installed (powerpc)
#   - QNX Realtime Platform 6.2 (ix86)
#   - BeOS 5.1 (ix86, m68k)
#   - OS/2 3.5 running GNU bash, GNU shelltools and XFree86/emx 3.6
#     (ix86); obviously should run on OS/2 4.x and ECS, too
#   - AmigaOS 3.9/m68k and AROS/i386, each running GeekGadgets/emx
#
# TAplay *hasn't* been tested on:
#   - GNU-OS (aka. GNU HURD), but ought to run as on Linux
#   - further Mach- and Microkernel-based  systems other  than MacOS X 
#     and QNX
#   - EComStation (aka. OS/2 4.5+)
#   - SunOS,  Solaris, NeXTStep, SCO OpenUnix, AIX,  HP-UX, Sinix, and
#     any other commercial unix variants
#
# TAplay will *NEVER* be tested on:
#   - Microsoft Windows, either pure or running CygWin or another Unix
#     environment simulation.  If it runs,  be happy;  if  it doesn't,
#     you're on your own to get it working.
#
#   Browse this script for details on  how it works and what it cannot
# (yet) do,  but do not change  anything below the  line (which states
# "the line") unless you fully understand how this script works.
#   If you'd like to improve this  script or to code a better version,
# give me your feedback and make me do it into a new release.
#
# Changelog and to-do-list (in order of priority ranking):
#
# see the files CHANGELOG and TO-DO.
#
### vw


#---------------------THE LINE ---------------------------------------
# please keep your fingers away from anything below here...
# ... this is the script part and is easily messed up.

self=taplay;
version=0.9.8;
self_year=2006;
self_author="Valerie Winter";
self_fqfn="$0";
parameters="$@";
datadir=/usr/lib/games/$self;
corercname=taplay.rcpart;
coredefname=taplay.definitions;
magicname=db.tamagic;
dbname=db.storyfiles;
buggylistname=db.buggyfiles;
xrdbname=db.xrdbparams;
corerc=$datadir/$corercname;
coredef=$datadir/$coredefname;
magic=$datadir/$magicname;
database=$datadir/$dbname;
xrdbfile=$datadir/$xrdbname;
buggyfiles=$datadir/$buggylistname;
tempname=$self.temp;
tempfile=$datadir/$tempname;
usrtemp=$HOME/$tempname;
rcfile=$HOME/.${self}rc;
logfile=$HOME/$self.log;
fallbackdir=$datadir/fallback;
utilsdir=$datadir/utils;
zccbin=$utilsdir/zcc;
ifcompilebin=$utilsdir/ifcompile;

# out of experience, I never rely  on local default settings, so I use
# the binaries directly, without any alias or environmental variables
test="builtin test";  # this assumes bash as set in the first line
which="type -p";      #re-define behaviour of "which"
file="`$which file` -L";
cut="`$which cut`";
wgrep="`$which grep` -w";
agrep="`$which grep` -a";
grep="`$which grep`";
ex="`$which ex`";
basename="`$which basename`";
dirname="`$which dirname`";
# we assume X11 is installed on a typical system that runs $self
xrdbload="`$which xrdb` -override";
#xrdbload="`which xrdb` -load";
xrdbremove="`$which xrdb` -remove";


# those messages are (or aren't) used in $self's output
msg_quiet="($self: psst, we are in quiet mode)"; # no, we don't use this... ;)
msg_mode=""; # this one has to remain unset!
msg_starting="detaching process";
msg_found="found";
msg_foundin="found in"; 
msg_notfound="couldn't find";
msg_notest="not tested";
msg_failed="failed";
msg_source="source code";


# import core definitions or abort if they are unavailable
$test -r "$corerc" && source "$corerc" \
    || { echo "$self: error: core rc file missing!"; exit 1; }

$test -r "$coredef" && source "$coredef" \
    || { echo "$self: error: core definitions file missing!"; exit 1; }


# load the list of buggy storyfiles that have to be handled in special
# ways  (currently, only Varicella.z8,  Photopia.z5, and  cave.ulx and
# cave.gblorb)
$test -r "$buggyfiles" && \
    buggylist=`cat $buggyfiles`;


# if the user has an rc file, load it
$test -r "$rcfile" && source $rcfile;


# for the unified  look-and-feel, this is used for  X11 apps and xterm
# and appears as parameter in some of the following list entries
# (old default is whitesmoke [rgb:245/245/245] on black; new is grey95
# on black).
# test if user has set a preference
$test -z "$default_background" && default_background=grey95;
$test -z "$default_foreground" && default_foreground=black;


# load $self's Xrdb settings into the X11 resource manager database
$test "$DISPLAY" -a  ! "$NOXAPP" && \
  {
     $test -r "$xrdbfile" && \
       {
	 ($xrdbload $xrdbfile &>/dev/null);
	 wait;
       } \
	 || echo "$self: warning: xrdb data file not available, using current defaults";
  }



# Now,  handle native  shell window  engines (as  of yet  under work).
# When  I have  the time  to  grep the  manuals, I  will complete  the
# terminal  entries below.  Everything  I entered  here is  taken from
# (erratic, I'm afraid) memory since I have switched every machine ---
# except for  those running MacOS X  or AmigaOS 3.9 ---  to Linux some
# time ago. (maybe you do this for me and send me a copy?)
osid="darwin os2 ecs amiga aros qnx beos";
for os in $osid; do
    $test "`echo $OSTYPE | $grep $os`" && \
    { 
	case $os in
	    darwin) OS_IS="MacOS X or GNU/Darwin";
		    term_std="$term_std -tn xterm-color";
		    term_inverse="$term_inverse -tn xterm-color";
		    # treat MacOS X like unix
		    ;;
	   os2|ecs) OS_IS="OS/2";
		    # 'start /b /win "title" /prog "program params"';
		    terminal="start /b /win";
		    term_std="";
		    term_inverse="";
		    term_classic="";
		    term_amber="";
		    term_trs80="";
		    term_8bit="";
		    term_title="";
		    term_exec="/prog";
		    ;;
	amiga|aros) OS_IS="AmigaOS";
		    # 'newshell con:/offsx/offsy/sizex/sizey/"title" from <script>'
		    terminal="newshell";
		    term_std="con:10/10/600/400/";
		    term_inverse="";
		    term_classic="";
		    term_amber="";
		    term_trs80="";
		    term_8bit="";
		    term_title="";
		    term_exec="from";
		    ;;
	       qnx) OS_IS="QNX RTP";
		    terminal="";
		    term_std="";
		    term_inverse="";
		    term_classic="";
		    term_amber="";
		    term_trs80="";
		    term_8bit="";
		    term_exec="";
		    ;;
	      beos) OS_IS="BeOS";
		    terminal="";
		    term_std="";
		    term_inverse="";
		    term_classic="";
		    term_amber="";
		    term_trs80="";
		    term_8bit="";
		    term_exec="";
		    ;;
           Windows) # not implemented
		    ;;
	     # everything else is assumed being a unix
	         *) OS_IS="a unix variant";
		    ;;
	esac
	# port the local variable to global context
	osident=$os;
    }
done
if $test "`echo $OSTYPE | $grep Windows`"; then
    echo "$self: system shock: environment identifies as 'operating system' but isn't!";
    echo "$self: Consider installing an operating system prior to using me.";
    echo "$self: I refuse to run on silly toys like this one.";
    exit 1;
fi


# handle some paths that have been set via shell variables
if $test "$ZCODE_PATH" -o "$INFOCOM_PATH" -o \
     "$LEVEL9DIR" -o "$AGT_PATH"; then
    envpaths="$ZCODE_PATH $LEVEL9DIR $AGT_PATH";
    $test "$ZCODE_PATH" = "$INFOCOM_PATH" || \
	envpaths="$INFOCOM_PATH $envpaths";
    # turn the ":" delimiter into " "  so that we have a list which is
    # demlimited by spaces and usable with "for foo in $bar; do"
    echo $envpaths >$tempfile;
    $ex $tempfile &>/dev/null <<EOF
%s/:/ /g
w
q
EOF
    envpaths="`cat $tempfile; rm -f $tempfile &>/dev/null`";
    # avoid redundancies in paths
    for path in $envpaths; do
	# first, snip last dir name if already in $filedirs
	for dir in $filedirs; do
	    $test "`basename $path`" = "$dir" && path=`dirname $path`;
	done
	tempfdir="$tempfdir $path";
    done
    envpaths="$tempfdir";
    # then, check if the directory is already in searchlist
    for path in $envpaths; do
	for dir in $datapaths; do
	    $test "$path" = "$dir" && \
		    path="";
	done
	addpaths="$addpaths $path";
    done
    datapaths="$addpaths $datapaths";
fi


function display_usage() {
    cat <<EOF
$self $version --- A text adventure playing session launcher
copyleft $self_year by $self_author
copyleft/maintenance from 2008 ad infinitum by Rene Kuligowski

$self is subject to the GNU General Public Licence v2

    An  automagical text adventure  (aka.  interactive  fiction)  session
  launcher for many of the common adventure engines:  ZCode, Glulx, TADS,
  Hugo, AGT, ALan,  SAAI, ACode, AdvSys, Adrift  (others  can be added by
  you).
    $self is *NOT* an  interpreter and doesn't  include  them.   It just
  starts them  in various  fashions, depending on  circumstances and your
  mood,  while  automagically   finding  the  storyfile  and  a  suitable
  interpreter  on  your  system.  $self's  behaviour  can   be  modified
  anytime, and  it can  play any  number  of sessions  simultaneously (if
  your computer  can handle  it, so can $self), even  on  dumb/streaming
  displays (like Emacs or a web  page)  and remote X11 display servers if
  you  have suitable interpreters.  Also, $self  helps  you  in managing
  your collection.

usage:
    $self -h
    $self -lf|-lp|-li|-d|-mf|-ml
    $self -w <storyfile>
    $self -dq "<string>"
    $self [-v] [-c][-m][-i] [-l] [-s] [-o|-x] [[-ti][-ts][-te][-to]|-tf] 
           [--simulate] [-u <interpreter>] <storyfile>
    
options:
    -h (or no parameters)     this help
    -lf, --listfiles          list all game files found on this system.
    -lp, --listpath           show the search paths for game files.
    -li, --listint            list all interpreters  and compilers found on
                              this system.
    -d, --listdb              show database contents  via $PAGER.  If that
                              can invoke an  editor and you have sufficient
                              rights, you can edit the database, too.
    -dq, --dbquery "<string>" query db about  <string> (will list any entry
                              containing the <string>).
    -mf, --makefvwmmenu       make FVWM menu listing all local storyfiles.
    -ml, --makelist           make a file list usable by TUI/GUI frontends.
    -w, --whatis <file>	      try to  find out the type  of <file> (implies
			      -v).
    -v, --verbose             show all output, not just errors.
    -c, --classic      	      run interpreters in classic/monochrome look.
    -m, --monochrome          run interpreters in monochrome mode.
    -i, --reverse             use white font on black background (xterm)
    -o, --native              force native application (MacOS X, AmigaOS)
    -x, --nonative	      forbid using  native application, use  X11 or
                              text mode
    -s, --streaming	      use  streaming-mode  (dumb)  interpreters  if
                              available (eg. dfrotz, dlevel9, dmagnetic) to
                              play eg. in emacs shell mode
    -u, --useint <int>        force $self to use <int> as interpreter.
    -n, --noxapp      	      do not launch an X application, use xterm.
    -l, --stayhere     	      play on this very vc, ignore that we are in a
                              multi-vc environment like X11.
    -ts, --shorttitles        display only '<game  name>' as xterm title.
    -to, --filenameonly       display the storyfile name as title.
    -ti, --titleint           show interpreter name in title.
    -te, --titlesys           show system engine format in title.
    -tv, --titleversion       show storyfile's s/n, release, and VM.
    -tf, --titlefullinfo      show everything we know about the storyfile.
    --simulate                do  everything except actually  starting the
                              game.

    $self  compiles  and runs source code on the fly if the appropriate
  compiler is  installed on your system.  Currently,  ZCode (Inform 6.30
  and 6.31 .inf sources only, compiling to z8; NOT Inform7 .ni sources),
  HUGO 3, TADS 2 and 3,  ALan 3, and Adventure System 1.2 are supported.
  Others can  be added by simply  creating and filling  in the according
  variables within  this script.  Note  that the sources of  Hugo, TADS,
  and ALan have  to be named according to the  source code version used;
  eg. .hugo2  for Hugo 2, .hug  or .hugo3 for  Hugo 3, .t or  .tads3 for
  TADS3, .tads2  for TADS2, .alan2 for  ALan 2, and .alan  or .alan3 for
  ALan3.  If you  do not do this, $self might try to compile v2 sources
  with a v3 compiler, which will not work.
    Browse this script for more information.

    For  interpreters, tools and  utilities,  start looking at  the site
			  www.ifarchive.org
  and the diverse sites www.<engine>.org (eg. www.alan.org).

  Hint: You shouldn't use GLK  based interpreters except where you don't
        have  a choice;  GLK is  a rudimentary  and  astonishingly badly
        coded  library (seen  from  UNIX view)  that  has very  inferior
        capabilities  in comparison  to purely  native  engines (curses,
        X11).

EOF
    exit 0;
}

# check if our private magic file is accessible
$test -r "$magic" && file="$file -m $magic" || \
  {
    #try a fallback in the same location as the script
    $test -r "`$dirname $self_fqfn`/$magicname" && \
	file="$file -m `$dirname $self_fqfn`/$magicname" || \
	  { 
	    # fall  back  to  system   default  magic  file  w/o  most
	    # storyfiles
	    file="$file";
	    echo "$self: warning: private storyfile magic not available";
          }
  }

# check if our storyfile database is accessible
$test -r "$database" || \
  {
    #try a fallback in the same location as the script
    database="`$dirname $self_fqfn`/$dbname";
    $test -r "$database" || {
	echo "$self: warning: database not available";
	database="";
      }
  }


# sort out all parameters given to us
for param in $parameters; do
  case $param in
   -lf|--listfiles) echo "$self: searching for storyfiles (might take a few seconds)...";
		    for system in $supported_systems; do
			suffices="$suffices `echo \"echo \\${suffix_${system}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
		    done
		    for path in $datapaths; do
			for dir in $filedirs; do
			    if $test -d $path/$dir; then
				echo -e "\n$path/$dir:";
				datctr=0;
				for suffix in $suffices; do
				    $test "$suffix" = "dat" && let datctr=$datctr+1;
				    $test "$suffix" = "dat" -a "$datctr" -gt "1" && \
					continue;
				    $test "`ls $path/$dir/*.$suffix 2>/dev/null`" && {
					pushd $path/$dir &>/dev/null;
					ls *.$suffix;
					popd &>/dev/null;
				      }
				done
			    fi
			done
		    done
		    echo -e "\n$self: done.  some .dat files listed above might *not* be storyfiles!";
		    AUTOQUIT=TRUE;
		    shift;
	 	    ;;
     -li|--listint) echo -n "$self: looking for user defined preferred interpreters... ";
	            echo "(only defined ones are listed)";
		    # note:  if  variables  are  empty, they  are  not
		    # elements  of the  list  (logically, isn't  it?).
		    # hence no checking and stating "(not defined)".
		    #   also, no output will  be given here if all are
		    # undefined.
	            for engine in $supported_systems; do
			int="`echo \"echo \\${${engine}_int}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
			    $test -n "$int" && {
				echo -e -n "\t$engine: ";
                                $test "`$which $int`" && \
				echo "$msg_found `$which $int`" \
				|| echo "$msg_notfound $int";
			      };
		    done
		    echo -e "$self: looking for interpreters from the substitution lists...";
                    for engine in $supported_systems; do
			$test ! "$engine" = "blorb" && \
			  {
			    terps="`echo \"echo \\${${engine}_subst}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
			    echo "interpreters for $engine:";
			    $test "$terps" || echo -e "\t(none known)";
			    for int in $terps; do
				if ($test "`echo $int | cut -c1-2`" = "if") \
				    && ($test ! "$int" = "ifpe"); then
				    continue;
				else $test "`$which $int`" && \
				    echo -e "\t$msg_found `$which $int`" \
				    || echo -e  "\t$msg_notfound $int";
				fi
			    done
			  }
		    done
#		    echo "$self: looking for 'inform' compiler...";
#		    $test "$inform" && echo -e "\t$msg_found $inform" \
#			|| echo $msg_notfound;
                    echo "$self: looking for compilers...";
		    for engine in $supported_systems; do
			$test ! "$engine" = "blorb" && \
			  {
			    comp="`echo \"echo \\${compiler_${engine}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
			    echo -en "\t$engine: ";
			    $test "$comp" && echo $comp \
				|| echo "$msg_notfound one";
			  }
		    done
		    AUTOQUIT=TRUE;
		    shift;
		    ;;
   -lp|--listpaths) echo -n "$self: currently, searching directories for story files, ";
	            echo "including ZCODE_PATH, INFOCOM_PATH, AGT_PATH, and LEVEL9DIR, are:"; 
	            for path in $datapaths; do
		      for dir in . $filedirs; do
			echo "$path/$dir";
		      done
		    done
		    AUTOQUIT=TRUE;
		    shift;
		    ;;
 -mf|--makefvwmmenu) menufile=./menu.ifgames;
	            string1="DestroyMenu";
	            string2="AddToMenu";
	            echo "$self: please wait, generating FVWM menu file $menufile...";
		    echo "suspend me and put me to the background if you have a larger collection";
		    echo "(press C-z, look at the process number [x] and type 'bg x')";
		    # simply call $self -lf ... ;)
		    $self_fqfn -lf >$usrtemp;
		    filelist="`cat $usrtemp | $grep -v $self`";
		    rm -f $usrtemp $menufile;
		    echo "# $self: autogenerated menu for FVWM" >$menufile;
		    echo "# - copy this file into ~/.fvwm or /etc/X11/fvwm" >>$menufile;
		    echo "# - include mnu_games_if into your menu structure" >>$menufile;
		    echo "# - insert 'read \"<path>/menu.ifgames\"' into your rc" >>$menufile;
		    for entry in $filelist; do
			if $test "`echo $entry | cut -c1`" = "/"; then
				menuname="`echo $entry | cut -f1 -d:`";
				echo -e "\n\n${string1} $menuname" >>$menufile;
				echo "${string2} $menuname" >>$menufile;
			else
			    name="`grep -w \"$entry\" $database | cut -f1 -d'|'`";
 			    $test "`echo $entry | cut -f2 -d.`" = "d$$" && \
 				entry="`echo $entry | cut -f1 -d.`.d\\\$\\\$";
			    $test -z "$name" && name=$entry;
			    echo "+ \"$name\" exec $self $entry" >>$menufile;
			fi
		    done
		    menulist="`grep AddToMenu $menufile | cut -f2 -d\" \"`";
		    echo -e "\n\n${string1} mnu_games_if" >>$menufile;
		    echo "${string2} mnu_games_if" >>$menufile;
		    for menu in $menulist; do
			echo "+ \"$menu\" PopUp $menu" >>$menufile;
		    done
		    echo "$self: done.  you should browse and edit $menufile a bit.";
	            AUTOQUIT=TRUE;
		    shift;
	 	    ;;
    -ml|--makelist) # this generates a simple ascii file of the form
	            # <game title> (tab) <author> (tab) $self <filename>
	            # for use with custom frond-end choosers
	            listfile=filelist.$self;
	            echo "$self: creating file list for front-end...";
                    # simply call $self -f ... ;)
		    $self_fqfn -lf >$usrtemp;
		    filelist="`cat $usrtemp | $grep -v $self`";
		    rm -f $usrtemp $listfile;
		    for entry in $filelist; do
			if $test "`echo $entry | cut -c1`" = "/"; then
			    continue;
			else
			    name="`grep -w \"$entry\" $database | cut -f1 -d'|'`";
                            author="`$wgrep \"$entry\" $database | cut -f3 -d'|'`";
			    $test -z "$author" -o "$author" = " " \
				&& author="unknown";
			    $test "`echo $name | cut -c1`" = " " -o -z "$name" \
				&& name="$entry";
			    echo -e "${name}\t${author}\t$self $entry" >>$usrtemp;
			fi
		    done
	            echo "$self: sorting filelist...";
		    sort $usrtemp >$listfile;
		    rm $usrtemp;
	            echo -n "$self: done.  You'll need to edit $listfile a bit, mainly to ";
		    echo "remove doublettes due to fs links and blinds.";
	            AUTOQUIT=TRUE;
		    shift;
	 	    ;;
#      -md|--makedb) # one  day,  this will  be  used  to extract  info
                    # directly from  storyfiles and blorb  metadata to
                    # create a database
#                   dbfile=db.storyfiles;
# 	            echo "$self: creating database from available storyfiles...";
# 	            AUTOQUIT=TRUE;
# 		    shift;
# 	 	    ;;
       -d|--listdb) $test "$PAGER" && $PAGER $database || less $database;
		    AUTOQUIT=TRUE;
		    shift;
		    ;;
     -dq|--dbquery) $test "$PAGER" && {$grep "$2" $database | $PAGER} || \
	                 $grep "$2" $database | less;
		    AUTOQUIT=TRUE;
		    shift;
	 	    ;;
       -w|--whatis) echo "$self: running in what is-mode --- examining story file";
	            WHATIS=TRUE;
	            SILENTIUM="";
		    shift;
		    ;;
       -o|--native) # use OS-depentant native interpreters if available
	            FORCENATIVE=TRUE;
		    NONATIVE="";
		    $test ! "$NONATIVE" && \
			msg_mode="$msg_mode - forcing native interpreter";
		    shift;
                    ;;
     -x|--nonative) # never use OS-depentant native interpreters
	            NONATIVE=TRUE;
		    FORCENATIVE="";
	            msg_mode="$msg_mode - forbidding native interpreter, using X11 or text";
		    shift;
                    ;;
       -n|--noxapp) NOXAPP=TRUE;
		    OS_IS="";
	            msg_mode="$msg_mode - user request to prefer xterm";
		    shift;
		    ;;
     -l|--stayhere) # run in local (this very) terminal
	            NOXAPP=TRUE;
		    DISPLAY="";
		    OS_IS="";
	            msg_mode="$msg_mode - user request to run in this vt";
		    msg_starting="running interpreter here";
		    shift;
		    ;;
      -i|--reverse) $test "$INVERSE" && INVERSE="" || INVERSE=TRUE;
                    #  this is  here if you  want to  reverse $self's
                    # behaviour by default
	            msg_mode="$msg_mode - inverse xterm mode requested";
		    shift;
		    ;;
      -c|--classic) CLASSIC=TRUE;
	            msg_mode="$msg_mode - \"classic\" mode requested";
		    shift;
		    ;;
   -m|--monochrome) MONO=TRUE;
	            msg_mode="$msg_mode - \"monochrome\" mode requested";
		    shift;
		    ;;
       -u|--useint) FORCEDINT=TRUE;
	            preferred="$2";
       	            msg_mode="$msg_mode - user forced interpreter";
		    shift;
		    shift;
		    ;;
    -s|--streaming) STREAMING=TRUE;
	            NONATIVE=TRUE;
		    NOXAPP=TRUE;
		    DISPLAY="";
		    OS_IS="";
		    PREFERRED=TRUE;
       	            msg_mode="$msg_mode - user forced streaming";
		    shift;
		    ;;
      -v|--verbose) $test "$SILENTIUM" && SILENTIUM="" || SILENTIUM=TRUE;
                    #  this is  here if you  want to  reverse $self's
                    # behaviour by default (see rcfile)
		    shift;
		    ;;
  -ts|--shorttitle) SHORTTITLE=TRUE;
	            # game name only
		    shift;
		    ;;
-to|--filenameonly) FILENAMEONLY=TRUE;
	            # "A Text Adventure (story.file)"
		    shift;
	 	    ;;
    -ti|--titleint) TITLEINT=TRUE;
	            # show interpreter in title
		    shift;
	 	    ;;
    -te|--titlesys) TITLESYS=TRUE;
	            # show engine (system) in title
		    shift;
	 	    ;;
 -tv|--titleversion) TITLEVER=TRUE;
	            # show game version and release in title
	            # (forces probing of zcode/glulx files)
		    shift;
	 	    ;;
 -tf|--titlefullinfo) TITLEINT=TRUE;
	            TITLESYS=TRUE;
	            TITLEVER=TRUE;
		    NONAME=TRUE;
		    FILENAMEONLY="";
		    SHORTTITLE="";
		    shift;
	 	    ;;
        --simulate) # this is for testing purposes only (to avoid tons
		    # of  open windows  and  resource eating  detached
		    # processes  with  no connection  to  a tty  while
		    # finding that tiny bug).
		    # $self does  everything except actually starting
		    # an interpreter.
		    echo "$self: running in simulation/diagnostics mode";
		    msg_starting="simulating only";
		    SIMULATE=TRUE;
		    SILENTIUM="";
		    shift;
		    ;;
		 *) $test "`echo $param | $cut -c1`" = "-" && \
			display_usage;
		    storyfile=$param;
		    ;;
   esac
done
$test "$AUTOQUIT" && exit 0;

# if no storyfile given, display usage and exit (from within function)
$test -z "$storyfile" && display_usage;

$test "$UID" = "0" -o "$GID" = "0" && \
  {
    echo "$self: ERROR: I was run by a superuser with intention to play.";
    echo -e "\tYou really shouldn't play from administrative accounts.  NEVER EVER.";
    echo -e "\tLog in as a normal user, then play anything you want.";
    exit 1;
  }

# ok, so $self was given a storyfile.  on we go.

# if the game file was given  without a path, try to find it somewhere
# in the $datapaths/$datadirs
firstchar=`echo $storyfile | $cut -c1`;
first2chars=`echo $storyfile | $cut -c1-2`;
if ($test "`$basename $storyfile`" = "$storyfile" -a ! -f "`$basename $storyfile`") && \
	 ($test ! "$firstchar" = "/" -a ! "$first2chars" = "./"); then
    $test ! "$SILENTIUM" && \
	echo -n "searching for \"$storyfile\"... ";
    for path in $datapaths; do
	for to in . $filedirs; do
	    $test -f "$path/$to/$storyfile" && \
		{ 
		    $test ! "$SILENTIUM" && echo "$msg_foundin $path/$to/";
		    fullpath="$path/$to/$storyfile";
		    break 2;
		} || fullpath="";
	done
    done
    $test ! "$fullpath" && \
       {
	 $test ! "$SILENTIUM" && echo $msg_failed;
	 echo "$self: error: cannot find $storyfile"; 
	 exit 1;
       }
else fullpath=$storyfile;
fi

# determine storyfile type.  look in the database first, and when that
# fails, try to find out.  if this is a blorb and contains an if-babel
# ifiction entry, set name and  author from there, while the engine is
# determined beforehand.
gamename="`$basename $storyfile`";
filesuffix=`echo $gamename | cut -f2 -d.`;
$test "$database" && is_known=`$wgrep $gamename $database` || is_known="";
if $test "$is_known"; then
    # get the other information as well
    system="`echo $is_known | $cut -f2 -d'|'`";
    $test "`echo $filesuffix | $grep blorb`" -o "`echo $filesuffix | $grep blb`" -o \
	"`echo $filesuffix | cut -c2-`" = "lb" && \
	system="${system}blorb";
    gametitle="`echo $is_known | $cut -f1 -d'|'`";
    gameauthor="`echo $is_known | $cut -f3 -d'|'`";
    gamedate="`echo $is_known | $cut -f5 -d'|'`";
    $test "$gameauthor" = " " -o -z "$gameauthor" && \
	gameauthor="(unknown)";
    filetype="`echo \"echo \\${ft_${system}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
    $test ! "$SILENTIUM" && \
      {
	echo -n "database knows $gamename as the $filetype engine format game ";
	echo "\"$gametitle\" by $gameauthor $gamedate";
	#$test "$SIMULATE" && echo "[db entry: \"$is_known\"]";
	$test "$WHATIS" && \
	    echo "let's see if this is correct";
      }
    # if there is  a file with ambiguous suffix  in the database, make
    # sure we try to determine its actual contents for safety
    case $filesuffix in
	blb|blorb|dat|data|gam|game|story|main)
	    NONDESCRIPT=TRUE;
	    ;;
    esac
else
    $test ! "$SILENTIUM" && \
	echo "\"$gamename\" is not listed in database";
fi
# the  following  if..fi  superstructure  has  been  commented  in  to
# *always* force  kind-of-storyfile checks.  If  your system is  a bit
# slow  and $self  takes  *ages*  to run  the  storyfile, remove  the
# commentary '#'s  in the  following three lines  and before  the 'fi'
# marked "end of the superstructure" below.
#
#if ($test ! "$is_known") || ($test "$is_known" -a "$WHATIS") || 
#   ($test "$NONDESCRIPT") || \
#   ($test "$TITLEVER" -a ! "`echo $system | grep blorb`"); then
    # try to find  out which interpreting system to  use.  Since we do
    # not go by file suffix,  but by filemagic, this is quite reliable
    # and  will  result in  unpredictable  behaviour  very rarely  ---
    # mostly, only if you have messed up the following code.  SAAI and
    # A-Code storyfiles could be  virtually anything else, so the file
    # suffices will  only be used  as additional hint.  Since  you are
    # expected to use $self only with IF storyfiles, everything ought
    # to work reliably.
    if $test ! "$SILENTIUM"; then
	$test "$NONDESCRIPT" && echo -n "--- however, suffix '$filesuffix' is ambiguous, ";
	echo -n "determining file type... ";
    fi
    $test -z "$filemagic" && \
	filemagic="`$file $fullpath 2>/dev/null | cut -f2 -d: | cut -c2-`";
    magicword=`echo $filemagic | $cut -f1 -d" "`;
    $test "$magicword" = "empty" -o "$magicword" = "" && {
 	echo -e "\n$self: error: this file is empty or otherwise damaged";
 	exit 1;
       }
    filesuffix=`echo $gamename | $cut -f2 -d.`;
    filetype="unknown";
    system="unknown";
    case $magicword in
	Assembler) # automagical compile  and run inform  source code,
	           # pt1a
	           for suffix in $suffix_source_zcode; do
	               $test "$filesuffix" = "$suffix" && \
			 {
			   system="zcode";
			   filetype=$ft_compiler_zcode;
		         }
	           done
	           ;;
   Infocom|Inform) magictype=`echo $filemagic | $cut -f4 -d' '`;
	      if $test "$magictype" = "game"; then
		  for suffix in $suffix_zcode; do
		       $test "$filesuffix" = "$suffix" && \
			 {
			   system="zcode";
			   filetype=$ft_zcode;
			 }
		  done
		  storyfile_vm=`echo $filemagic | cut -f7 -d' ' | cut -c1`;
		  gameserial="`echo $filemagic | cut -f11 -d' ' | cut -c1-6`";
		  gamerelease="`echo $filemagic | cut -f9 -d' ' | cut -f1 -d,`";
	      fi
	      $test "$magictype" = "save" && \
		{
		   system="non-exec";
		   filetype=$ft_save;
		}
	      ;;
       Glulx) for suffix in $suffix_glulx; do
		   $test "$filesuffix" = "$suffix" && \
		     {
		       system="glulx";
		       filetype=$ft_glulx;
		    }
	      done
	      storyfile_vm=`echo $filemagic | cut -f5 -d' ' | cut -c1`;
	      gameserial="`echo $filemagic | cut -f9 -d' ' | cut -c1-6`";
	      gamerelease="`echo $filemagic | cut -f7 -d' ' | cut -f1 -d,`";
	      ;;
    Magnetic) if $test "`echo $filemagic | $wgrep graphics`" -o \
	         "`echo $filemagic | $wgrep hints`"; then
                  system="non-exec";
		  filetype=$ft_nonexec;
              else
		  for suffix in $suffix_msrl; do
		       $test "$filesuffix" = "$suffix" && \
			 {
			   system="msrl";
			   filetype=$ft_msrl;
			 }
		  done
	      fi
	      ;;
   Applesoft) for suffix in $suffix_alan2; do
		   $test "$filesuffix" = "$suffix" && \
		     {
		       system="alan2";
		       filetype=$ft_alan;
		     }
	      done
	      ;;
      AdvSys) for suffix in $suffix_advsys; do
		   $test "$filesuffix" = "$suffix" && \
		     {
		       system="advsys";
		       filetype=$ft_advsys;
		     }
	      done
	      ;;
	TADS) tadsver=`echo $filemagic | $cut -f2 -d" "`;
	      for suffix in $suffix_tads; do
		   $test "$filesuffix" = "$suffix" && \
		     {
		       system="tads$tadsver";
		       $test "$tadsver" = "2" && filetype=$ft_tads2;
		       $test "$tadsver" = "3" && filetype=$ft_tads3;
		     }
	      done
	      ;;
	ALAN) alanver=`echo $filemagic | $cut -f5 -d" "`;
	      for suffix in $suffix_alan2 $suffix_alan3; do
		   $test "$filesuffix" = "$suffix" && \
		     {
		       system="alan$alanver";
		       $test "$alanver" = "2" && filetype=$ft_alan2;
		       $test "$alanver" = "3" && filetype=$ft_alan3;
		     }
	      done
	      ;;
	 IFF) # with Blorb, we dont need to check the file suffix since
	      # the magic contents of IFF resource forms are unique
	      isblorb="`echo $filemagic | $grep 'Blorb'`";
	      isquetzal="`echo $filemagic | $grep 'Quetzal'`";
	      if $test "$isblorb"; then
		 for chunk in IFhd SNam AUTH "(c) " ANNO RelN Fspc; do
		     $test "`$agrep $chunk $fullpath`" && \
		       {
			 has_chunks="$has_chunks $chunk";
			#
			#    this space is intentionally left blank ;-)
			#
			# $test ! "$chunk" = "IFhd" && \
			#    echo -e "\t\"$chunk\": $chunk_content"; 
			#done
		       }
		 done
                 if $test ! "`$grep Exec $fullpath`"; then
                      system="non-exec";
		      filetype="$ft_nonexec";
		 else
		     for item in $blorbtypes; do
			$test "`$grep $item $fullpath`" && \
			    filetype=$item;
			signature=$filetype;
		     done
		     if $test "$filetype"; then
			 case $filetype in
			     ZCOD) system="zcodeblorb";
				   filetype=$ft_zcode;
				 ;;
			     MSRL) system="msrlblorb";
				   filetype=$ft_msrl;
				 ;;
			     LVL9) system="level9blorb";
				   filetype=$ft_acode;
				 ;;
		   TADS|TAD2|TAD3) system="tadsblorb";
				   filetype=$ft_tads;
				 ;;
			     HUGO) system="hugoblorb";
				   filetype=$ft_hugo;
				 ;;
		   ALAN|ALN2|ALN3) system="alan3blorb";
				   filetype=$ft_alan3;
				 ;;
		   ADAM|SAAI|SAGA) system="saaiblorb";
				   filetype=$ft_saai;
				 ;;
			     GLUL) system="glulxblorb";
				   filetype=$ft_glulx;
				 ;;
			 esac
		     fi
		 fi
		 #filetype="blorbed $filetype resources";
		 filetype="blorbed $filetype";
	      # if this is a Quetzal save file, say so
	      elif $test "$isquetzal"; then
		 filetype=$ft_qsave;
		 system="non-exec";
	      fi
	      ;;
	data) # here,  we actually need  the file  suffix to  find out
              # what we have --- it  is only reliable if the user made
              # sure that it is a storyfile of some kind.  Well, if it
              # isn't, the interpreter will  simply refuse to start or
              # crash itself.  Or something.  Keyword error handling.
	      for suffix in $suffix_acode; do
	               $test "$filesuffix" = "$suffix" && {
			   system="acode";
			   filetype=$ft_acode;
		         }
	      done
	      for suffix in $suffix_adrift; do
	               $test "$filesuffix" = "$suffix" && {
			   system="adrift";
			   filetype=$ft_adrift;
		         }
	      done
	      for suffix in $suffix_agt; do
	               $test "$filesuffix" = "$suffix" && {
			   system="agt";
			   filetype=$ft_agt;
		         }
	      done
	      for suffix in $suffix_advsys; do
	               $test "$filesuffix" = "$suffix" && {
			   system="advsys";
			   filetype=$ft_advsys;
		         }
	      done
	      for suffix in $suffix_hugo; do
	               $test "$filesuffix" = "$suffix" && {
			   system="hugo";
			   filetype=$ft_hugo;
		         }
	      done
	      for suffix in $suffix_alan2; do
	               $test "$filesuffix" = "$suffix" && {
			   system="alan2";
			   filetype=$ft_alan2;
		         }
	      done
	      for suffix in $suffix_alan3; do
	               $test "$filesuffix" = "$suffix" && {
			   system="alan3";
			   filetype=$ft_alan3;
		         }
	      done
	      ;;
       ASCII) for suffix in $suffix_saai; do
	               $test "$filesuffix" = "$suffix" && {
			   system="saai";
			   filetype=$ft_saai;
		         }
	      done
              # automagical compile and run source code, pt1b
	      for suffix in $suffix_source_zcode; do
	               $test "$filesuffix" = "$suffix" && {
			   system="zcode";
			   filetype=$ft_compiler_zcode;
		         }
	      done
	      for suffix in $suffix_source_advsys; do
	               $test "$filesuffix" = "$suffix" && {
			   system="advsys";
			   filetype=$ft_compiler_advsys;
		         }
	      done
	      for suffix in $suffix_source_alan2; do
	               $test "$filesuffix" = "$suffix" && {
			   system="alan2";
			   filetype=$ft_compiler_alan2;
		         }
	      done
	      for suffix in $suffix_source_alan3; do
	               $test "$filesuffix" = "$suffix" && {
			   system="alan3";
			   filetype=$ft_compiler_alan3;
		         }
	      done
	      for suffix in $suffix_source_tads2; do
	               $test "$filesuffix" = "$suffix" && {
			   system="tads2";
			   filetype=$ft_compiler_tads2;
		         }
	      done
	      for suffix in $suffix_source_tads3; do
	               $test "$filesuffix" = "$suffix" && {
			   system="tads3";
			   filetype=$ft_compiler_tads3;
		         }
	      done
	      for suffix in $suffix_source_hugo; do
	               $test "$filesuffix" = "$suffix" && {
			   system="hugo";
			   filetype=$ft_compiler_hugo;
		         }
	      done
	      ;;
    esac
    # give some feedback on what we found out
    if $test "$system" = "unknown"; then
	$test ! "$SILENTIUM" && echo $msg_failed;
	echo "$self: error: $storyfile is no recognizable IF story data";
	exit 1;
    else
	$test ! "$SILENTIUM" && { \
	    echo -e "\n\t- suffix is \"$filesuffix\", but this doesn't mean anything";
	    echo -e -n "\t- filemagic is ";
	    $test "$filemagic" && echo "\"$filemagic\"" || echo "$msg_notest";
	    if ($test "`echo $filetype | $grep blorb`"); then
		echo -e -n "\t- it ";
		$test "$signature" \
		    && echo -n "contains a \"$signature\" " \
		    || echo -n "does not contain an ";
                echo "executable signature";
		$test ! "$has_chunks" = "" && \
	           echo -e "\t- it contains informational signatures: $has_chunks";
	    fi
	    echo "... seems to be $filetype.";
	  }
	$test "$SILENTIUM" && \
	  {
	    $test "$system" = "non-exec" && \
		echo "$self: this is a $filetype file, not an IF story";
	  }
    fi
#fi    #--- end of superstructure

# if $storyfile is  a blorb, query the iFiction  record (if available)
# and/or the  blorb's informational chunks  (if available) to  set the
# window title
if $test "`echo $filetype | $grep blorb`" -o "`echo $system | $grep blorb`"; then
    # ^-- '$test  "$isblorb"' wouldn't  suffice here because  we might
    # not have tested the file type and set "isblorb"
    has_ifiction=`$grep IFmd $fullpath`;
    if $test "$has_ifiction"; then
	is_known=TRUE;
	ifictver=`$agrep '<ifindex' $fullpath | cut -f2 -d'"'`;
	if $test "$ifictver" = "1.0"; then
	    gamedate=`$agrep '<firstpublished>' $fullpath | cut -f2 -d'>' | cut -f1 -d'<'`;
	else
	    gamedate=`$agrep '<year>' $fullpath | cut -f2 -d'>' | cut -f1 -d'<'`;
	fi
	gametitle=`$agrep '<title>' $fullpath | cut -f2 -d'>' | cut -f1 -d'<'`;
	gameauthor=`$agrep '<author>' $fullpath | cut -f2 -d'>' | cut -f1 -d'<'`;
	engine=`$agrep '<format>' $fullpath | head -n 1 | cut -f2 -d'>' | cut -f1 -d'<'`;
	gamerelease=`$agrep '<release>' $fullpath | grep '/' | cut -f2 -d'>' | cut -f1 -d'<'`;
	gameserial=`$agrep '<serial>' $fullpath | cut -f2 -d'>' | cut -f1 -d'<'`;
	coverart=`$agrep '<cover' $fullpath | head -n 1 | cut -f2 -d'>' | cut -f1 -d'<'`;
        $test ! "$SILENTIUM" && \
	  {
	    echo -n "this Blorb contains an iFiction v$ifictver record: ";
	     echo -n "\"$gametitle\"";
	     $test -n "$gameserial" -a -n "$gamerelease" && \
		 echo -n " (s/n $gameserial/release $gamerelease)";
	     echo ", $engine engine, by $gameauthor in $gamedate";
	  }
    else
	$test ! "$SILENTIUM" && \
	    echo "note: this is an older Blorb without iFiction record";
    fi
fi


# display a note  about appropriately naming files, at  least by using
# softlinks,  if  the suffix  is  ambiguous,  conflicts  with MIME  or
# disturbs other  suffix-based contexts (like  in Windows or  MacOS or
# some unix GUIs like KDE and GNOME).
#   Advantage:  make  a  pool  directory  and  browse  it  by  ex-  or
# in-cluding the engine format simply  by a single suffix each.  Think
# of finding duplicates, revisions,  releases, ports, series or single
# storyfiles by  name parts,  by company or  by author...  and  all of
# that without even the slightest GUI and with a minimum of typing.
# examples:
# ls -l /usr/share/games/if/pool/*[Zz]ork*
# ls -l /usr/share/games/if/pool/[Ee]mily_[Ss]hort*.z*
# ls -l /usr/share/games/if/pool/*.[^Ss]* (all non-SAAI)
# ls -l /usr/share/games/if/pool/*[Tt]emple*.z*
# ls -l /usr/share/games/if/pool/port-[Aa]dventure*.{z?,*ulx,*blorb}
#
# ### note: this routine commented in for reasons of speed
#
# if $test ! "$filesuffix" = "$system" -a ! "$filesuffix" = "magscroll" -a \
#    ! "$system" = "non-exec" -a ! "`echo $filesuffix | cut -c2-`" = "blorb"; then
#     if $test "`echo $system | grep blorb`"; then
# 	bestsuffix="`echo $system | cut -c1`blorb";
#     elif $test "$system" = "msrl"; then
# 	bestsuffix="magscroll";
#     else 
# 	$test "`echo $filetype | grep 'non-exec'`" && \
# 	    bestsuffix="rblorb" || \
# 	    bestsuffix=`echo $system`;
#     fi
#     if $test "$gametitle" -a "$gameauthor"; then
# 	$test ! "$gameauthor" = "(unknown)" && \
# 	  {
# 	    for item in $gameauthor; do
# 		newfileauthname="${newfileauthname}_$item";
# 	    done
# 	    # strip leading underscore
# 	    newfileauthname=`echo $newfileauthname | cut -c2-`;
# 	  }
# 	for item in $gametitle; do
# 	    newfilename="${newfilename}_$item";
# 	done
# 	# strip subtitles, which usually start after a colon
# 	newfilename=`echo $newfilename | cut -f1 -d:`;
# 	# strip leading underscore
# 	newfilename=`echo $newfilename | cut -c2-`;
# 	# concatenate full name
# 	$test ! "$gameauthor" = "(unknown)" && \
# 	    bestname="${newfileauthname}-$newfilename" \
# 	    || bestname="";
#     else
# 	# a hint how to build the name
# 	newfilename="<the_story_title>";
#     fi
#     # this is intended to be displayed in any case
# #    echo -n "$self: hint: for clarity, you should softlink the file to ";
#     echo -n "$self: hint: for clarity, you should softlink $storyfile to ";
#     echo -n "\"$newfilename.$bestsuffix\" ";
#     $test "$bestname" && echo -n "or \"$bestname.$bestsuffix\" ";
#     echo "(to stay compatible with stubborn interpreters, don't rename it directly)";
# fi

# display  note about blorb  files without  executable code,  where it
# would be pointless to try an engine randomly
if ($test "$isblorb" -a "$system" = "non-exec") && ($test ! "$WHATIS"); then
    echo -n "$self: Add the storyfile to the blorb or start it manually with the ";
    echo "appropriate interpreter.";
    exit 1;
fi

# WHATIS-mode or non-exec code ends the script right here
$test "$WHATIS" \
    -o "$system" = "non-exec" \
    -o "$system" = "unknown" && \
    exit 0;


# automagical  compile and run  source code,  pt2: compile  the source
# into a storyfile and then run that with an interpreter
$test "`echo $filetype | $grep source`" && \
  {
    compiler="`echo \"echo \\${compiler_${system}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
    if $test "$compiler"; then
	echo "$self: $system compiler found.  Creating storyfile with standard settings...";
	$test -n "`echo $doesntlikesuffix | $grep $compiler`" || \
	    fullpath="`echo $fullpath | cut -f1 -d.`";
#	echo $compiler $fullpath;
	$compiler $fullpath;
	filetype="`echo \"echo \\${ft_${system}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
	$test "$system" = "zcode" && defaultsuffix="z8" || \
	  {
	    defaultsuffix="`echo \"echo \\${suffix_${system}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
	    defaultsuffix=`echo $defaultsuffix | cut -f1 -d' '`;
	  }
	$test -n "`echo $doesntlikesuffix | $grep $compiler`" && \
	    fullpath="`echo $fullpath | cut -f1 -d.`.$defaultsuffix";
	gamename="`echo $gamename | cut -f1 -d.`.$defaultsuffix";
      else 
	  echo "$self: error: cannot find $system compiler, aborting";
	  exit 1;
      fi
  }


userpref="`echo \"echo \\${${system}_int}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
$test "$preferred" || \
  {
    $test "$userpref" && \
      {
	preferred=$userpref;
	PREFINT=TRUE;
      }    
  }
# we use special fallbacks of $self:
#  - we  are  running  all   original  Infocom  games  in  a  modified
#    xfrotz-2.32.1/frotz-2.43 combo  that has X11  display, frotz-2.43
#    features and can display GST (Planetfall, Stationfall) as well as
#    alternate prompts (eg. Suspended) correctly.
#  - if  !DISPLAY or NOXAPP,  we use  a modified  frotz with  the same
#    functionality.
#  - test if the game is VM6 and the .mg1 file exists; if true, always
#    prefer this  to (possibly garbled) blorb variants  and use xfrotz
#    to play (original Infocom only).
#  - try to make buggy  storyfiles (eg.  Varicella) playable with full
#    features by using frotz and settings that work (see $buggylist).
#  - everything can be overridden by shell switches.
# Turn this if..fi affair into comments if you dislike this.
if $test "$gameauthor" = "Infocom"; then
	condition="is an original Infocom game";
	if ($test "$storyfile_vm" = 6 -a ! "$FORCEDINT" -a ! "$FORCENATIVE"); then
	    SPECIALFILE=TRUE;
	    INFOCOM_V6=TRUE;
	    condition="$condition (VM6 with";
	    gfxfile="`echo $fullpath | cut -f1 -d.`";
	    $test -f "${gfxfile}.blb" -o -f "${gfxfile}.blorb" && \
		condition="$condition blorbed";
	    if $test "$gameauthor" = "Infocom"; then
		$test -f "${gfxfile}.mg1" && \
		    {
		    $test "``echo $condition | grep blorb" && \
			condition="$condition as well as";
		    condition="$condition MS-DOS .mg1";
		}
	    fi
	    $test "`echo $condition | grep blorb`" -o "`echo $condition | grep mg1`" || \
		condition="$condition no";
	    condition="$condition graphics file available)";
	    terplist="$fallbackdir/tadfrotz $fallbackdir/tafrotz";
	    if $test "`echo $condition | grep mg1`"; then
		$test "$DISPLAY" -a ! "$NOXAPP" && \
		    terplist="$terplist xfrotz $fallbackdir/frotz-x11 $fallbackdir/taxfrotz";
	    else
		$test "$DISPLAY" -a ! "$NOXAPP" && \
		    terplist="$terplist zoom";
	    fi
	fi
fi
if $test "$storyfile_vm" -lt 6 -a "$gameauthor" = "Infocom" -a ! "$FORCEDINT"; then
    condition="${condition} that might like the special features of original Infocom interpreters";
    terplist="pinfo pinfocom $fallbackdir/tadfrotz $fallbackdir/tafrotz";
    $test "$DISPLAY" -a ! "$NOXAPP" && \
	terplist="$terplist $fallbackdir/taxfrotz";
    SPECIALFILE=TRUE;
fi
for terp in $terplist; do
    $test -x "`$which $terp`" && \
      {
	preferred="$terp";
	PREFINT=TRUE;
      }
done
if $test "$gameauthor" = "Infocom"; then
    $test -n "$preferred" && \
	condition="${condition}; setting interpreter to '$preferred'" \
	|| \
	condition="${condition}, but you do not have a suiting interpreter.";
    $test ! "$SILENTIUM" && echo "'$gamename' $condition";    
fi
$test -n "$preferred" || \
    {
       PREFINT="";
       SPECIALFILE="";
    }
# end of Infocom special fallbacks


# test for buggy storyfiles only when not in dumb/streaming mode
$test "$STREAMING" || \
  for game in $buggylist; do
    $test "$gamename" = "$game" && \
      {
	BUGGYFILE=TRUE;
	echo -n "$self: WARNING: '$gamename' is a buggy storyfile, ";
	$test "$FORCEDINT" && \
	    echo -e "better let me choose the interpreter. " || \
	    {
	    for terp in frotz $fallbackdir/tafrotz; do
		$test -x "`which $terp`" && \
		  {
		    preferred="$terp";
		    PREFINT=TRUE;
		    echo -n "using 'frotz' with suitable parameters.  ";
		    echo "some errors might still occur!";
		  } 
	    done
	    $test "echo $preferred | $wgrep frotz" || \
		echo "and you do not have 'frotz' installed.  display will be garbled!";
	  }
    }
done

# make sure  the right interpreter  or a suitable substitute  is used.
# first, we handle certain system's native interpreters.
if ($test ! "$NONATIVE") && (($test "$FORCENATIVE") || ($test -z "$preferred" -a -n "$OS_IS")); then
   PREFINT="TRUE";
   # use  .native  application if  available;  if  it  isn't, skip  to
   # standard unix X11 and console interpreters
    native_interpreter="`echo \"echo \\${${osident}_${system}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
    if $test -x "$native_interpreter"; then
       interpreter="$native_interpreter";
       parameter="";
       $test ! "$NOXAPP" && {
	   preferred="$interpreter";
	   NONUNIX="TRUE";
         }
    fi
fi
# either no native one was found, NONATIVE is set, or this is a unix system
# skip this when FORCEDINT, SPECIALFILE or STREAMING
if ($test -z "${preferred}" -o -z "`$which ${preferred}`" -o "$NOXAPP") && \
    ($test ! "$FORCEDINT") && ($test ! "$STREAMING") && \
    ($test ! "$SPECIALFILE"); then
    PREFINT="FALSE";
    substlist="`echo \"echo \\${${system}_subst}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
    for file in $substlist; do
	if $test "`$which $file`" -o -e "${fallbackdir}/$file"; then
 	    if ($test ! "$DISPLAY" -a "`echo $file | cut -c1`" = "x") || \
 	       ($test ! "$DISPLAY" -a -n "`echo $isxinterpreter | $wgrep $file`") || \
               ($test "$DISPLAY" -a "$NOXAPP" -a "`echo $file | cut -c1`" = "x") || \
               ($test "$DISPLAY" -a "$NOXAPP" -a -n "`echo $isxinterpreter | $wgrep $file`"); \
	      then
		continue;
	    else
		interpreter="$file";
		$test -e "${fallbackdir}/$file" && \
		    interpreter="${fallbackdir}/$file";
	    fi
#	else
#	    $test -e "${fallbackdir}/$file" && \
#		interpreter="${fallbackdir}/$file";
	fi
    done
else
    PREFINT="TRUE";
    interpreter=$preferred;
fi
# dumb mode requested?
if ($test "$STREAMING" -a ! "$FORCEDINT"); then
    substlist="`echo \"echo \\${${system}_dumb}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";    
    insert="dumb ";
    for file in $substlist; do
	$test `$which $file` && \
	    interpreter="$file";
    done
fi
# now, use  the right parameters  for either normal, classic,  or dumb
# mode
if $test "$interpreter"; then
    interpr_basename="`basename $interpreter`";
    parameter="`echo \"echo \\${${system}_param}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
    defaultparam="`echo \"echo \\${param_${interpr_basename}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
#   $test "$FORCEDINT" -o "$SPECIALFILE" -o -z "$userpref" && \
    if $test "$INFOCOM_V6"; then
	parameter=$defaultparam;
    else
	classicparam="`echo \"echo \\${classic_${interpr_basename}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
	inverseparam="`echo \"echo \\${inv_${interpr_basename}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
	dumbparam="`echo \"echo \\${dumb_${interpr_basename}}\" >$tempfile; source $tempfile; rm $tempfile >&/dev/null`";
	if ($test -z "$parameter" -o "$FORCEDINT") && ($test "$CLASSIC" -o "$MONO"); then
	    parameter="$classicparam";
	fi
	if ($test -z "$parameter" -o "$FORCEDINT"); then
	    parameter="$defaultparam";
	fi
	if ($test "$INVERSE" -a -n "$inverseparam") || ($test "$BUGGYFILE" -a -n "$inverseparam"); then
	    parameter="$inverseparam";
	fi
	if ($test "$STREAMING"); then
	    $test -n "$dumbparam" && \
		parameter="$dumbparam" || \
		parameter="$defaultparam";
	fi
    fi
    runstring="$interpreter $parameter";
else 
    # abort if no interpreter was found
    echo "$self: error: no ${insert}$filetype interpreter found anywhere, aborting";
    exit 1;
fi
# give some feedback on what has been determined above
if $test ! "$SILENTIUM"; then
    $test "${OS_IS}" -a ! "$FORCEDINT" -a ! "$PREFINT" && \
	echo "running on $OS_IS, preferring native application if available";
    echo -n "note: user's preferred interpreter for ";
    $test "`echo $system | grep blorb`" -a ! "`echo $filetype | grep blorb`"&& \
	echo -n "blorbed ";
    echo -n "$filetype ";
    if $test "$userpref"; then
	echo "is defined as '$userpref'";
    else
	echo "is not defined, defaulting to substitution list for a suitable interpreter";
    fi
    test "$msg_mode" && echo "$self: mode changes: $msg_mode";
fi
# if storyfile is liable to use graphics, let the user know
$test "$NOXAPP" && \
  {
    if ($test "$system" = "zcode" -a "$storyfile_vm" = "6") || \
       ($test "$system" = "glulx") || ($test "$system" = "acode") || \
       ($test "$system" = "msrl") || \
       ($test "`echo $system | $grep blorb`" -a ! "$FORCEDINT"); then
	echo "$self: hint: the game might have inlined graphics, try a graphical interpreter";
    fi
  }
# show the user what will be run
$test -z "$SILENTIUM" && \
    echo "$msg_starting, using '$runstring'";

# a --- necessary --- hack for advint and similar stubborn terps:
for terp in $doesntlikesuffix; do
    $test "$interpreter" = "$terp" && \
	fullpath=`echo $fullpath | cut -f1 -d.`;
done

# a bit of title welding:
# compose  a  window  title  for   xterm  and  other  Xtk  hint  aware
# applications that contains the game name, or the storyfile basename,
# if the game name is unknown.
if $test "$is_known"; then
    # former commercial games
#    case "$gameauthor" in
#	Infocom|Activision|\
#        "Magnetic Scrolls"|\
#        Level9|"Level 9"|\
#        "Scott Adams"|\
#        "Brian Howarth")
#	    SHORTTITLE=TRUE;
#	    ;;
#    esac
    # -ts switch
    $test "$SHORTTITLE" && windowname="$gametitle" || \
      {
	windowname="\"$gametitle\" by $gameauthor";
      }
fi
# if not listed in db and neither iFiction or blorb chunk info, or -to
# switch given, have a default title, eg.: "A Text Adventure (foo.z5)"
$test -z "$windowname" -o "$windowname" = " " -o "$FILENAMEONLY" && \
    {
      NONAME=TRUE;
      windowname="A Text Adventure";
    }
# this is a bit complex: set  the title according to the switches -ti,
# -te, and -tv (or -tf instead), and the title style set above
if $test "$TITLEINT" -o "$TITLESYS" -o "$TITLEVER" -o "$NONAME"; then
    windowname="$windowname  (";
    $test "$NONAME" && windowname="${windowname}$gamename";
    $test "$TITLEVER" && \
      {
        case $system in
	    zcode|glulx|zcodeblorb|glulxblorb)
		$test -n "$gamerelease" -a -n "$gameserial" && \
		    windowname="${windowname}  $gamerelease/$gameserial";
		;;
	esac
      }
    $test "$TITLEINT" -o "$TITLESYS" && \
	windowname="$windowname, ";
    $test "$TITLESYS" && windowname="${windowname}$filetype";
    $test "$TITLESYS" -a -n "$storyfile_vm" && \
      {
	$test "$filetype" = "$ft_zcode" -o "$filetype" = "$ft_glulx" && \
	    windowname="${windowname} VM $storyfile_vm";
}
    $test "$TITLEINT" && \
	{
	   $test "$TITLESYS" && \
	    windowname="${windowname}, ";
	}
    $test "$TITLEINT" && windowname="${windowname}using $interpr_basename";
    windowname="${windowname})";
fi


# okay.  Now, let's see where and  how to start.  see if we are called
# from within  an X environment  or in the  same account where  an X11
# session  is  currently running.   If  the  interpreter  is a  native
# application (NONUNIX)  or its name starts  with "x" or it  is in the
# "isxinterpreter" list,  just launch it,  else use an xterm,  or heed
# NOXAPP  and/or CLASSIC  if set  (since -l  is toggled  by un-setting
# DISPLAY, this is a simple check).
$test "$SIMULATE" && echo "would be running the following:";
if ($test "$DISPLAY" -a	! "`echo ${interpr_basename} | $cut -c1`" = "x" -a ! "$NONUNIX") && \
    ($test "$DISPLAY" -a "`echo ${isxinterpreter} | $wgrep ${interpr_basename}`" = ""  -a ! "$NONUNIX") || \
    ($test "$NONUNIX" -a "$NOXAPP"); then
    # if no xterm parameters are set, let's default to xterm-color and
    # a  nice  terminal  size,  both  of which  are  well  suited  for
    # adventuring
    $test -z "$termwin_param" && termwin_param="$term_std";
    $test "$INVERSE" && termwin_param="$term_inverse";
    # if CLASSIC is true, use traditional xterm size
    $test "$CLASSIC" && termwin_param="$term_classic";
    # level9 and scottfree are b/w  only, and since text is sparse, we
    # assume "luxurious size" to be 80x25 which is already too big
    if ($test "$system" = "saai" -o "$system" = "acode"); then
	termwin_param="$term_small";
	$test "$INVERSE" -o "$CLASSIC" && termwin_param=$term_classic;
    fi
    # if scottfree  is run in TRS80 simulation,  adjust xterm geometry
    # to TRS80 64x25 screen
    if ($test "$system" = "saai") && \
       ($test "$CLASSIC" -o "`echo ${saai_param} | $cut -c1-2`" = "-t"); then
	   termwin_param="$term_trs80";
    fi
    # a nice classic look --- level9 in most 8bit systems' screen mode
    # (40x25)
    # note: this was fun with level9 interpreter v2.0; v3 is different
    # instead we use 80x25 in amber on black
    $test "$system" = "acode" -a "$CLASSIC" && \
        termwin_param="$term_amber";
    #
    # here. we compose the full terminal string
    termwin_param="$termwin_param $term_title";
    #
    if $test "$SIMULATE"; then
	echo -e "\t $terminal $termwin_param \"$windowname\" $term_exec $runstring $fullpath &";
	exit 0;
    else
	# now run the terminal process (stare at the screen in awe ;-)
       $terminal $termwin_param "$windowname" $term_exec $runstring $fullpath &
    fi
elif ($test ! "$NOXAPP") && ($test "$ISMACOS" -o "$DISPLAY"); then
    # not an xterm,  but another x11 or native  binary that should run
    # in a detached process
    if ($test "`echo $hasxtkhints | $wgrep ${interpr_basename}`") && \
	($test ! "`echo $hasnohints | $wgrep ${interpr_basename}`"); then
	if $test "$SIMULATE"; then
	    echo -e "\t ${runstring} -title "$windowname" $fullpath &";
	    exit 0;
	fi
	${runstring} -title "$windowname" $fullpath &>$logfile &
    else
	($xrdbremove - "Glk*Geometry: 642x506" &>/dev/null);
	wait;
	if $test "$SIMULATE"; then
	    echo -e "\t ${runstring} $fullpath &";
	    exit 0;
	fi
	${runstring} $fullpath &>$logfile &
    fi
else
    # we are on a vt/vc/tty/pty and want to display right here
    if $test "$SIMULATE"; then
	echo -e "\t ${runstring} $fullpath";
	exit 0;
    fi
    # if  this is  an  xterm, set  the  title and  window size  before
    # playing
    $test "$TERM" = "xterm" -o "$TERM" = "xterm-color" && \
      {
	echo -ne "\033[8;35;80t";
	echo -ne "\033]0;$windowname\007";
      }

    ${runstring} ${fullpath};

    # reset the title to xterm and the size to 80x25
    $test "$TERM" = "xterm" -o "$TERM" = "xterm-color" && \
      {
	echo -ne "\033[8;25;80t";
	echo -ne "\033]0;xterm\007";
      }
fi

#$xrdbremove $xrdbfile;
$xrdbremove - "Glk*Geometry: 642x506" &>/dev/null;

exit 0;
