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