AI-MegaHAL
view release on metacpan or search on metacpan
libmegahal.c view on Meta::CPAN
#define isalnum(x) IsAlNum(_AmigaLocale,x)
#undef isdigit
#define isdigit(x) IsDigit(_AmigaLocale,x)
#undef isspace
#define isspace(x) IsSpace(_AmigaLocale,x)
#endif
#ifndef __mac_os
#undef FALSE
#undef TRUE
typedef enum { FALSE, TRUE } bool;
#endif
typedef struct {
BYTE1 length;
char *word;
} STRING;
typedef struct {
BYTE4 size;
STRING *entry;
BYTE2 *index;
} DICTIONARY;
typedef struct {
BYTE2 size;
STRING *from;
STRING *to;
} SWAP;
typedef struct NODE {
BYTE2 symbol;
BYTE4 usage;
BYTE2 count;
BYTE2 branch;
struct NODE **tree;
} TREE;
typedef struct {
BYTE1 order;
TREE *forward;
TREE *backward;
TREE **context;
DICTIONARY *dictionary;
} MODEL;
typedef enum { UNKNOWN, QUIT, EXIT, SAVE, DELAY, HELP, SPEECH, VOICELIST, VOICE, BRAIN, QUIET} COMMAND_WORDS;
typedef struct {
STRING word;
char *helpstring;
COMMAND_WORDS command;
} COMMAND;
/*===========================================================================*/
static int width=75;
static int order=5;
static bool typing_delay=FALSE;
static bool noprompt=FALSE;
static bool speech=FALSE;
static bool quiet=FALSE;
static bool nowrap=FALSE;
static bool nobanner=FALSE;
static char *errorfilename = "megahal.log";
static char *statusfilename = "megahal.txt";
static DICTIONARY *words=NULL;
static DICTIONARY *greets=NULL;
static MODEL *model=NULL;
static FILE *errorfp;
static FILE *statusfp;
static DICTIONARY *ban=NULL;
static DICTIONARY *aux=NULL;
static DICTIONARY *fin=NULL;
static DICTIONARY *grt=NULL;
static SWAP *swp=NULL;
static bool used_key;
static char *directory=NULL;
static char *last=NULL;
static COMMAND command[] = {
{ { 4, "QUIT" }, "quits the program and saves MegaHAL's brain", QUIT },
{ { 4, "EXIT" }, "exits the program *without* saving MegaHAL's brain", EXIT },
{ { 4, "SAVE" }, "saves the current MegaHAL brain", SAVE },
{ { 5, "DELAY" }, "toggles MegaHAL's typing delay (off by default)", DELAY },
{ { 6, "SPEECH" }, "toggles MegaHAL's speech (off by default)", SPEECH },
{ { 6, "VOICES" }, "list available voices for speech", VOICELIST },
{ { 5, "VOICE" }, "switches to voice specified", VOICE },
{ { 5, "BRAIN" }, "change to another MegaHAL personality", BRAIN },
{ { 4, "HELP" }, "displays this message", HELP },
{ { 5, "QUIET" }, "toggles MegaHAL's responses (on by default)",QUIET},
/*
{ { 5, "STATS" }, "Display stats", STATS},
{ { 5, "STATS-SESSION" }, "Display stats for this session only",STATS_SESSION},
{ { 5, "STATS-ALL" },"Display stats for the whole lifetime",STATS-ALL},
*/
};
#ifdef AMIGA
struct Locale *_AmigaLocale;
#endif
#ifdef __mac_os
Boolean gSpeechExists = false;
SpeechChannel gSpeechChannel = nil;
#endif
/* FIXME - these need to be static */
static void add_aux(MODEL *, DICTIONARY *, STRING);
static void add_key(MODEL *, DICTIONARY *, STRING);
static void add_node(TREE *, TREE *, int);
static void add_swap(SWAP *, char *, char *);
static TREE *add_symbol(TREE *, BYTE2);
static BYTE2 add_word(DICTIONARY *, STRING);
static int babble(MODEL *, DICTIONARY *, DICTIONARY *);
static bool boundary(char *, int);
libmegahal.c view on Meta::CPAN
static char *read_input(char *);
static void save_model(char *, MODEL *);
#ifdef __mac_os
static char *strdup(const char *);
#endif
static void upper(char *);
static void write_input(char *);
static void write_output(char *);
#if defined(DOS) || defined(__mac_os)
static void usleep(int);
#endif
#if defined(_MSC_VER) || defined(__MINGW32_VERSION)
#include <windows.h>
#define usleep(i) Sleep(i)
#endif
static char *format_output(char *);
static void free_dictionary(DICTIONARY *);
static void free_model(MODEL *);
static void free_tree(TREE *);
static void free_word(STRING);
static void free_words(DICTIONARY *);
static void initialize_context(MODEL *);
static void initialize_dictionary(DICTIONARY *);
static DICTIONARY *initialize_list(char *);
static SWAP *initialize_swap(char *);
static void load_dictionary(FILE *, DICTIONARY *);
static bool load_model(char *, MODEL *);
static void load_personality(MODEL **);
static void load_tree(FILE *, TREE *);
static void load_word(FILE *, DICTIONARY *);
static DICTIONARY *make_keywords(MODEL *, DICTIONARY *);
static char *make_output(DICTIONARY *);
static MODEL *new_model(int);
static TREE *new_node(void);
static SWAP *new_swap(void);
static bool print_header(FILE *);
static bool progress(char *, int, int);
static DICTIONARY *reply(MODEL *, DICTIONARY *);
static void save_dictionary(FILE *, DICTIONARY *);
static void save_tree(FILE *, TREE *);
static void save_word(FILE *, STRING);
static int search_dictionary(DICTIONARY *, STRING, bool *);
static int search_node(TREE *, int, bool *);
static int seed(MODEL *, DICTIONARY *);
static void show_dictionary(DICTIONARY *);
static void speak(char *);
static bool status(char *, ...);
static void train(MODEL *, char *);
static void typein(char);
static void update_context(MODEL *, int);
static void update_model(MODEL *, int);
static bool warn(char *, char *, ...);
static int wordcmp(STRING, STRING);
static bool word_exists(DICTIONARY *, STRING);
static int rnd(int);
/* Function: setnoprompt
Purpose: Set noprompt variable.
*/
void megahal_setnoprompt(void)
{
noprompt = TRUE;
}
void megahal_setnowrap (void)
{
nowrap = TRUE;
}
void megahal_setnobanner (void)
{
nobanner = TRUE;
}
void megahal_seterrorfile(char *filename)
{
errorfilename = filename;
}
void megahal_setstatusfile(char *filename)
{
statusfilename = filename;
}
/*
megahal_initialize --
Initialize various brains and files.
Results:
None.
*/
void megahal_initialize(void)
{
errorfp = stderr;
statusfp = stdout;
// initialize_error(errorfilename);
// initialize_status(statusfilename);
ignore(0);
#ifdef AMIGA
_AmigaLocale=OpenLocale(NULL);
#endif
#ifdef __mac_os
gSpeechExists = initialize_speech();
#endif
if(!nobanner)
fprintf(stdout,
"+------------------------------------------------------------------------+\n"
"| |\n"
"| # # ###### #### ## # # ## # |\n"
"| ## ## # # # # # # # # # # ### |\n"
"| # ## # ##### # # # ###### # # # # # |\n"
"| # # # # ### ###### # # ###### # # # ### |\n"
"| # # # # # # # # # # # # # # # # |\n"
"| # # ###### #### # # # # # # ###### # ###r6 |\n"
"| |\n"
"| Copyright(C) 1998 Jason Hutchens |\n"
"+------------------------------------------------------------------------+\n"
);
libmegahal.c view on Meta::CPAN
output = generate_reply(model, words);
capitalize(output);
return output;
}
/*
megahal_learn --
Take string as input and and learn with no output.
*/
void megahal_learn(char *input, int log)
{
if (log != 0)
write_input(input); /* log input if so desired */
upper(input);
make_words(input, words);
learn(model, words);
}
/*
megahal_initial_greeting --
This function returns an initial greeting. It can be used to start
Megahal conversations, but it isn't necessary.
*/
char *megahal_initial_greeting(void)
{
char *output;
make_greeting(greets);
output = generate_reply(model, greets);
return output;
}
/*
megahal_output --
This function pretty prints output.
Wrapper function to have things in the right namespace.
*/
void megahal_output(char *output)
{
if(!quiet)
write_output(output);
}
/*
megahal_input --
Get a string from stdin, using a prompt.
*/
char *megahal_input(char *prompt)
{
if (noprompt)
return read_input("");
else
return read_input(prompt);
}
/*
megahal_command --
Check to see if input is a megahal command, and if so, act upon it.
Returns 1 if it is a command, 0 if it is not.
*/
int megahal_command(char *input)
{
int position = 0;
char *output;
make_words(input,words);
switch(execute_command(words, &position)) {
case EXIT:
exithal();
break;
case QUIT:
save_model("megahal.brn", model);
exithal();
break;
case SAVE:
save_model("megahal.brn", model);
break;
case DELAY:
typing_delay=!typing_delay;
printf("MegaHAL typing is now %s.\n", typing_delay?"on":"off");
return 1;
case SPEECH:
speech=!speech;
printf("MegaHAL speech is now %s.\n", speech?"on":"off");
return 1;
case HELP:
help();
return 1;
case VOICELIST:
listvoices();
return 1;
case VOICE:
changevoice(words, position);
return 1;
case BRAIN:
change_personality(words, position, &model);
make_greeting(greets);
output=generate_reply(model, greets);
write_output(output);
return 1;
case QUIET:
quiet=!quiet;
return 1;
default:
return 0;
}
return 0;
}
libmegahal.c view on Meta::CPAN
* If there is only one word, then it can't be a command.
*/
*position=words->size+1;
if(words->size<=1) return(UNKNOWN);
/*
* Search through the word array. If a command prefix is found,
* then try to match the following word with a command word. If
* a match is found, then return a command identifier. If the
* Following word is a number, then change the judge. Otherwise,
* continue the search.
*/
for(i=0; i<words->size-1; ++i)
/*
* The command prefix was found.
*/
if(words->entry[i].word[words->entry[i].length - 1] == '#') {
/*
* Look for a command word.
*/
for(j = 0; j < COMMAND_SIZE; ++j)
if(wordcmp(command[j].word, words->entry[i + 1]) == 0) {
*position = i + 1;
return(command[j].command);
}
}
return(UNKNOWN);
}
/*---------------------------------------------------------------------------*/
/*
* Function: ExitHAL
*
* Purpose: Terminate the program.
*/
void exithal(void)
{
#ifdef __mac_os
/*
* Must be called because it does use some system memory
*/
if (gSpeechChannel) {
StopSpeech(gSpeechChannel);
DisposeSpeechChannel(gSpeechChannel);
gSpeechChannel = nil;
}
#endif
exit(0);
}
/*---------------------------------------------------------------------------*/
/*
* Function: Read_Input
*
* Purpose: Read an input string from the user.
*/
char *read_input(char *prompt)
{
static char *input=NULL;
bool finish;
int length;
int c;
/*
* Perform some initializations. The finish boolean variable is used
* to detect a double line-feed, while length contains the number of
* characters in the input string.
*/
finish=FALSE;
length=0;
if(input==NULL) {
input=(char *)malloc(sizeof(char));
if(input==NULL) {
error("read_input", "Unable to allocate the input string");
return(input);
}
}
/*
* Display the prompt to the user.
*/
fprintf(stdout, prompt);
fflush(stdout);
/*
* Loop forever, reading characters and putting them into the input
* string.
*/
while(TRUE) {
/*
* Read a single character from stdin.
*/
c=getc(stdin);
/*
* If the character is a line-feed, then set the finish variable
* to TRUE. If it already is TRUE, then this is a double line-feed,
* in which case we should exit. After a line-feed, display the
* prompt again, and set the character to the space character, as
* we don't permit linefeeds to appear in the input.
*/
if((char)(c)=='\n') {
if(finish==TRUE) break;
fprintf(stdout, prompt);
fflush(stdout);
finish=TRUE;
c=32;
} else {
finish=FALSE;
}
/*
* Re-allocate the input string so that it can hold one more
* character.
*/
++length;
input=(char *)realloc((char *)input,sizeof(char)*(length+1));
if(input==NULL) {
error("read_input", "Unable to re-allocate the input string");
return(NULL);
}
/*
* Add the character just read to the input string.
*/
input[length-1]=(char)c;
input[length]='\0';
}
while(isspace(input[length-1])) --length;
input[length]='\0';
/*
* We have finished, so return the input string.
*/
return(input);
}
/*---------------------------------------------------------------------------*/
/*
* Function: Initialize_Error
*
* Purpose: Close the current error file pointer, and open a new one.
*/
bool initialize_error(char *filename)
{
if(errorfp!=stderr) fclose(errorfp);
if(filename==NULL) return(TRUE);
errorfp = fopen(filename, "a");
if(errorfp==NULL) {
errorfp=stderr;
return(FALSE);
}
return(print_header(errorfp));
}
/*---------------------------------------------------------------------------*/
/*
* Function: Error
*
( run in 0.952 second using v1.01-cache-2.11-cpan-6aa56a78535 )