head 1.18; access; symbols; locks ahuxley:1.18; strict; comment @ * @; 1.18 date 2001.02.25.16.48.46; author alexis; state Exp; branches; next 1.17; 1.17 date 2000.01.09.10.20.02; author ahuxley; state Exp; branches; next 1.16; 1.16 date 99.01.07.11.37.44; author alexis; state Exp; branches; next 1.15; 1.15 date 98.10.07.21.56.02; author alexis; state Exp; branches; next 1.14; 1.14 date 98.10.07.14.55.09; author alexis; state Exp; branches; next 1.13; 1.13 date 98.10.07.10.46.36; author alexis; state Exp; branches; next 1.12; 1.12 date 97.11.11.14.08.34; author alexis; state Exp; branches; next 1.11; 1.11 date 97.11.10.18.43.45; author alexis; state Exp; branches; next 1.10; 1.10 date 97.10.06.22.46.52; author alexis; state Exp; branches; next 1.9; 1.9 date 97.10.06.16.20.16; author alexis; state Exp; branches; next 1.8; 1.8 date 97.10.06.14.46.41; author alexis; state Exp; branches; next 1.7; 1.7 date 97.10.06.14.22.51; author alexis; state Exp; branches; next 1.6; 1.6 date 97.10.05.19.49.40; author alexis; state Exp; branches; next 1.5; 1.5 date 97.10.05.16.12.14; author alexis; state Exp; branches; next 1.4; 1.4 date 97.10.05.15.01.09; author alexis; state Exp; branches; next 1.3; 1.3 date 97.10.04.10.11.02; author alexis; state Exp; branches; next 1.2; 1.2 date 97.10.02.10.59.28; author alexis; state Exp; branches; next 1.1; 1.1 date 96.10.20.12.00.35; author alexis; state Exp; branches; next ; desc @The animal guessing game @ 1.18 log @converted to 'active' format @ text @/* * ANIMAL GUESSING GAME * * This program prompt the user to think of an animal and then tries to * guess what it is by asking a series of questions. Really it's just an * exercise in structures, pointers and tree balancing, and in packaging * and release structuring. * * These is a reasonable diagrammatic explanation of what it does below. */ /* * Very urgent things first. */ #define MAIN /* headers to define RCS symbols for inclusion in *this* object only */ /* this file's own RCS symbols */ static char *animal_c_rcs_id = "$Header: /home/alexis/dev/active/animal/bin/RCS/animal.c,v 1.17 2000/01/09 10:20:02 ahuxley Exp alexis $"; /* * System-wide header files to include - with explanations why. */ #include /* for NULL, stderr, printf(), ... */ #include /* for calloc() */ #include /* strdup(), strlen(), ... */ #include /* exit() */ #include /* for errno */ #include /* for signal() and syms */ /* * Program-wide header files to include - with explanations why. */ #include "../lib/utils.h" /* for mybasename(), error(), ... */ #include "patchlevel.h" /* for version info */ /* * Some urgent symbols - these are forward declarations and structure defs. */ #define SUPPORT_REPHRASING FALSE /* support rephrasing? see note below */ #define SUPPORT_SLOVAK FALSE /* support slovak messages? */ /* * This program uses a simple structure to contain information about * questions to ask or animals to guess, as well as information as to * what question to ask next or what animal to guess next depending on * the answer to questions. The data structure can look this for example: * * Start Here * Has it got 4 legs? * /\ * (yes) / \ (no) * / \ * / \ * It's a snake!? Does it have long ears? * /\ * (yes) / \ (no) * / \ * / \ * It's a rabbit!? It's a cow!? * * * As you can see, the data structure 'hangs' by the first question, and * it can rapidly become quite unbalanced (e.g. if the user things of a * snake then one question is enough to ascertain it's a snake, but if the * user were to think of a horse (how would the data structure be changed to * incorporate a horse?) then the number of questions would be at least * three. * * Now, rephrasing involves jiggling the questions about in order to * turn this * * /\ * * /\ * * /\ * * * * * into this * _ * / \ * /\ /\ * * * * * * * This 'rebalancing' is quite tricky, primarily because the questions * themselves don't only get rearranged, but must also be changed! and the * way they get changed depends precisely how the tree is inbalanced (there * are four different sorts of inbalance including the one drawn above). * * Rebalancing also requires that we keep a record of how out of balance * all sections of the tree are. This information is kept in the tree itself. * Outofbalancedness is defined as the height of the tree hanging from the * left branch minus the height of the tree hanging from the right branch. * If the addition of new animals and questions causes an outofbalancedness * to reach 2, then rebalancing is possible. * * However, the rephrasing results in questions that even the likes of * Mr Spock might find confusing, so at the flick of a switch (namely * the 'SUPPORT_REPHRASING' switch) support for rephrasing is removed. */ /* * This program can also support the Slovak language. This requires * words such as 'who' or 'what' to be used, but these words depend on * the article type in the data structures (people require 'who', animals * require 'what', places require 'where' etc). So the language of the * data defines the language of the questions. (It'd be a bit daft if the * program asked "Think of a zviera. Is it a konik?") So any datafiles that * get initially loaded into the datastructures must tell the program not * only what language to ask 'Think of a' in, but must also tell the * program how to say 'animal' and 'who' or 'place' and where' in the * language of choice. * * But, again, to simplify the program no end, (or at least simplify * it for the casual reader,) support for foreign languages can be * removed at the flick of the 'SUPPORT_SLOVAK' switch. * * Note that comments are only in the non-SUPPORT_SLOVAK code. */ struct node { /* information cell */ char *txt; /* for question text or animal name */ struct node *lch; /* where to go if answer is yes */ struct node *rch; /* where to go if answer is no */ #if SUPPORT_REPHRASING int hgt; /* outofbalanceness for current node */ #endif }; #define AN_RC_QUIT 1 /* return code used to mean quit */ #define AN_RC_RESTART 2 /* to mean take it from the top */ #if SUPPORT_REPHRASING #define AN_RC_RECALC 3 /* to mean the structure has been added to, and outofbalancedness *could* now require rebalancing, but it might not, so recalculate to see */ #define AN_LGC_OR 1 /* used in rephrasing questions */ #define AN_LGC_AND 2 /* used in rephrasing questions */ #endif #define AN_CH_LFT 1 /* to tell rephraser where problem is */ #define AN_CH_RGT 2 /* to tell rephraser where problem is */ /* * Forward declarations for functions used only in this file. */ #if SUPPORT_REPHRASING /* see loadfile() below for why return type changes if rephrasing allowed */ static int loadfile(char *, struct node **); #else static void loadfile(char *, struct node **); #endif static int savefile(char *, struct node *); static void usage(void); static int process(struct node **); static int gen_lockfile_name(char *, char *); /* write filename into buffer */ /* * Data only used by functions in this file. */ static char *definer = NULL; /* 'what', 'who' in right lang */ static char *class = NULL; /* 'animal', 'person' in right lang */ #if SUPPORT_SLOVAK static int language; /* dialling code of lang's country */ #endif /* * Data belonging to this file, but referenced by others. */ char *progname; /* name of this program */ /* * Functions start here ... */ /****************************************************************************** * * Function: main * * Parameters: command line parameter count * array of command line words * * Returns: doesn't; it uses exit() instead * * Description: * * initialises a few variables used elsewhere, processes * command line options and required command line parameter * - which should be a file name - by loading the specified * file into the tree-like datastructure, then enters * main loop in which it asks the user to think of an * animal - or whatever - and then processes their response * until they respond with 'q'. * * The way to follow what the program is doing is to * draw the data structure with a pen and paper and then * put your finger on the top node and move down asking * questions until you get to a leaf-node when you state * the guess therein. To determine the initial shape of the * data structure then just play the game always saying * "yes that's what it was" when it guesses. * ******************************************************************************/ main( int argc, char *argv[]) { struct node *rootptr; /* root if the data structure */ int rc; /* to temporily hold return codes */ int lockingpid; /* pid of current animal file locker */ /* get name of this prog */ progname = mybasename(argv[0], NULL); /* enable error and warning messages */ debug_level = (unsigned) DBG_ERROR|DBG_WARNING; /* * Process valid command line options. Valid options are: * -V report version number and exit immediately * -d set debugging level to specified value * -v enable info messages */ while (argc > 1 && argv[1][0] == '-') { if (strcmp(argv[1], "-V") == 0) { #if SUPPORT_SLOVAK if (language == 421) printf("%s verzia %s\n", progname, patchlevel); else printf("%s version %s\n", progname, patchlevel); #else printf("%s version %s\n", progname, patchlevel); #endif exit(EXIT_SUCCESS); } else if (strcmp(argv[1], "-v") == 0) debug_level = (unsigned) 3; else if (strcmp(argv[1], "-d") == 0) { if (argc<3 || sscanf(argv[2], "%lu", &debug_level)!=1) usage(); argc--; argv++; } else usage(); argc--; argv++; } /* * Check there is one argument (name of data file) (in addition to * the name of the program itself). */ if (argc != 2) usage(); signal(SIGTERM, genericsighandler); signal(SIGINT, genericsighandler); if ((lockingpid=my_lock(argv[1], gen_lockfile_name)) > 0) error("%s is in use by process %d", argv[1], lockingpid); else if (lockingpid < 0) error("can't create lockfile: %s", strerror(errno)); rootptr = NULL; /* mark tree empty */ (void) loadfile(argv[1], &rootptr); /* populate tree with datafile */ if (class == NULL) error("class undefined (use 'C' in data file)"); if (definer == NULL) error("definer undefined (use 'D' in data file)"); /* * Main loop - prompt user, process response, check return code * for quit value. */ for (rc=AN_RC_RESTART;rc!=AN_RC_QUIT;rc=process(&rootptr)) #if SUPPORT_SLOVAK if (language == 421) printf("Predstav si nejake %s ... ", class); else /* getart() generates the word 'a' or 'an' */ printf("Think of %s%s ... ", getart(argv[1]), class); #else /* getart() generates the word 'a' or 'an' */ printf("Think of %s%s ... ", getart(argv[1]), class); #endif /* * Just before quitting save all the tree (which has probably changed). */ savefile(argv[1], rootptr); my_unlock(argv[1], gen_lockfile_name); exit(EXIT_SUCCESS); } /****************************************************************************** * * Function: usage * * Parameters: none * * Returns: doesn't; it uses exit() instead * * Description: * * this gets called when the user calls this program with * invalid options of missing parameters. it tells them * what they should have done and then exits. * ******************************************************************************/ static void usage() { #if SUPPORT_SLOVAK if (language == 421) { fprintf(stderr, "Pust mi tak: %s \n", progname); fprintf(stderr, " %s -V\n", progname); } else { fprintf(stderr, "Usage: %s [ -d | -v ] \n", progname); fprintf(stderr, " %s -V\n", progname); } #else fprintf(stderr, "Usage: %s [ -d | -v ] \n", progname); fprintf(stderr, " %s -V\n", progname); #endif exit(EXIT_FAILURE); } /****************************************************************************** * * Function: rotate * * Parameters: three addresses of node pointers * * Returns: nothing * * Description: * * swaps three values around - this is used by the * rephrasing code, and isn't compiled in if rephrasing * is not included. * ******************************************************************************/ #if SUPPORT_REPHRASE static void rotate( struct node **ptr1_addr, struct node **ptr2_addr, struct node **ptr3_addr) { struct node *ptr; ptr = *ptr1_addr; *ptr1_addr = *ptr2_addr; *ptr2_addr = *ptr3_addr; *ptr3_addr = ptr; } #endif /****************************************************************************** * * Function: process * * Parameters: address of a node to start at * (note function is recursive (i.e. calls itself) so * while *initially* it's passed the very top node, * later it's passed a lower node. Note it's passed * *the address of* a node, this is order that it can * change the node itself itself! * * Returns: code indicating what to do as it reverses up the data * * Description: * * Ok, this is the biggy! What it's basically doing is * asking a question and if the answer it receives leads it * to ask another question then it calls itself to get itself * to do that (rather than doing it itself)! Follow? :-) * In the event that it encounters a non-question - i.e. * an animal or a person or whatever, then it says "I think * I know what you were thinking of!" and proceeds to * state its guess and ask if it was correct. If it was * correct, well there's nothing else to do except retreat * back out of the calls to itself it made on the way down. * If it's wrong then it needs to ask what the user was * thinking of and replace the animal that it thought the * user was thinking of with a question that differentiates * between the guess the program made and what the user's * animal actually was. Having inserted the question where * the animal was, it then need to create two new nodes * for the animals and insert them. * * And if it did create two new nodes then there is a change * that unbalancedness has been introduced, so we must * request that calls of this function check for it as * they retreat out of the recursion. And if they do find * outofbalancedness of level 2 (1 is acceptable) then they * have to do some rephrasing - if it's switched on. * ******************************************************************************/ static int process( struct node **nodeptr_addr) { char response[128], response2[128]; int rc; #if SUPPORT_REPHRASING int rc, lhgt, rhgt, llhgt, lrhgt, rlhgt, rrhgt; #endif #if SUPPORT_REPHRASING debug(DBG_SPECIAL1, "height of current tree is %d", (*nodeptr_addr)->hgt); #endif /* * If the current node has children then it must be a question. */ if ((*nodeptr_addr)->lch != NULL) { #if SUPPORT_SLOVAK if (language == 421) { printf("%s? [anzk] ", (*nodeptr_addr)->txt); (void) fgets(response, (int) sizeof(response), stdin); switch (response[0]) { case 'a': rc = process(&(*nodeptr_addr)->lch); break; case 'n': rc = process(&(*nodeptr_addr)->rch); break; case 'k': return(AN_RC_QUIT); case 'z': return(AN_RC_RESTART); } } else { printf("%s? [ynqar] ", (*nodeptr_addr)->txt); (void) fgets(response, (int) sizeof(response), stdin); switch (response[0]) { case 'y': rc = process(&(*nodeptr_addr)->lch); break; case 'n': rc = process(&(*nodeptr_addr)->rch); break; case 'q': return(AN_RC_QUIT); case 'r': return(AN_RC_RESTART); case 'a': exit(EXIT_SUCCESS); } } #else /* * Ask the question and get the answer */ printf("%s? [ynqar] ", (*nodeptr_addr)->txt); (void) fgets(response, (int) sizeof(response), stdin); /* * If the user answers 'yes' to the question then move down to * the left and call this function again. If 'no' the go to the * right. */ switch (response[0]) { case 'y': rc = process(&(*nodeptr_addr)->lch); break; case 'n': rc = process(&(*nodeptr_addr)->rch); break; case 'q': return(AN_RC_QUIT); case 'r': return(AN_RC_RESTART); case 'a': exit(EXIT_SUCCESS); } #endif /* * Now, the call to this function itself above resulted (after * a few more deeper calls to itself) to the animal being correctly * guessed or the guess being wrong and a new question and a new * animal being inserted into the data structure. Note that we * saved the record code. Now if the return code says data was added * and hence we need to recalculate outofbalancednesses then that's * what we do. Outofbalancednesses or 2 or -2 require rebalancing. * 1 or -1 is not unbalanced enoug to be able to rebalance it, and * 0 is perfectly balanced already. * * The code for actually doing the rebalancing is a nightmare! * And explaining how rebalancing is done is just impossible; but * basically it involves rearranging three questions and putting * 'or's and 'not's and 'and's in front of some of them. */ debug(DBG_SPECIAL1, "process: coming up from '%c' branch, rc is %d", response[0], rc); switch (rc) { #if SUPPORT_REPHRASING case AN_RC_RECALC: debug(DBG_SPECIAL1, "process: reblnc ..."); lhgt = (*nodeptr_addr)->lch->hgt; rhgt = (*nodeptr_addr)->rch->hgt; (*nodeptr_addr)->hgt = ((lhgt > rhgt) ? lhgt : rhgt) + 1; switch (rhgt - lhgt) { case -2: debug(DBG_SPECIAL1, "process: reblnc -2"); llhgt = (*nodeptr_addr)->lch->lch->hgt; lrhgt = (*nodeptr_addr)->lch->rch->hgt; switch (lrhgt - llhgt) { case -1: debug(DBG_SPECIAL1, "process: reblnc -2/-1"); /* rotate(&(*nodeptr_addr)->lch->rch, nodeptr_addr, &(*nodeptr_addr)->lch); (void) rephrase(TRUE, AN_LGC_AND, FALSE, nodeptr_addr, AN_CH_LFT); */ rotate(&(*nodeptr_addr)->lch->rch, nodeptr_addr, &(*nodeptr_addr)->lch); (void) rephrase(TRUE, AN_LGC_AND, TRUE, nodeptr_addr, AN_CH_RGT); return(AN_RC_RESTART); case 0: debug(DBG_SPECIAL1, "process: reblnc -2/0"); error("not coded yet"); case 1: debug(DBG_SPECIAL1, "process: reblnc -2/1"); rotate(&(*nodeptr_addr)->lch->lch, nodeptr_addr, &(*nodeptr_addr)->lch); (void) rephrase(TRUE, AN_LGC_OR, FALSE, nodeptr_addr, AN_CH_LFT); return(AN_RC_RESTART); default: error("process: reblnc -2/default"); } case -1: debug(DBG_SPECIAL1, "process: reblnc -1"); return(AN_RC_RECALC); case 0: debug(DBG_SPECIAL1, "process: reblnc 0"); return(AN_RC_RECALC); case 1: debug(DBG_SPECIAL1, "process: reblnc 1"); return(AN_RC_RECALC); case 2: debug(DBG_SPECIAL1, "process: reblnc 2"); rlhgt = (*nodeptr_addr)->rch->lch->hgt; rrhgt = (*nodeptr_addr)->rch->rch->hgt; switch(rrhgt - rlhgt) { case -1: debug(DBG_SPECIAL1, "process: reblnc 2/-1"); rotate(&(*nodeptr_addr)->rch->rch, nodeptr_addr, &(*nodeptr_addr)->rch); (void) rephrase(TRUE, AN_LGC_AND, FALSE, nodeptr_addr, AN_CH_RGT); return(AN_RC_RESTART); case 0: debug(DBG_SPECIAL1, "process: reblnc 2/0"); error("unexpected situation (001)"); case 1: debug(DBG_SPECIAL1, "process: reblnc 2/1"); rotate(&(*nodeptr_addr)->rch->lch, nodeptr_addr, &(*nodeptr_addr)->rch); (void) rephrase(TRUE, AN_LGC_OR, TRUE, nodeptr_addr, AN_CH_LFT); return(AN_RC_RESTART); default: error("unexpected situation (002)"); } default: error("unexpected situation (003)"); } return(AN_RC_RECALC); #endif case AN_RC_QUIT: return(AN_RC_QUIT); case AN_RC_RESTART: return(AN_RC_RESTART); } } else { #if SUPPORT_SLOVAK if (language == 421) { printf("Je to %s? [ankz] ", (*nodeptr_addr)->txt); (void) fgets(response, (int) sizeof(response), stdin); switch (response[0]) { case 'a': printf("Mudry som nie?\n"); return(AN_RC_RESTART); case 'z': return(AN_RC_RESTART); case 'k': return(AN_RC_QUIT); case 'n': printf("%s je to? [kz] ", definer); (void) fgets(response, (int) sizeof(response), stdin); switch (response[0]) { case 'k': return(AN_RC_QUIT); case 'z': return(AN_RC_RESTART); } printf("Pis mi otazku; odpoved pre %s musi byt 'ano', a pre %s musi byt 'nie': [kz] ", (*nodeptr_addr)->txt, response); (void) fgets(response2, (int) sizeof(response2), stdin); switch (response2[0]) { case 'k': return(AN_RC_QUIT); case 'z': return(AN_RC_RESTART); } #ifdef MSDOS /* * This program works under MSDOS, except that * MSDOS uses CR-NL to represent what Unix does * with only NL. So we need to erase an extra * character on the end of an user-supplied * question for MSDOS. */ if (response2[strlen(response2)-1] == '\r') response2[strlen(response2)-1] = '\0'; if (response[strlen(response)-1] == '\r') response[strlen(response)-1] = '\0'; #endif if (response[strlen(response)-1] == '\n') response[strlen(response)-1] = '\0'; if (response2[strlen(response2)-1] == '\n') response2[strlen(response2)-1] = '\0'; if (response2[strlen(response2)-1] == '?') response2[strlen(response2)-1] = '\0'; (*nodeptr_addr)->lch=calloc(1, sizeof(struct node)); (*nodeptr_addr)->lch->txt = (*nodeptr_addr)->txt; (*nodeptr_addr)->lch->lch = NULL; (*nodeptr_addr)->lch->rch = NULL; #if SUPPORT_REPHRASING (*nodeptr_addr)->lch->hgt = 0; #endif (*nodeptr_addr)->rch=calloc(1, sizeof(struct node)); (*nodeptr_addr)->rch->txt=strdup(response); (*nodeptr_addr)->rch->lch = NULL; (*nodeptr_addr)->rch->rch = NULL; #if SUPPORT_REPHRASING (*nodeptr_addr)->rch->hgt = 0; #endif (*nodeptr_addr)->txt = strdup(response2); #if SUPPORT_REPHRASING (*nodeptr_addr)->hgt = 1; #endif printf("Diky! Uz som bol mudry, ale teraz som mudrejsi!\n"); #if SUPPORT_REPHRASING return(AN_RC_RECALC); #else return(AN_RC_RESTART); #endif } } else { /* getart() generates the word 'a' or 'an' */ printf("Is it %s%s? [ynqar] ", getart((*nodeptr_addr)->txt), (*nodeptr_addr)->txt); (void) fgets(response, (int) sizeof(response), stdin); switch (response[0]) { case 'y': printf("Great!\n"); return(AN_RC_RESTART); case 'r': return(AN_RC_RESTART); case 'q': return(AN_RC_QUIT); case 'a': exit(EXIT_SUCCESS); case 'n': printf("%s is it? [qar] ", definer); (void) fgets(response, (int) sizeof(response), stdin); switch (response[0]) { case 'q': return(AN_RC_QUIT); case 'a': exit(EXIT_SUCCESS); case 'r': return(AN_RC_RESTART); } printf("Enter a question for which the answer for %s is yes, and for which %s is no: [qar] ", (*nodeptr_addr)->txt, response); (void) fgets(response2, (int) sizeof(response2), stdin); switch (response2[0]) { case 'q': return(AN_RC_QUIT); case 'a': exit(EXIT_SUCCESS); case 'r': return(AN_RC_RESTART); } #ifdef MSDOS /* * This program works under MSDOS, except that * MSDOS uses CR-NL to represent what Unix does * with only NL. So we need to erase an extra * character on the end of an user-supplied * question for MSDOS. */ if (response2[strlen(response2)-1] == '\r') response2[strlen(response2)-1] = '\0'; if (response[strlen(response)-1] == '\r') response[strlen(response)-1] = '\0'; #endif if (response[strlen(response)-1] == '\n') response[strlen(response)-1] = '\0'; if (response2[strlen(response2)-1] == '\n') response2[strlen(response2)-1] = '\0'; if (response2[strlen(response2)-1] == '?') response2[strlen(response2)-1] = '\0'; (*nodeptr_addr)->lch=calloc(1, sizeof(struct node)); (*nodeptr_addr)->lch->txt = (*nodeptr_addr)->txt; (*nodeptr_addr)->lch->lch = NULL; (*nodeptr_addr)->lch->rch = NULL; #if SUPPORT_REPHRASING (*nodeptr_addr)->lch->hgt = 0; #endif (*nodeptr_addr)->rch=calloc(1, sizeof(struct node)); (*nodeptr_addr)->rch->txt=strdup(response); (*nodeptr_addr)->rch->lch = NULL; (*nodeptr_addr)->rch->rch = NULL; #if SUPPORT_REPHRASING (*nodeptr_addr)->rch->hgt = 0; #endif (*nodeptr_addr)->txt = strdup(response2); #if SUPPORT_REPHRASING (*nodeptr_addr)->hgt = 1; #endif printf("Thanks! I was intelligent but now I'm more intelligent!\n"); #if SUPPORT_REPHRASING return(AN_RC_RECALC); #else return(AN_RC_RESTART); #endif } } #else /* getart() generates the word 'a' or 'an' */ printf("Is it %s%s? [ynqar] ", getart((*nodeptr_addr)->txt), (*nodeptr_addr)->txt); (void) fgets(response, (int) sizeof(response), stdin); switch (response[0]) { case 'y': printf("Great!\n"); return(AN_RC_RESTART); case 'r': return(AN_RC_RESTART); case 'q': return(AN_RC_QUIT); case 'a': exit(EXIT_SUCCESS); /* * Here we are asking 'what is it?'. We get the new animal * and a question to differentiate between the wrong guess and * what the user actually was thinking of. */ case 'n': printf("%s is it? [qar] ", definer); (void) fgets(response, (int) sizeof(response), stdin); switch (response[0]) { case 'q': return(AN_RC_QUIT); case 'a': exit(EXIT_SUCCESS); case 'r': return(AN_RC_RESTART); } printf("Enter a question for which the answer for %s is yes, and for which %s is no: [qar] ", (*nodeptr_addr)->txt, response); (void) fgets(response2, (int) sizeof(response2), stdin); switch (response2[0]) { case 'q': return(AN_RC_QUIT); case 'a': exit(EXIT_SUCCESS); case 'r': return(AN_RC_RESTART); } #ifdef MSDOS /* * This program works under MSDOS, except that * MSDOS uses CR-NL to represent what Unix does * with only NL. So we need to erase an extra * character on the end of an user-supplied * question for MSDOS. */ if (response2[strlen(response2)-1] == '\r') response2[strlen(response2)-1] = '\0'; if (response[strlen(response)-1] == '\r') response[strlen(response)-1] = '\0'; #endif if (response[strlen(response)-1] == '\n') response[strlen(response)-1] = '\0'; if (response2[strlen(response2)-1] == '\n') response2[strlen(response2)-1] = '\0'; if (response2[strlen(response2)-1] == '?') response2[strlen(response2)-1] = '\0'; /* * Here we create a new left child node, and copy * the wrongly guessed animal into it. */ (*nodeptr_addr)->lch=calloc(1, sizeof(struct node)); (*nodeptr_addr)->lch->txt = (*nodeptr_addr)->txt; (*nodeptr_addr)->lch->lch = NULL; (*nodeptr_addr)->lch->rch = NULL; #if SUPPORT_REPHRASING (*nodeptr_addr)->lch->hgt = 0; #endif /* * Here we create a new right child node, and copy * the new animal into it. */ (*nodeptr_addr)->rch=calloc(1, sizeof(struct node)); (*nodeptr_addr)->rch->txt=strdup(response); (*nodeptr_addr)->rch->lch = NULL; (*nodeptr_addr)->rch->rch = NULL; #if SUPPORT_REPHRASING (*nodeptr_addr)->rch->hgt = 0; #endif /* * And where the wrong guess was, we now put the * question that differentiates between the two * animals. */ (*nodeptr_addr)->txt = strdup(response2); #if SUPPORT_REPHRASING (*nodeptr_addr)->hgt = 1; #endif printf("Thanks! I was intelligent but now I'm more intelligent!\n"); #if SUPPORT_REPHRASING /* * If rephrasing is enabled, then we need to tell * the process()es that called us, to check for * imbalance. */ return(AN_RC_RECALC); #else return(AN_RC_RESTART); #endif } #endif } } /****************************************************************************** * * Function: rephrase * * Parameters: don't ask * * Returns: nothing worth noting * * Description: * * oh my god ... you just don't want to know what this * does ... I'm not sure I can even remember! * ******************************************************************************/ #if SUPPORT_REPHRASING static int rephrase( int logic1, int comb, int logic2, struct node **nodeptr_addr, int link) { char response[128], response2[128]; struct node *tmpptr; #if SUPPORT_SLOVAK if (language == 421) { printf("Aby moje otazky boli jasnejsie, mohol by si: \n"); printf(" 1) zjasnesit toto: '(%s%s) %s (%s%s)'\n", (logic1 ? "" : "NOT "), (*nodeptr_addr)->txt, ((comb==AN_LGC_AND) ? "A" : "ALEBO"), (logic2 ? "" : "NIE "), ((link == AN_CH_RGT) ? (*nodeptr_addr)->rch : (*nodeptr_addr)->lch)->txt); printf(" 2) or zjasnesit toto: '(%s%s) %s (%s%s)'\n", (logic1 ? "NIE " : ""), (*nodeptr_addr)->txt, ((comb==AN_LGC_AND) ? "ALEBO" : "A"), (logic2 ? "NIE " : ""), ((link == AN_CH_RGT) ? (*nodeptr_addr)->rch : (*nodeptr_addr)->lch)->txt); printf(" 3) nerobit nic, ale budem pouzivat prvu moznost\n"); printf("Vyber si [123]: "); } else { printf("In order to simplify the questions I ask, you may: \n"); printf(" 1) rephrase this: '(%s%s) %s (%s%s)'\n", (logic1 ? "" : "NOT "), (*nodeptr_addr)->txt, ((comb==AN_LGC_AND) ? "AND" : "OR"), (logic2 ? "" : "NOT "), ((link == AN_CH_RGT) ? (*nodeptr_addr)->rch : (*nodeptr_addr)->lch)->txt); printf(" 2) or rephrase this: '(%s%s) %s (%s%s)'\n", (logic1 ? "NOT " : ""), (*nodeptr_addr)->txt, ((comb==AN_LGC_AND) ? "OR" : "AND"), (logic2 ? "NOT " : ""), ((link == AN_CH_RGT) ? (*nodeptr_addr)->rch : (*nodeptr_addr)->lch)->txt); printf(" 3) not rephrase either of them\n"); printf("Choose [123]: "); } #else printf("In order to simplify the questions I ask, you may: \n"); printf(" 1) rephrase this: '(%s%s) %s (%s%s)'\n", (logic1 ? "" : "NOT "), (*nodeptr_addr)->txt, ((comb==AN_LGC_AND) ? "AND" : "OR"), (logic2 ? "" : "NOT "), ((link == AN_CH_RGT) ? (*nodeptr_addr)->rch : (*nodeptr_addr)->lch)->txt); printf(" 2) or rephrase this: '(%s%s) %s (%s%s)'\n", (logic1 ? "NOT " : ""), (*nodeptr_addr)->txt, ((comb==AN_LGC_AND) ? "OR" : "AND"), (logic2 ? "NOT " : ""), ((link == AN_CH_RGT) ? (*nodeptr_addr)->rch : (*nodeptr_addr)->lch)->txt); printf(" 3) not rephrase either of them\n"); printf("Choose [123]: "); #endif (void) fgets(response, (int) sizeof(response), stdin); if (response[0] == '\0' || response[0] == '3') { #if SUPPORT_SLOVAK if (language == 421) { sprintf(response2, "(%s%s) %s (%s%s)'", (logic1 ? "" : "NIE "), (*nodeptr_addr)->txt, ((comb==AN_LGC_AND) ? "A" : "ALEBO"), (logic2 ? "" : "NIE "), ((link == AN_CH_RGT) ? (*nodeptr_addr)->rch : (*nodeptr_addr)->lch)->txt); } else { sprintf(response2, "(%s%s) %s (%s%s)'", (logic1 ? "" : "NOT "), (*nodeptr_addr)->txt, ((comb==AN_LGC_AND) ? "AND" : "OR"), (logic2 ? "" : "NOT "), ((link == AN_CH_RGT) ? (*nodeptr_addr)->rch : (*nodeptr_addr)->lch)->txt); } #else sprintf(response2, "(%s%s) %s (%s%s)'", (logic1 ? "" : "NOT "), (*nodeptr_addr)->txt, ((comb==AN_LGC_AND) ? "AND" : "OR"), (logic2 ? "" : "NOT "), ((link == AN_CH_RGT) ? (*nodeptr_addr)->rch : (*nodeptr_addr)->lch)->txt); #endif } else if (response[0] == '1' || response[0] == '2') { #if SUPPORT_SLOVAK if (language == 421) printf("Tak zjasnesaj to: "); else printf("Enter the rephrasing: "); #else printf("Enter the rephrasing: "); #endif (void) fgets(response2, (int) sizeof(response2), stdin); if (response[0] == '2') { debug(DBG_SPECIAL1, "swapping"); tmpptr = (*nodeptr_addr)->lch; (*nodeptr_addr)->lch = (*nodeptr_addr)->rch; (*nodeptr_addr)->rch = tmpptr; } else debug(DBG_SPECIAL1, "not swapping"); } free((*nodeptr_addr)->txt); (*nodeptr_addr)->txt = strdup(response2); return(0); } #endif /****************************************************************************** * * Function: savefile * * Parameters: name of file to save tree to * pointer to top of data structure to save * * Returns: nothing worth noting * * Description: * saves the words 'what' and 'animal' (or 'who' and * 'person' or whatever) and then saves the top question * and then calls itself to save the whole left sub-tree * and then calls itself again to save to whole right * sub-tree. Of course if the current node is not a question * then it just saves the animal (or whatever) and has * no sub-trees underneath to deal with. * * Note the only the top invocation actually opens the * file - all the others know it's open already - and they * know it's open by examining the file handle - hence it * must be either global or function-static. * ******************************************************************************/ static int savefile( char *datafile, struct node *nodeptr) { static FILE *fp = NULL; if (fp == NULL) { if ((fp=fopen(datafile, "w")) == NULL) #if SUPPORT_SLOVAK if (language == 421) error("nemozem nahrat subor"); else error("can't save datafile"); #else error("can't save datafile"); #endif fprintf(fp, "D %s\n", definer); fprintf(fp, "C %s\n", class); #if SUPPORT_SLOVAK fprintf(fp, "L %d\n", language); #endif } if (nodeptr->lch == NULL) fprintf(fp, "A %s\n", nodeptr->txt); else { fprintf(fp, "Q %s\n", nodeptr->txt); savefile(NULL, nodeptr->lch); savefile(NULL, nodeptr->rch); } } /****************************************************************************** * * Function: loadfile * * Parameters: name of file to load tree from * address of pointer to top of data structure to save * (note it's the 'address of' since this function will * want to change its value). * * Returns: nothing worth noting * * Description: * loads the words 'what' and 'animal' (or 'who' and * 'person' or whatever) and then loads the top question * and then calls itself to load the whole left sub-tree * and then calls itself again to load to whole right * sub-tree. Of course if the current node is not a question * then it just loads the animal (or whatever) and has * no sub-trees underneath to deal with. * * Note the only the top invocation actually opens the * file - all the others know it's open already - and they * know it's open by examining the file handle - hence it * must be either global or function-static. * ******************************************************************************/ #if SUPPORT_REPHRASING static int loadfile( #else static void loadfile( #endif char *datafile, struct node **nodeptr_addr) { static FILE *fp = NULL; char text[128]; #if SUPPORT_REPHRASING int lhgt, rhgt; #endif if (fp == NULL && (fp=fopen(datafile, "r")) == NULL) #if SUPPORT_SLOVAK if (language == 421) error("nemohol som citat %s", datafile); else error("couldn't open %s", datafile); #else error("couldn't open %s", datafile); #endif while (!feof(fp)) { (void) fgets(text, (int) sizeof(text), fp); if (text[strlen(text)-1] == '\n') text[strlen(text)-1] = '\0'; if (text[strlen(text)-1] == '\?') text[strlen(text)-1] = '\0'; switch (text[0]) { case '\0': case '#': break; case 'Q': case 'A': *nodeptr_addr = calloc(1, sizeof(struct node)); (*nodeptr_addr)->txt = strdup(text+2); if (text[0] == 'Q') { #if SUPPORT_REPHRASING lhgt = loadfile(NULL, &(*nodeptr_addr)->lch); rhgt = loadfile(NULL, &(*nodeptr_addr)->rch); (*nodeptr_addr)->hgt = ((lhgt > rhgt) ? lhgt : rhgt) + 1; #else loadfile(NULL, &(*nodeptr_addr)->lch); loadfile(NULL, &(*nodeptr_addr)->rch); #endif } else { (*nodeptr_addr)->lch = NULL; (*nodeptr_addr)->rch = NULL; #if SUPPORT_REPHRASING (*nodeptr_addr)->hgt = 0; #endif } #if SUPPORT_REPHRASING return((*nodeptr_addr)->hgt); #else return; #endif case 'C': class = strdup(text+2); debug(DBG_SPECIAL1, "class set to %s", class); break; #if SUPPORT_SLOVAK case 'L': language = atoi(text+2); debug(DBG_SPECIAL1, "language set to %d", language); break; #endif case 'D': definer = strdup(text+2); debug(DBG_SPECIAL1, "definer set to %s", definer); break; } } if (feof(fp)) fclose(fp); #if SUPPORT_REPHRASING return((*nodeptr_addr)->hgt); #endif } int gen_lockfile_name( char *lockfile, char *lockwhat) { sprintf(lockfile, "%s.pid", lockwhat); return(0); } @ 1.17 log @added call to unlock - since every time the stale lock removal was reported @ text @d19 1 a19 1 static char *animal_c_rcs_id = "$Header: /home/ahuxley/dev/supported/animal/bin/RCS/animal.c,v 1.16 1999/01/07 11:37:44 alexis Exp ahuxley $"; d36 1 a36 1 #include "utils.h" /* for mybasename(), error(), ... */ @ 1.16 log @lock functions now require a name generating function as parameter class and definer absence is an error @ text @d19 1 a19 1 static char *animal_c_rcs_id = "$Header: /diskb/home/alexis/dev/animal/bin/RCS/animal.c,v 1.15 1998/10/07 21:56:02 alexis Exp alexis $"; d303 1 @ 1.15 log @switched from using 'version' var, to 'patchlevel' @ text @d19 1 a19 1 static char *animal_c_rcs_id = "$Header: /diskb/home/alexis/dev/animal/bin/RCS/animal.c,v 1.14 1998/10/07 14:55:09 alexis Exp alexis $"; d29 2 d159 1 d165 2 a166 2 static char *definer; /* 'what', 'who' in right lang */ static char *class; /* 'animal', 'person' in right lang */ d216 1 d265 8 d275 5 d293 1 a293 1 #else d1063 2 d1113 8 @ 1.14 log @lots of changes - primarily cosmetic also added preprocessor symbols to control slovak and rephrasing. @ text @d19 1 a19 1 static char *animal_c_rcs_id = "$Header: animal.c,v 1.13 1998/10/07 10:46:36 alexis Exp alexis $"; d35 1 a35 1 #include "version.h" /* for version_init */ a161 1 static char *version; a217 2 /* extract version no. from RCS id */ version = version_init(animal_c_rcs_id); a227 1 debug_level |= (unsigned) DBG_INFO; d230 1 a230 1 info("verzia %s", version); d232 1 a232 1 info("version %s", version); d234 1 a234 1 info("version %s", version); @ 1.13 log @changed gets to fgets and basename to mybasename @ text @d1 23 a23 3 #define MAIN static char *animal_c_rcs_id = "$Id: animal.c,v 1.12 1997/11/11 14:08:34 alexis Exp alexis $"; d29 5 d37 91 a127 5 struct node { char *txt; struct node *lch; struct node *rch; int hgt; d130 38 a167 15 #define AN_RC_QUIT 1 #define AN_RC_RESTART 2 #define AN_RC_RECALC 3 #define AN_LGC_OR 1 #define AN_LGC_AND 2 #define AN_CH_LFT 1 #define AN_CH_RGT 2 char *progname; char *version; char *definer; char *class; int language; d169 38 a206 11 usage() { if (language == 42) { fprintf(stderr, "Pust mi tak: %s \n", progname); fprintf(stderr, " %s -V\n", progname); } else { fprintf(stderr, "Usage: %s [ -d | -v ] \n", progname); fprintf(stderr, " %s -V\n", progname); } exit(1); } d212 2 a213 3 struct node *rootptr; int rc; char *datafile; d215 5 a219 2 progname = mybasename(argv[0], NULL); debug_level = DBG_ERROR|DBG_WARNING; d222 7 d231 7 a237 4 debug_level |= DBG_INFO; if (language == 42) { info("verzia %s", version); } else { d239 2 a240 2 } exit(0); d243 1 a243 1 debug_level = 3; d246 2 a247 2 (argc<3) && usage(); (sscanf(argv[2], "%ld", &debug_level)!=1) && usage(); d257 5 d265 7 a271 2 rootptr = NULL; loadfile(argv[1], &rootptr); d274 8 a281 3 if (language == 42) { printf("Predstav si nejake %s ... ", class); } else { d283 8 d293 31 a323 1 savefile(argv[1], rootptr); d326 18 a343 1 int rotate( d355 43 d399 1 a399 1 int process( d403 2 d406 1 d408 1 d410 6 d417 24 a440 10 if (language == 42) { printf("%s? [anzk] ", (*nodeptr_addr)->txt); fgets(response, sizeof(response), stdin); switch (response[0]) { case 'a': rc = process(&(*nodeptr_addr)->lch); break; case 'n': rc = process(&(*nodeptr_addr)->rch); break; case 'k': return(AN_RC_QUIT); case 'z': return(AN_RC_RESTART); d442 5 a446 1 } else { d448 8 a455 1 fgets(response, sizeof(response), stdin); d463 1 a463 1 case 'a': exit(0); d465 19 a483 1 } d486 1 d503 1 a503 1 rephrase(TRUE, AN_LGC_AND, FALSE, nodeptr_addr, AN_CH_LFT); */ d507 1 a507 1 rephrase(TRUE, AN_LGC_AND, TRUE, nodeptr_addr, AN_CH_RGT); d511 1 a511 1 error(exit, 1, "not coded yet"); d517 1 a517 1 rephrase(TRUE, AN_LGC_OR, FALSE, nodeptr_addr, AN_CH_LFT); d520 1 a520 1 error(exit, 1, "process: reblnc -2/default"); d541 1 a541 1 rephrase(TRUE, AN_LGC_AND, FALSE, nodeptr_addr, AN_CH_RGT); d545 1 a545 1 error(exit, 1, "unexpected situation (001)"); d551 1 a551 1 rephrase(TRUE, AN_LGC_OR, TRUE, nodeptr_addr, AN_CH_LFT); d554 1 a554 1 error(exit, 1, "unexpected situation (002)"); d557 1 a557 1 error(exit, 1, "unexpected situation (003)"); d560 1 d567 90 a656 20 if (language == 42) { printf("Je to %s? [ankz] ", (*nodeptr_addr)->txt); fgets(response, sizeof(response), stdin); switch (response[0]) { case 'a': printf("Mudry som nie?\n"); return(AN_RC_RESTART); case 'z': return(AN_RC_RESTART); case 'k': return(AN_RC_QUIT); case 'n': printf("%s je to? [kz] ", definer); fgets(response, sizeof(response), stdin); switch (response[0]) { case 'k': return(AN_RC_QUIT); case 'z': return(AN_RC_RESTART); } printf("Pis mi otazku; odpoved pre %s musi byt 'ano', a pre %s musi byt 'nie': [kz] ", (*nodeptr_addr)->txt, response); fgets(response2, sizeof(response2), stdin); switch (response2[0]) { case 'k': return(AN_RC_QUIT); case 'z': return(AN_RC_RESTART); } d658 42 a699 4 if (response2[strlen(response2)-1] == '\r') response2[strlen(response2)-1] = '\0'; if (response2[strlen(response2)-1] == '\n') response2[strlen(response2)-1] = '\0'; d701 1 a701 16 if (response2[strlen(response2)-1] == '?') response2[strlen(response2)-1] = '\0'; (*nodeptr_addr)->lch=calloc(1, sizeof(struct node)); (*nodeptr_addr)->lch->txt = (*nodeptr_addr)->txt; (*nodeptr_addr)->lch->lch = NULL; (*nodeptr_addr)->lch->rch = NULL; (*nodeptr_addr)->lch->hgt = 0; (*nodeptr_addr)->rch=calloc(1, sizeof(struct node)); (*nodeptr_addr)->rch->txt=strdup(response); (*nodeptr_addr)->rch->lch = NULL; (*nodeptr_addr)->rch->rch = NULL; (*nodeptr_addr)->rch->hgt = 0; (*nodeptr_addr)->txt = strdup(response2); (*nodeptr_addr)->hgt = 1; printf("Diky! Uz som bol mudry, ale teraz som mudrejsi!\n"); return(AN_RC_RECALC); d703 2 a704 1 } else { d706 1 a706 1 fgets(response, sizeof(response), stdin); d712 8 a719 1 case 'a': exit(0); d721 1 a721 1 fgets(response, sizeof(response), stdin); d724 1 a724 1 case 'a': exit(0); d728 1 a728 1 fgets(response2, sizeof(response2), stdin); d731 1 a731 1 case 'a': exit(0); d735 8 d745 5 a751 1 #endif d754 6 d764 1 d766 6 d776 1 d778 7 d786 1 d788 1 d790 7 d798 3 d802 1 a802 1 } d806 14 d821 2 a822 1 int rephrase( d832 2 a833 1 if (language == 42) { d867 17 d885 1 a885 1 fgets(response, sizeof(response), stdin); d887 2 a888 1 if (language == 42) { d903 8 d912 2 a913 1 if (language == 42) { d915 1 a915 1 } else { d917 4 a920 2 } fgets(response2, sizeof(response2), stdin); d931 1 d933 26 d960 1 a960 1 savefile( d967 8 a974 5 if (language == 42) { error(exit, 1, "nemozes nahrat subor"); } else { error(exit, 1, "can't save datafile"); } d977 1 d979 1 d991 32 a1022 1 int loadfile( d1028 1 d1030 1 d1033 8 a1040 5 if (language == 42) { error(exit, 4, "nemohol som citat %s", datafile); } else { error(exit, 4, "couldn't open %s", datafile); } d1043 1 a1043 1 fgets(text, sizeof(text), fp); d1055 1 d1059 4 d1066 1 d1068 1 d1070 1 d1072 3 d1079 1 d1084 1 d1095 1 d1097 1 @ 1.12 log @support for slovak fixed rephrasing contrapositives @ text @d2 1 a2 1 static char *animal_c_rcs_id = "$Id: animal.c,v 1.11 1997/11/10 18:43:45 alexis Exp alexis $"; d9 1 a9 1 #include "utils.h" /* for basename(), error(), ... */ d55 1 a55 1 progname = basename(argv[0], NULL); d123 1 a123 1 gets(response); d134 1 a134 1 gets(response); d228 1 a228 1 gets(response); d235 1 a235 1 gets(response); d241 1 a241 1 gets(response2); d271 1 a271 1 gets(response); d279 1 a279 1 gets(response); d286 1 a286 1 gets(response2); d365 1 a365 1 gets(response); d388 1 a388 1 gets(response2); @ 1.11 log @*** empty log message *** @ text @d2 1 a2 1 static char *animal_c_rcs_id = "$Id: animal.c,v 1.10 1997/10/06 22:46:52 alexis Exp $"; d160 4 d167 1 a167 1 rephrase(TRUE, AN_LGC_AND, FALSE, nodeptr_addr, AN_CH_LFT); d246 6 d292 6 d327 1 a327 1 char response[128]; d330 3 a332 3 if (language == 42) { printf("Aby moje otazky boli jasnejsie, mohol by si: \n"); printf(" 1) zjasnesit toto: '(%s%s) %s (%s%s)'\n", d338 1 a338 2 printf(" 2) or zjasnesit toto: '(%s%s) %s (%s%s)'\n", d345 5 a349 6 printf(" 3) nerobit nic, ale budem pouzivat prvu moznost\n"); printf("Vyber si [123]: "); } else { printf("In order to simplify the questions I ask, you may: \n"); printf(" 1) rephrase this: '(%s%s) %s (%s%s)'\n", d355 1 a355 2 printf(" 2) or rephrase this: '(%s%s) %s (%s%s)'\n", d361 3 a363 6 printf(" 3) not rephrase either of them\n"); printf("Choose [123]: "); } a365 6 d368 6 a373 6 sprintf(response, "(%s%s) %s (%s%s)'", (logic1 ? "" : "NIE "), (*nodeptr_addr)->txt, ((comb==AN_LGC_AND) ? "A" : "ALEBO"), (logic2 ? "" : "NIE "), ((link == AN_CH_RGT) ? (*nodeptr_addr)->rch : (*nodeptr_addr)->lch)->txt); d375 1 a375 1 sprintf(response, "(%s%s) %s (%s%s)'", a381 1 d384 1 a384 1 printf("Tak zjasnesaj to: "); d386 1 a386 1 printf("Enter the rephrasing: "); d388 1 a388 1 gets(response); d390 1 d394 2 a395 1 } d398 1 a398 1 (*nodeptr_addr)->txt = strdup(response); d466 1 a466 1 debug(DBG_SPECIAL1, "class set to %s\n", class); d470 1 a470 1 debug(DBG_SPECIAL1, "language set to %s\n", language); d474 1 a474 1 debug(DBG_SPECIAL1, "definer set to %s\n", definer); @ 1.10 log @added rebalancing code @ text @d2 1 a2 1 static char *animal_c_rcs_id = "$Id: animal.c,v 1.9 1997/10/06 16:20:16 alexis Exp $"; d9 1 a9 1 #include "ppplcd_utils.h" /* for basename(), error(), ... */ d19 9 a27 4 #define AN_NOACTION 0 #define AN_QUIT 1 #define AN_RESTART 2 #define AN_RECALC 3 d31 3 d37 4 d43 1 d62 3 d66 1 d90 6 a95 2 for (rc=AN_RESTART;rc!=AN_QUIT;rc=process(&rootptr)) printf("Think of %s%s ... ", getart(argv[1]), basename(argv[1], ".dat")); a117 1 struct node *tmpptr; d121 12 d140 2 a141 2 case 'q': return(AN_QUIT); case 'r': return(AN_RESTART); d144 1 d147 2 a148 2 case AN_RECALC: debug(DBG_SPECIAL1, "process: rebalance ..."); d154 1 a154 1 debug(DBG_SPECIAL1, "process: rebalance -2"); d159 1 a159 1 debug(DBG_SPECIAL1, "process: rebalance -2/-1"); d163 2 a164 20 printf("1) Rephrase: '(%s) AND (%s)'\n", (*nodeptr_addr)->txt, (*nodeptr_addr)->rch->txt); printf("2) Rephrase: '(NOT %s) OR (NOT %s)'\n", (*nodeptr_addr)->txt, (*nodeptr_addr)->rch->txt); printf("3) Neither\n"); printf("Choice [123]: "); gets(response); if (response[0] == '\0' || response[0] == '3') sprintf(response, "(%s) AND (%s)", (*nodeptr_addr)->txt, (*nodeptr_addr)->rch->txt); else if (response[0] == '1') { printf("Rephrase: "); gets(response); } else if (response[0] == '2') { printf("Rephrase: "); gets(response); tmpptr = (*nodeptr_addr)->lch; (*nodeptr_addr)->lch = (*nodeptr_addr)->rch; (*nodeptr_addr)->rch = tmpptr; } free((*nodeptr_addr)->txt); (*nodeptr_addr)->txt = strdup(response); return(AN_RESTART); d166 1 a166 1 debug(DBG_SPECIAL1, "process: rebalance -2/0"); d169 1 a169 1 debug(DBG_SPECIAL1, "process: rebalance -2/1"); d173 2 a174 20 printf("1) Rephrase: '(%s) OR (NOT %s)'\n", (*nodeptr_addr)->txt, (*nodeptr_addr)->lch->txt); printf("2) Rephrase: '(NOT %s) AND (%s)'\n", (*nodeptr_addr)->txt, (*nodeptr_addr)->lch->txt); printf("3) Neither\n"); printf("Choice [123]: "); gets(response); if (response[0] == '\0' || response[0] == '3') sprintf(response, "(%s) OR (NOT %s)", (*nodeptr_addr)->txt, (*nodeptr_addr)->lch->txt); else if (response[0] == '1') { printf("Rephrase: "); gets(response); } else if (response[0] == '2') { printf("Rephrase: "); gets(response); tmpptr = (*nodeptr_addr)->lch; (*nodeptr_addr)->lch = (*nodeptr_addr)->rch; (*nodeptr_addr)->rch = tmpptr; } free((*nodeptr_addr)->txt); (*nodeptr_addr)->txt = strdup(response); return(AN_RESTART); d176 1 a176 1 error(exit, 1, "process: rebalance -2/default"); a177 1 break; d179 2 a180 2 debug(DBG_SPECIAL1, "process: rebalance -1"); return(AN_RECALC); d182 2 a183 2 debug(DBG_SPECIAL1, "process: rebalance 0"); return(AN_RECALC); d185 2 a186 2 debug(DBG_SPECIAL1, "process: rebalance 1"); return(AN_RECALC); d188 1 a188 1 debug(DBG_SPECIAL1, "process: rebalance 2"); d193 1 a193 1 debug(DBG_SPECIAL1, "process: rebalance 2/-1"); d197 2 a198 20 printf("1) Rephrase: '(%s) AND (NOT %s)'\n", (*nodeptr_addr)->txt, (*nodeptr_addr)->rch->txt); printf("2) Rephrase: '(NOT %s) OR (%s)'\n", (*nodeptr_addr)->txt, (*nodeptr_addr)->rch->txt); printf("3) Neither\n"); printf("Choice [123]: "); gets(response); if (response[0] == '\0' || response[0] == '3') sprintf(response, "(%s) AND (NOT %s)", (*nodeptr_addr)->txt, (*nodeptr_addr)->rch->txt); else if (response[0] == '1') { printf("Rephrase: "); gets(response); } else if (response[0] == '2') { printf("Rephrase: "); gets(response); tmpptr = (*nodeptr_addr)->lch; (*nodeptr_addr)->lch = (*nodeptr_addr)->rch; (*nodeptr_addr)->rch = tmpptr; } free((*nodeptr_addr)->txt); (*nodeptr_addr)->txt = strdup(response); return(AN_RESTART); d200 2 a201 2 debug(DBG_SPECIAL1, "process: rebalance 2/0"); error(exit, 1, "not coded yet"); d203 1 a203 1 debug(DBG_SPECIAL1, "process: rebalance 2/1"); d207 2 a208 21 printf("1) Rephrase: '(%s) OR (%s)'\n", (*nodeptr_addr)->txt, (*nodeptr_addr)->lch->txt); printf("2) Rephrase: '(NOT %s) AND (NOT %s)'\n", (*nodeptr_addr)->txt, (*nodeptr_addr)->lch->txt); printf("3) Neither\n"); printf("Choice [123]: "); gets(response); if (response[0] == '\0' || response[0] == '3') sprintf(response, "(%s) AND (NOT %s)", (*nodeptr_addr)->txt, (*nodeptr_addr)->lch->txt); else if (response[0] == '1') { printf("Rephrase: "); gets(response); } else if (response[0] == '2') { printf("Rephrase: "); gets(response); tmpptr = (*nodeptr_addr)->lch; (*nodeptr_addr)->lch = (*nodeptr_addr)->rch; (*nodeptr_addr)->rch = tmpptr; } free((*nodeptr_addr)->txt); (*nodeptr_addr)->txt = strdup(response); return(AN_RESTART); error(exit, 1, "not coded yet"); d210 1 a210 1 error(exit, 1, "process: rebalance 2/default"); d213 1 a213 1 error(exit, 1, "process: rebalance default"); d215 5 a219 5 return(AN_RECALC); case AN_QUIT: return(AN_QUIT); case AN_RESTART: return(AN_RESTART); d222 38 d264 3 a266 3 return(AN_RESTART); case 'r': return(AN_RESTART); case 'q': return(AN_QUIT); d268 1 a268 1 case 'n': printf("What is it? [qar] "); d271 1 a271 1 case 'q': return(AN_QUIT); d273 1 a273 1 case 'r': return(AN_RESTART); d278 1 a278 1 case 'q': return(AN_QUIT); d280 1 a280 1 case 'r': return(AN_RESTART); d296 94 a389 1 return(AN_RECALC); d392 2 d401 11 a411 2 if (fp == NULL && (fp=fopen(datafile, "w")) == NULL) return; d431 3 d435 1 d437 1 a437 1 if (!feof(fp)) { d444 27 a470 10 *nodeptr_addr = calloc(1, sizeof(struct node)); (*nodeptr_addr)->txt = strdup(text+2); if (text[0] == 'Q') { lhgt = loadfile(NULL, &(*nodeptr_addr)->lch); rhgt = loadfile(NULL, &(*nodeptr_addr)->rch); (*nodeptr_addr)->hgt = ((lhgt > rhgt) ? lhgt : rhgt) + 1; } else { (*nodeptr_addr)->lch = NULL; (*nodeptr_addr)->rch = NULL; (*nodeptr_addr)->hgt = 0; @ 1.9 log @*** empty log message *** @ text @d2 1 a2 1 static char *animal_c_rcs_id = "$Id: animal.c,v 1.8 1997/10/06 14:46:41 alexis Exp alexis $"; d29 1 a29 1 fprintf(stderr, "Usage: %s \n", progname); d52 4 a55 1 } else if (strcmp(argv[1], "-d") == 0) { d79 13 d96 2 a97 1 int rc, lhgt, rhgt; d114 147 a260 6 case AN_RECALC: lhgt = (*nodeptr_addr)->lch->hgt; rhgt = (*nodeptr_addr)->rch->hgt; (*nodeptr_addr)->hgt = ((lhgt > rhgt) ? lhgt : rhgt) + 1; return(AN_RECALC); case AN_QUIT: return(AN_QUIT); case AN_RESTART: return(AN_RESTART); a327 2 debug(DBG_SPECIAL1, "datafile=%s", datafile ? datafile : "NULL"); @ 1.8 log @added support for restarting and aborting at the time a question must be entered. also completed transition to recursion mode. @ text @d2 1 a2 1 static char *animal_c_rcs_id = "$Id: animal.c,v 1.7 1997/10/06 14:22:51 alexis Exp alexis $"; d16 1 a16 1 int bal; d19 5 d38 2 a39 3 struct node *rootptr, *nodeptr; int quit, done; char response[128]; d68 1 a68 2 if (loadfile(argv[1], &rootptr)) error(exit, 2, "datafile problem"); d70 1 a70 1 for (quit=0;!quit;) { a72 52 #if 0 for (done=0,nodeptr=rootptr;!quit&&!done;) { if (nodeptr->lch != NULL) { printf("%s? [ynqar] ", nodeptr->txt); gets(response); switch (response[0]) { case 'y': nodeptr=nodeptr->lch; break; case 'n': nodeptr=nodeptr->rch; break; case 'q': quit = 1; break; case 'r': done = 1; break; case 'a': exit(0); } } else { printf("Is it %s%s? [ynqar] ", getart(nodeptr->txt), nodeptr->txt); gets(response); switch (response[0]) { case 'y': printf("Great!\n"); break; case 'n': nodeptr->lch=calloc(1, sizeof(struct node)); nodeptr->lch->txt = nodeptr->txt; nodeptr->lch->lch = NULL; nodeptr->lch->rch = NULL; nodeptr->rch=calloc(1, sizeof(struct node)); printf("What is it? "); gets(response); nodeptr->rch->txt=strdup(response); nodeptr->rch->lch = NULL; nodeptr->rch->rch = NULL; printf("Enter a question for which the answer for %s is yes, and for which %s is no: ", nodeptr->lch->txt, nodeptr->rch->txt); gets(response); if (response[strlen(response)-1] == '?') response[strlen(response)-1] = '\0'; nodeptr->txt = strdup(response); break; case 'q': quit = 1; break; case 'r': done = 1; break; case 'a': exit(0); } done = 1; } } #else quit=process(&rootptr); #endif } d80 1 d82 1 d87 6 a92 3 case 'y': return(process(&(*nodeptr_addr)->lch)); case 'n': return(process(&(*nodeptr_addr)->rch)); case 'q': return(1); d94 9 a102 1 case 'r': return(0); d109 3 a111 3 return(0); case 'r': return(0); case 'q': return(1); d116 1 a116 1 case 'q': return(1); d118 1 a118 1 case 'r': return(0); d123 1 a123 1 case 'q': return(1); d125 1 a125 1 case 'r': return(0); d133 1 d138 1 d140 2 a141 1 return(0); d148 1 a148 1 struct node *rootptr) d154 2 a155 2 if (rootptr->lch == NULL) fprintf(fp, "A %s\n", rootptr->txt); d157 3 a159 3 fprintf(fp, "Q %s\n", rootptr->txt); savefile(NULL, rootptr->lch); savefile(NULL, rootptr->rch); d165 1 a165 1 struct node **rootptr_addr) d169 1 d174 1 a174 1 return(1); d183 2 a184 2 *rootptr_addr = calloc(1, sizeof(struct node)); (*rootptr_addr)->txt = strdup(text+2); d186 3 a188 2 loadfile(NULL, &(*rootptr_addr)->lch); loadfile(NULL, &(*rootptr_addr)->rch); d190 3 a192 2 (*rootptr_addr)->lch = NULL; (*rootptr_addr)->rch = NULL; d198 2 @ 1.7 log @*** empty log message *** @ text @d2 1 a2 1 static char *animal_c_rcs_id = "$Id: animal.c,v 1.6 1997/10/05 19:49:40 alexis Exp $"; d73 1 a73 1 printf("%s? [ynqra] ", nodeptr->txt); d87 1 a87 1 printf("Is it %s%s? [ynqr] ", getart(nodeptr->txt), nodeptr->txt); d128 1 a128 1 char response[128]; d131 1 a131 1 printf("%s? [ynqra] ", (*nodeptr_addr)->txt); d134 3 a136 8 case 'y': process(&(*nodeptr_addr)->lch); break; case 'n': process(&(*nodeptr_addr)->rch); break; case 'q': quit = 1; break; case 'r': done = 1; break; d138 1 d141 35 a175 1 printf("leaf node reached, but not coded yet\n"); @ 1.6 log @*** empty log message *** @ text @d2 1 a2 1 static char *animal_c_rcs_id = "$Id: animal.c,v 1.5 1997/10/05 16:12:14 alexis Exp $"; d16 1 d69 2 d117 3 d123 24 @ 1.5 log @added 'abort' option which exits immediately (without saving) @ text @d2 1 a2 1 static char *rcs_id = "$Id: animal.c,v 1.4 1997/10/05 15:01:09 alexis Exp alexis $"; d39 1 a39 1 version = version_init(rcs_id); d101 2 @ 1.4 log @datafile name required parameter - also used for 'Think of a XXXXX' @ text @d2 1 a2 1 static char *rcs_id = "$Id: animal.c,v 1.3 1997/10/04 10:11:02 alexis Exp alexis $"; d70 1 a70 1 printf("%s? [ynqr] ", nodeptr->txt); d80 2 d106 2 @ 1.3 log @*** empty log message *** @ text @d2 1 a2 1 static char *rcs_id = "$Id$"; d8 2 a9 1 #include /* for basename(), error(), ... */ d23 1 a23 1 fprintf(stderr, "Usage: %s\n", progname); d35 1 d37 2 a38 1 progname = basename(argv[0]); d47 5 d54 1 d59 3 d63 2 a64 6 loadfile(&rootptr); if (rootptr == NULL) { printf("database error: must have at least minimal tree\n"); exit(1); } d67 1 a67 1 printf("Think of an animal ... "); d82 1 a82 5 printf("Is it %s%s? [ynqr] ", (nodeptr->txt[0] >= 'A' && nodeptr->txt[0] <= 'Z') ? "" : (nodeptr->txt[0] == 'a' || nodeptr->txt[0] == 'e' || nodeptr->txt[0] == 'i' || nodeptr->txt[0] == 'o' || nodeptr->txt[0] == 'u') ? "an " : "a ", nodeptr->txt); d110 1 a110 1 savefile(rootptr); d114 1 d118 1 a118 1 if (fp == NULL && (fp=fopen("datafile", "w")) == NULL) d125 2 a126 2 savefile(rootptr->lch); savefile(rootptr->rch); d130 2 a131 1 loadfile( d137 4 a140 2 if (fp == NULL && (fp=fopen("datafile", "r")) == NULL) return; d152 2 a153 2 loadfile(&(*rootptr_addr)->lch); loadfile(&(*rootptr_addr)->rch); @ 1.2 log @lots of changes - principally, it's in english and it loads and saves data @ text @d1 9 a9 3 #include #include #include d17 13 a29 1 main() d35 15 d74 5 a78 1 printf("Is it a %s? [ynqr] ", nodeptr->txt); @ 1.1 log @Initial revision @ text @d7 2 a8 1 struct node *lch, *rch; a10 4 void processleaf(struct node **); void processnode(struct node **); void processnewleaf(struct node **); d13 11 a23 2 static struct node root = { "Slon", NULL, NULL }; struct node *rootptr; d25 42 a66 4 rootptr = &root; while (1) { printf("Predstav si nejake zviera ... "); processnode(&rootptr); d68 2 d72 2 a73 2 void processnode( struct node **rootptraddr) d75 2 a76 4 char response[10]; if ((*rootptraddr)->lch == NULL) { processleaf(rootptraddr); d78 7 a84 13 } while (1) { printf("%s ? ", (*rootptraddr)->txt); gets(response); switch (response[0]) { case 'a': processnode(&(*rootptraddr)->lch); return; case 'n': processnode(&(*rootptraddr)->rch); return; default: printf("prosim ta, len 'a' alebo 'n'\n"); break; } d88 2 a89 2 void processleaf( struct node **rootaddrptr) d91 2 a92 1 char response[10]; d94 2 d97 17 a113 43 while (1) { printf("Je to %s ? ", (*rootaddrptr)->txt); gets(response); switch (response[0]) { case 'a': printf("Mudry som hej ?\n\n"); return; case 'n': processnewleaf(rootaddrptr); return; default: printf("prosim ta, len 'a' alebo 'n'\n"); break; } } } void processnewleaf( struct node **rootaddrptr) { char response[120]; struct node *newnode, *tmpnode; printf("Tak, ja neviem, co je to ? "); gets(response); newnode = malloc(sizeof(struct node)); newnode->lch = NULL; newnode->rch = NULL; newnode->txt = (char *) malloc(strlen(response)+1); strcpy(newnode->txt, response); printf("Prosim ta pis otazku ktora rozdeli medzi %s a %s\n", (*rootaddrptr)->txt, newnode->txt); printf(" Odpoved pre %s musi byt ano a pre %s musi byt nie\n", (*rootaddrptr)->txt, newnode->txt); printf(" Nepis otaznik\n"); printf(" Tvoja otazka je: "); gets(response); tmpnode = *rootaddrptr; *rootaddrptr = malloc(sizeof(struct node)); (*rootaddrptr)->txt = malloc(strlen(response)+1); strcpy((*rootaddrptr)->txt, response); (*rootaddrptr)->lch = tmpnode; (*rootaddrptr)->rch = newnode; d115 2 a116 1 printf("Dik. Bol som mudry, teraz som mudrejsi\n\n"); @