AI-MegaHAL
view release on metacpan or search on metacpan
libmegahal.c view on Meta::CPAN
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Modified version
Alexandr Ciornii
Win32 (MSVC & gcc), FreeBSD, Mac Darwin compatibility
const'ing function parameters
Craig Andrews
void megahal_learn
*/
/*===========================================================================*/
/*
* $Id: megahal.c,v 1.6 2002/10/16 04:32:53 davidw Exp $
*
* File: megahal.c
*
* Program: MegaHAL
*
* Purpose: To simulate a natural language conversation with a psychotic
* computer. This is achieved by learning from the user's
* input using a third-order Markov model on the word level.
* Words are considered to be sequences of characters separated
* by whitespace and punctuation. Replies are generated
* randomly based on a keyword, and they are scored using
* measures of surprise.
*
* Author: Mr. Jason L. Hutchens (http://www.amristar.com.au/~hutch/)
*
* WWW: http://megahal.sourceforge.net
*
* Compilation Notes
* =================
*
* When compiling, be sure to link with the maths library so that the
* log() function can be found.
*
* On the Macintosh, add the library SpeechLib to your project. It is
* very important that you set the attributes to Import Weak. You can
* do this by selecting the lib and then use Project Inspector from the
* Window menu.
*
* CREDITS
* =======
*
* Amiga (AmigaOS)
* ---------------
* Dag Agren (dagren@ra.abo.fi)
*
* DEC (OSF)
* ---------
* Jason Hutchens (hutch@ciips.ee.uwa.edu.au)
*
* Macintosh
* ---------
* Paul Baxter (pbaxter@assistivetech.com)
* Doug Turner (dturner@best.com)
*
* PC (Linux)
* ----------
* Jason Hutchens (hutch@ciips.ee.uwa.edu.au)
*
* PC (OS/2)
* ---------
* Bjorn Karlowsky (?)
*
* PC (Windows 3.11)
* -----------------
* Jim Crawford (pfister_@hotmail.com)
*
* PC (Windows '95)
* ----------------
* Jason Hutchens (hutch@ciips.ee.uwa.edu.au)
*
* PPC (Linux)
* -----------
* Lucas Vergnettes (Lucasv@sdf.lonestar.org)
*
* SGI (Irix)
* ----------
* Jason Hutchens (hutch@ciips.ee.uwa.edu.au)
*
* Sun (SunOS)
* -----------
* Jason Hutchens (hutch@ciips.ee.uwa.edu.au)
*/
/*===========================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#ifndef _MSC_VER
#include <unistd.h>
//#include <getopt.h>
#endif
#if !defined(AMIGA) && !defined(__mac_os) && !defined(__FreeBSD__) && !defined(__APPLE__)
// FreeBSD malloc.h is empty and gives error
// Tested on FreeBSD 5.4
#include <malloc.h>
#endif
#include <string.h>
#include <signal.h>
#include <math.h>
#include <time.h>
#include <ctype.h>
#if defined(__mac_os)
#include <types.h>
#include <Speech.h>
#else
#include <sys/types.h>
#endif
#include "megahal.h"
#if defined(DEBUG)
#include "debug.h"
#endif
libmegahal.c view on Meta::CPAN
/*---------------------------------------------------------------------------*/
/*
* Function: Generate_Reply
*
* Purpose: Take a string of user input and return a string of output
* which may vaguely be construed as containing a reply to
* whatever is in the input string.
*/
char *generate_reply(MODEL *model, DICTIONARY *words)
{
static DICTIONARY *dummy=NULL;
DICTIONARY *replywords;
DICTIONARY *keywords;
float surprise;
float max_surprise;
char *output;
static char *output_none=NULL;
int count;
int basetime;
int timeout = TIMEOUT;
/*
* Create an array of keywords from the words in the user's input
*/
keywords=make_keywords(model, words);
/*
* Make sure some sort of reply exists
*/
if(output_none==NULL) {
output_none=malloc(40);
if(output_none!=NULL)
strcpy(output_none, "I don't know enough to answer you yet!");
}
output=output_none;
if(dummy == NULL) dummy = new_dictionary();
replywords = reply(model, dummy);
if(dissimilar(words, replywords) == TRUE) output = make_output(replywords);
/*
* Loop for the specified waiting period, generating and evaluating
* replies
*/
max_surprise=(float)-1.0;
count=0;
basetime=time(NULL);
/* progress("Generating reply", 0, 1); */
do {
replywords=reply(model, keywords);
surprise=evaluate_reply(model, keywords, replywords);
++count;
if((surprise>max_surprise)&&(dissimilar(words, replywords)==TRUE)) {
max_surprise=surprise;
output=make_output(replywords);
}
/* progress(NULL, (time(NULL)-basetime),timeout); */
} while((time(NULL)-basetime)<timeout);
progress(NULL, 1, 1);
/*
* Return the best answer we generated
*/
return(output);
}
/*---------------------------------------------------------------------------*/
/*
* Function: Dissimilar
*
* Purpose: Return TRUE or FALSE depending on whether the dictionaries
* are the same or not.
*/
bool dissimilar(DICTIONARY *words1, DICTIONARY *words2)
{
register int i;
if(words1->size!=words2->size) return(TRUE);
for(i=0; i<words1->size; ++i)
if(wordcmp(words1->entry[i], words2->entry[i])!=0) return(TRUE);
return(FALSE);
}
/*---------------------------------------------------------------------------*/
/*
* Function: Make_Keywords
*
* Purpose: Put all the interesting words from the user's input into
* a keywords dictionary, which will be used when generating
* a reply.
*/
DICTIONARY *make_keywords(MODEL *model, DICTIONARY *words)
{
static DICTIONARY *keys=NULL;
register int i;
register int j;
int c;
if(keys==NULL) keys=new_dictionary();
for(i=0; i<keys->size; ++i) free(keys->entry[i].word);
free_dictionary(keys);
for(i=0; i<words->size; ++i) {
/*
* Find the symbol ID of the word. If it doesn't exist in
* the model, or if it begins with a non-alphanumeric
* character, or if it is in the exclusion array, then
* skip over it.
*/
c=0;
for(j=0; j<swp->size; ++j)
if(wordcmp(swp->from[j], words->entry[i])==0) {
add_key(model, keys, swp->to[j]);
++c;
}
if(c==0) add_key(model, keys, words->entry[i]);
}
if(keys->size>0) for(i=0; i<words->size; ++i) {
( run in 2.308 seconds using v1.01-cache-2.11-cpan-98e64b0badf )