[comp.os.minix] animals

tholm@uvicctr.UUCP (Terrence W. Holm) (09/14/88)

EFTH MINIX report #45  - September 1988 -  animals(1)


Ok, some people have told me that utilities are fine,
but MINIX needs REAL programs......thus.....

There follows an implementation of animals(1) for MINIX.
Please consider this public domain software. A "man" page
is included.

An example data base /usr/tmp/animals is also included.
Once you understand how to construct a better animal data
base, you can scrap this one.

Note: This program uses a couple of items posted in previous
EFTH reports.

----------------------------------------------------------
echo x - animals.1
gres '^X' '' > animals.1 << '/'
XCOMMANDS
X    animals(1)		- teach the computer about animals
X
XINVOCATION
X    animals  [ data_base ]
X
XEXPLANATION
X    Animals(1) is a classic computer game. The user thinks
X    of an animal and then answers yes or no (y/n) to the
X    questions posed by the computer until either the
X    computer guesses the animal, or it gives up. When
X    the computer does not know an animal it asks for its
X    name and a question that would distinguish the new
X    animal from another already known by the computer.
X
X    When the user answers "n" to the question "Are you
X    thinking of an animal?", the animal data base is
X    updated with information learned during the session.
X    The game may be aborted by hitting the sigint (DEL)
X    or the sigquit (^\) key.
X
XNOTES
X    There should be enough space in a 64K data area for
X    500 animals.
X
X    Data base files are created with permission "rw-rw-rw-"
X    so that everyone can use them.
X
X    If two people are using the same data base at one time
X    then whoever exits last will overwrite the information
X    added by the first user.
X
XFILES
X    /usr/tmp/animals		default animal data base
/
echo x - animals.c
gres '^X' '' > animals.c << '/'
X/*  animals(1)
X *
X *  Authors: Terrence W. Holm & Edwin L. Froese          Sept. 1988
X *
X *  The animals game originated many years ago - this
X *  program was written from our memories of the past.
X */
X
X#include <stdio.h>
X#include <string.h>
X#include <signal.h>
X#include <sgtty.h>
X#include <ctype.h>
X#include <unistd.h>
X
X#define  ANIMALS	"/usr/tmp/animals"
X#define  DEFAULT_ANIMAL	"beaver"
X#define  MAX_NODES	999	/*  Enough for 500 animals  */
X#define  MAX_LINE	90
X
Xint   Abort();
Xchar *Get_Animal();
Xchar *Get_Question();
Xchar *A_or_An();
Xchar *Alloc();
X
Xstruct node
X  {
X  int   question;
X  char *text;
X  int   yes;
X  int   no;
X  } animals[ MAX_NODES ];
X
Xint count = 0;
Xstruct sgttyb old_tty_mode;
X
X
Xmain( argc, argv )
X  int   argc;
X  char *argv[];
X
X  {
X  char *animal_file = ANIMALS;
X
X  if ( argc > 2 )
X    {
X    fprintf( stderr, "Usage:  %s  [ data_base ]\n", argv[0] );
X    exit( 1 );
X    }
X
X  if ( argc == 2 )
X    animal_file = argv[1];
X
X  ioctl( 0, TIOCGETP, &old_tty_mode );
X
X  signal( SIGINT,  Abort );
X  signal( SIGQUIT, Abort );
X
X  if ( access( animal_file, R_OK ) == 0 )
X    Read_Animals( animal_file );
X  else
X    {
X    animals[0].question = 0;
X    animals[0].text = DEFAULT_ANIMAL;
X    count = 1;
X    }
X
X  while ( Ask( "\nAre you thinking of an animal?" ) )
X    {
X    int i = 0;
X
X    while ( 1 )
X      {
X      if ( animals[i].question )
X	{
X	if ( Ask( animals[i].text ) )
X	  i = animals[i].yes;
X	else
X	  i = animals[i].no;
X	}
X      else
X	{
X	printf( "Were you thinking of %s %s",
X		   A_or_An( animals[i].text ), animals[i].text );
X
X	if ( Ask( "?" ) )
X	  printf( "I knew it!\n" );
X
X	else
X	  {
X	  /*  Insert a new question and animal name  */
X
X	  if ( count + 2 > MAX_NODES )
X	    Error( "Too many animal names" );
X
X	  animals[count].question = 0;
X	  animals[count].text = animals[i].text;
X	  ++count;
X
X	  animals[count].question = 0;
X	  printf( "What animal were you thinking of? " );
X	  animals[count].text = Get_Animal();
X	  ++count;
X
X	  animals[i].question = 1;
X	  printf( "What question would distinguish %s %s from\n%s %s? ",
X		A_or_An( animals[count-2].text ), animals[count-2].text,
X		A_or_An( animals[count-1].text ), animals[count-1].text );
X
X	  animals[i].text = Get_Question();
X
X	  printf( "For %s %s, the answer would be",
X		A_or_An( animals[count-1].text ), animals[count-1].text );
X
X	  if ( Ask( "?" ) )
X	    {
X	    animals[i].yes = count - 1;
X	    animals[i].no  = count - 2;
X	    }
X	  else
X	    {
X	    animals[i].yes = count - 2;
X	    animals[i].no  = count - 1;
X	    }
X	  }
X
X	break;
X	}
X      }  /*  End while ( 1 )  */
X
X    }
X
X
X  ioctl( 0, TIOCSETP, &old_tty_mode  );
X
X  printf( "\nThank you for playing \"animals\".\n" );
X  printf( "The animal data base is now being updated.\n" );
X
X  Write_Animals( animal_file );
X
X  sleep( 1 );
X  printf( "\nBye.\n" );
X
X  exit( 0 );
X  }
X
X
X/*
X *  Reading and writing the animal data base
X */
X
X
XRead_Animals( animal_file )
X  char *animal_file;
X
X  {
X  FILE *f;
X  char buffer[ MAX_LINE ];
X
X  if ( (f = fopen( animal_file, "r" )) == NULL )
X    Error( "Can not open animal data base" );
X
X  while ( fgets( buffer, MAX_LINE, f ) != NULL )
X    {
X    int   string_length;
X    char *string;
X
X    buffer[ strlen(buffer) - 1 ] = '\0';
X
X    swab( buffer, buffer, strlen(buffer) );
X
X    if ( buffer[ 0 ] == 'q' )
X      {
X      char *end = strchr( buffer, '?' );
X      string_length = end - buffer;
X      animals[ count ].question = 1;
X      sscanf( end + 1, "%d:%d", &animals[ count ].yes, &animals[ count ].no );
X      }
X    else
X      {
X      animals[ count ].question = 0;
X      string_length = strlen( buffer ) - 1;
X      }
X
X    string = Alloc( string_length + 1 );
X
X    string[ 0 ] = '\0';
X    strncat( string, buffer+1, string_length );
X
X    animals[ count ].text = string;
X
X    count++;
X    }
X
X  fclose( f );
X  }
X
X
XWrite_Animals( animal_file )
X  char *animal_file;
X
X  {
X  FILE *f;
X  int i;
X  char buffer[ MAX_LINE ];
X
X  if ( (f = fopen( animal_file, "w" )) == NULL )
X     Error( "Can not write animal data base" );
X
X  for ( i = 0;  i < count;  ++i )
X    {
X    if ( animals[i].question )
X      sprintf( buffer, "q%s%d:%d", animals[i].text,
X	        animals[i].yes, animals[i].no );
X    else
X      sprintf( buffer, "a%s", animals[i].text );
X
X    /*  Make the data base a bit difficult to read  */
X
X    swab( buffer, buffer, strlen(buffer) );
X
X    fprintf( f, "%s\n", buffer );
X    }
X
X  fclose( f );
X
X  chmod( animal_file, 0666 );
X  }
X
X
X/*
X *  Reading data from the user
X */
X
X
Xint Ask( question )
X  char *question;
X
X  {
X  struct sgttyb new_tty_mode;
X  int response;
X
X  new_tty_mode = old_tty_mode;
X  new_tty_mode.sg_flags |= CBREAK;
X  ioctl( 0, TIOCSETP, &new_tty_mode  );
X
X  printf( "%s ", question );
X
X  while ( (response = getchar()) != 'y'  &&  response != 'n' )
X    printf( "\n%s [yn]?", question );
X
X  putchar( '\n' );
X
X  ioctl( 0, TIOCSETP, &old_tty_mode  );
X
X  if ( response == 'y' )
X    return( 1 );
X  else
X    return( 0 );
X  }
X
X
Xchar *Get_Animal()
X  {
X  char  s[ MAX_LINE ];
X  char *text;
X  int   text_length;
X
X  fgets( s, MAX_LINE, stdin );
X
X  text_length = strlen(s);
X
X  text = Alloc( text_length );
X
X  text[ 0 ] = '\0';
X  strncat( text, s, text_length - 1 );
X
X  return( text );
X  }
X
X
Xchar *Get_Question()
X  {
X  char s[ MAX_LINE ];
X  char *end;
X  char *text;
X
X  fgets( s, MAX_LINE, stdin );
X
X  /*  Capitalize the first letter  */
X
X  if ( islower( s[0] ) )
X    s[0] = toupper( s[0] );
X
X  /*  Make sure the question ends with a '?'  */
X
X  if ( (end = strchr( s, '?' )) == NULL )
X    s[ strlen(s) - 1 ] = '?';
X  else
X    end[1] = '\0';
X
X  text = Alloc( strlen(s) + 1 );
X
X  strcpy( text, s );
X
X  return( text );
X  }
X
X
X/*
X *  Utility routines
X */
X
X
Xchar *A_or_An( word )
X  char *word;
X
X  {
X  if ( strchr( "aeiouAEIOU", word[0] ) == NULL )
X    return( "a" );
X  else
X    return( "an" );
X  }
X
X
Xchar *Alloc( size )
X  int size;
X
X  {
X  char *malloc();
X  char *memory;
X
X  if ( (memory = malloc( size )) == NULL )
X    Error( "No room in memory for all the animals" );
X
X  return( memory );
X  }
X
X
XAbort()
X  {
X  ioctl( 0, TIOCSETP, &old_tty_mode  );
X
X  printf( "\nThank you for playing \"animals\".\n" );
X  printf( "Since you aborted, the animal data base will not be updated.\n" );
X
X  sleep( 1 );
X  printf( "\nBye.\n" );
X
X  exit( 1 );
X  }
X
X
XError( message )
X  char *message;
X
X  {
X  ioctl( 0, TIOCSETP, &old_tty_mode  );
X
X  fprintf( stderr, "Error: %s\n", message );
X
X  exit( 1 );
X  }
/
echo x - animals
gres '^X' '' > animals << '/'
XIq stig erne2?1:
XDqeo stib ra?k:43
XDqeo stih po2?:342
XDqeo stiw iehgm ro ehtna1 00p uodn s4( 5ikolrgma)s8?7:
XDqeo stie taf si?h:65
XIq stia c moom noctnseattni  nod garec?s043:9
XDqeo stih va eutks?s811:7
XIq stiC nada'a sanitnolaa inam?l311:4
XDqeo stih va e aerlayll no gones9?1:0
Xeaelhpnat
XDqeo stih va e aerlayll no genkc1?:121
XDqeo stil vi eniS uohtA emirac9?:879
XDqeo stih va etsirep?s021:9
Xbaaeevr
XDqeo stis uqae?k611:5
XWqre eht ealtso en socsnmudeb  yohsga dnm noeksy3?:653
XDqeo stif yl6?:876
Xsaael
Xwalaurs
XDqeo stih va eno eo( rwt)oh muspo  nti sabkc2?:212
Xzabear
XIq stie txnitc2?:872
Xcamale
Xfaorg
XDqeo stil ki epalpse2?:652
XDqeo stis iw?m433:3
XDqeo stih va eolsto  fette?h065:9
XIq stia m rausipla4?:654
XIq stia c rainover2?:903
Xtarynaonasrusur xe
XDqeo stih va eobynp alet slano gti sabkc3?:213
Xaaapotasrusu
Xsaetogasrusu
XDqeo stih va eelsg8?:218
XDqeo stih va e ahsle?l444:3
XDqeo stim vo eEVYRs ollw?y844:7
XDqdit eh yilevo  nht esialdno  faMrutiui snit ehI dnai ncOae?n833:7
Xwaihetd doo
Xgaer yodod
XDqeo stie tas amllc ihdler?n244:1
Xgaerhyuodn
Xtayop oolde
Xpatib lu letrreir
Xdacuk
Xtarulte
XAqert eh yofnu dnof rasmi  noNtr hmAreci?a054:9
Xkanaagoro
XDqeo stif yl6?:436
XDqeo stih va e arbia?n788:8
XDqeo stil vi enit ehs ae5?:655
XDq oocbwyo siredo  nhtme5?:215
XDqeo stis ya" iokno ni"k5?:435
Xharoes
XDqeo stih va eofrul ge?s989:0
Xpagi
XDqeo stih va enaltre snoi sth ae?d277:1
XIq stia m maam?l755:8
Xkaliel rhwlae
XDqeo stim ka eogdos saihim1?011:90
Xgaernew rom
XDqeo stih va e aornued dnsuo?t266:1
Xcaorocidel
Xaallgitaro
XDq ohtyel vi enik tihcnec puobrasd7?:096
XDqeo stis cu klboo?d666:5
XDqeo stil ki erfiu?t477:3
Xmasouqtio
Xmauoes
Xvamaiperb ta
XDqeo sti" emwo?"877:7
XDqeo stic notsurtcw be?s677:5
XDqeo stih va e aamen9?:349
Xmaooes
Xwaihetm toh
XDqeo stih va eeftaehsr8?:438
Xcacorkaohc
Xsaipedr
XDqeo stil vi eiwhtnim ?e087:9
Xdamoseit cact
XIq stiv nemouo?s688:5
Xsafowtra eubg
Xgaernes anek
Xiaugnaa
Xfaurtif yl
Xpaatmrgima
XDqeo stih va e aatli9?:129
Xaaddre
Xsaolht
Xaaombea
Xcawo
Xaaudtlh muna
XCquodli  tne dpuo  nht eatlb etaT ahkngsvini?g699:5
XIq stin tavi eotE raht1?701:80
Xlaoin
XIq stin tavi eotN rohtA emirac1?009:9
Xaaravdrak
XDqeo stih va e ahsle?l01:2011
XDqeo stil vi eniS ocltna?d01:4013
Xlaalam
Xgarolial
XAqert ehera yni  nactpviti?y01:5016
Xtarueky
Xlabotsre
Xgarifaef
XLaco heNssM notsre
Xbaalkcb aer
Xsasauqtahc
Xcaihpmnaeze
XEaT..
Xgaertaw ihets ahkr
Xtanua
/
----------------------------------------------------------

		Edwin L. Froese
		  uw-beaver!ubc-cs!mprg!handel!froese

		Terrence W. Holm
		  uw-beaver!uvicctr!tholm