From: Andy D. <kha...@us...> - 2005-12-23 23:39:43
|
Update of /cvsroot/planeshift/planeshift/src/server/bulkobjects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4836/src/server/bulkobjects Modified Files: dictionary.cpp psnpcdialog.cpp dictionary.h psnpcdialog.h Log Message: Began use of wordnet in searching hypernyms when matching NPC speech triggers. Index: dictionary.cpp =================================================================== RCS file: /cvsroot/planeshift/planeshift/src/server/bulkobjects/dictionary.cpp,v retrieving revision 1.90 retrieving revision 1.91 diff -C2 -d -r1.90 -r1.91 *** dictionary.cpp 17 Dec 2005 05:29:53 -0000 1.90 --- dictionary.cpp 23 Dec 2005 23:39:34 -0000 1.91 *************** *** 24,27 **** --- 24,28 ---- #include <iutil/document.h> #include <csutil/xmltiny.h> + #include <wn.h> #include "../iserver/idal.h" *************** *** 48,51 **** --- 49,53 ---- #include "util/serverconsole.h" #include "util/mathscript.h" + NPCDialogDict *dict; *************** *** 63,66 **** --- 65,71 ---- bool NPCDialogDict::Initialize(iDataConnection *db) { + // Initialise WordNet + CS_ASSERT(wninit() == 0); + if (LoadDisallowedWords(db)) { *************** *** 117,122 **** if (npc_term) return npc_term; ! NpcTerm *newphrase = new NpcTerm; ! newphrase->term = term; phrases.Insert(newphrase,TREE_OWNS_DATA); // TRUE means tree owns data --- 122,126 ---- if (npc_term) return npc_term; ! NpcTerm *newphrase = new NpcTerm(term); phrases.Insert(newphrase,TREE_OWNS_DATA); // TRUE means tree owns data *************** *** 127,131 **** { Result result(db->Select("select word," ! " synonym_of, more_general" " from npc_synonyms")); --- 131,135 ---- { Result result(db->Select("select word," ! " synonym_of" " from npc_synonyms")); *************** *** 142,146 **** csString synonym_of(result[i]["synonym_of"]); - csString more_general(result[i]["more_general"]); if (synonym_of.Length()) --- 146,149 ---- *************** *** 148,161 **** term->synonym = AddTerm(synonym_of); } - if (more_general.Length()) - { - if (term->synonym) - { - Error4("NPC Synonym %s have more general = %s that will not be used because of synonym %s", - term->term.GetDataSafe(),more_general.GetDataSafe(), - term->synonym->term.GetDataSafe()); - } - term->moreGeneral = AddTerm(more_general); - } } --- 151,154 ---- *************** *** 192,197 **** } ! NpcTerm *found, key; ! key.term = word; found = phrases.Find(&key); --- 185,189 ---- } ! NpcTerm *found, key(word); found = phrases.Find(&key); *************** *** 209,214 **** { // add word ! found = new NpcTerm; ! found->term = word; // CPrintf(CON_DEBUG, "Adding %s.\n",(const char *)word); phrases.Insert(found,TREE_OWNS_DATA); --- 201,205 ---- { // add word ! found = new NpcTerm(word); // CPrintf(CON_DEBUG, "Adding %s.\n",(const char *)word); phrases.Insert(found,TREE_OWNS_DATA); *************** *** 346,351 **** NpcTerm * NPCDialogDict::FindTerm(const char *term) { ! NpcTerm key; ! key.term = term; key.term.Downcase(); return phrases.Find(&key); --- 337,341 ---- NpcTerm * NPCDialogDict::FindTerm(const char *term) { ! NpcTerm key(term); key.term.Downcase(); return phrases.Find(&key); *************** *** 356,360 **** NpcTerm * termRec = FindTerm(term); if (termRec == NULL) ! return NULL; if (termRec->synonym) return termRec->synonym; --- 346,357 ---- NpcTerm * termRec = FindTerm(term); if (termRec == NULL) ! { ! // If we don't have it and it is a noun, then add it! ! NpcTerm newTerm(term); ! if(newTerm.IsNoun()) ! termRec = AddTerm(term); ! ! return termRec; ! } if (termRec->synonym) return termRec->synonym; *************** *** 617,620 **** --- 614,666 ---- } + bool NpcTerm::IsNoun() + { + char* baseform = morphstr(const_cast<char *>(term.GetData()), NOUN); + + if(!baseform) + baseform = const_cast<char *>(term.GetData()); + + return in_wn(baseform, NOUN) != 0; + } + + const char* NpcTerm::GetHypernym(size_t depth) + { + if(hypernymSynNet == NULL) + hypernymSynNet = findtheinfo_ds(const_cast<char *>(term.GetData()), NOUN, -HYPERPTR, ALLSENSES); + + SynsetPtr current = hypernymSynNet; + + for(size_t i = 0; i<depth; i++) + { + if(current == NULL) + return NULL; + + current = current->ptrlist; + } + + if(current == NULL) + return NULL; + + return *current->words; + } + + size_t NpcTerm::GetHypernymDepth() + { + if(hypernymSynNet == NULL) + hypernymSynNet = findtheinfo_ds(const_cast<char*>(term.GetData()), NOUN, -HYPERPTR, ALLSENSES); + + SynsetPtr current = hypernymSynNet; + + size_t i = 0; + + while(current != NULL) + { + current = current->ptrlist; + i++; + } + + return i; + + } bool NpcTrigger::Load(iResultRow& row) Index: psnpcdialog.cpp =================================================================== RCS file: /cvsroot/planeshift/planeshift/src/server/bulkobjects/psnpcdialog.cpp,v retrieving revision 1.69 retrieving revision 1.70 diff -C2 -d -r1.69 -r1.70 *** psnpcdialog.cpp 23 Dec 2005 18:01:12 -0000 1.69 --- psnpcdialog.cpp 23 Dec 2005 23:39:34 -0000 1.70 *************** *** 64,68 **** #include "psraceinfo.h" - //---------------------------------------------------------------------------- --- 64,67 ---- *************** *** 89,105 **** } ! bool NpcTriggerSentence::GeneralizeTerm(NPCDialogDict *dict,size_t level) { ! if (level >= terms.Length()) return false; ! if (terms[level]->moreGeneral) ! { ! terms[level] = terms[level]->moreGeneral; ! str = ""; ! return true; ! } ! return false; } --- 88,99 ---- } ! const char* NpcTriggerSentence::GeneralizeTerm(NPCDialogDict *dict,size_t which, size_t depth) { ! if (which >= terms.Length()) return false; ! str = ""; ! return terms[which]->GetHypernym(depth); } *************** *** 429,477 **** } ! NpcResponse *psNPCDialog::FindOrGeneralizeTrigger(Client *client,NpcTriggerSentence& trigger,NpcTriggerSentence& generalized, ! const csArray<int>& gen_terms, size_t level) { NpcResponse *resp; ! if (level == gen_terms.Length()) { ! csString generalized_copy = generalized.GetString(); ! ! dict->CheckForTriggerGroup(generalized_copy); // substitute master trigger if this is child trigger in group ! ! resp = FindResponse( generalized_copy, trigger.GetString()); ! if (resp) { ! CPrintf(CON_DEBUG, "Found response to: '%s'\n", generalized.GetString().GetData()); ! ! // // Removed till we find a better way to manage repeated responses ! // // At the moment are annoying since you cannot restart the conversation from ! // // a certain point ! // int times; ! // csTicks when; ! // if (dialogHistory.EverSaid(client->GetPlayerID(), resp->id, when, times)) ! // { ! // return RepeatedResponse(trigger.GetString(), resp, when, times); ! // } ! // else ! // dialogHistory.AddToHistory(client->GetPlayerID(), resp->id, csGetTicks() ); ! ! return resp; // Found what we are looking for ! } ! } ! else ! { ! do ! { ! resp = FindOrGeneralizeTrigger(client,trigger,generalized,gen_terms,level+1); if (resp) return resp; // Found what we are looking for } ! while (generalized.GeneralizeTerm(dict,gen_terms[level])); ! ! // Reset term back to original so re-search covers term again ! generalized.Term(gen_terms[level]) = trigger.Term(gen_terms[level]); ! } return NULL; --- 423,489 ---- } ! NpcResponse *psNPCDialog::FindOrGeneralizeTrigger(Client *client,NpcTriggerSentence& trigger, ! const csArray<int>& gen_terms) { NpcResponse *resp; + csStringArray generalized; ! bool hit; ! ! // Perform breadth-first search on generalisations ! ! // Copy all terms into stringarray ! for(size_t i=0;i<trigger.TermLength();i++) ! generalized.Push(trigger.Term(i)->term); ! ! // We do at least one search with no generalisations ! size_t depth = 0; ! ! do { ! hit = false; ! ! for(size_t i=0;i<gen_terms.Length();i++) { ! const char* hypernym = trigger.Term(gen_terms[i])->GetHypernym(depth); ! if(hypernym) ! { ! generalized.Put(gen_terms[i],hypernym); ! hit = true; ! } ! ! csString generalized_copy; ! ! // Merge string ! for(size_t i=0;i<generalized.Length();i++) ! { ! generalized_copy.Append(generalized[i]); ! } ! dict->CheckForTriggerGroup(generalized_copy); // substitute master trigger if this is child trigger in group ! ! resp = FindResponse( generalized_copy, trigger.GetString()); if (resp) + { + CPrintf(CON_DEBUG, "Found response to: '%s'\n", generalized_copy.GetData()); + + // // Removed till we find a better way to manage repeated responses + // // At the moment are annoying since you cannot restart the conversation from + // // a certain point + // int times; + // csTicks when; + // if (dialogHistory.EverSaid(client->GetPlayerID(), resp->id, when, times)) + // { + // return RepeatedResponse(trigger.GetString(), resp, when, times); + // } + // else + // dialogHistory.AddToHistory(client->GetPlayerID(), resp->id, csGetTicks() ); + + return resp; // Found what we are looking for + } } ! depth++; ! } while (hit == true); return NULL; *************** *** 548,576 **** } ! // Replace known terms to get standard terms // eg. hello is replaced with gretting FilterKnownTerms(pstext, trigger); - - if (trigger.TermLength() == 0) - { - CPrintf(CON_DEBUG, "Failed filter known terms check\n"); - return ErrorResponse(pstext); - } - resp = NULL; generalized = trigger; csArray<int> gen_terms; // Cross ref to terms with generalization ! // Build cross ref to terms that have generalization. for (int i = 0; i < (int)generalized.TermLength(); i++) { ! if (generalized.Term(i)->moreGeneral) ! { gen_terms.Push(i); - } } ! resp = FindOrGeneralizeTrigger(client,trigger,generalized,gen_terms,0); if (resp == NULL) --- 560,579 ---- } ! // Replace custom known terms to get standard terms // eg. hello is replaced with gretting FilterKnownTerms(pstext, trigger); resp = NULL; generalized = trigger; csArray<int> gen_terms; // Cross ref to terms with generalization ! // Build cross ref to terms that have generalization (nouns). for (int i = 0; i < (int)generalized.TermLength(); i++) { ! if(generalized.Term(i)->IsNoun()) gen_terms.Push(i); } ! resp = FindOrGeneralizeTrigger(client,trigger,gen_terms); if (resp == NULL) Index: dictionary.h =================================================================== RCS file: /cvsroot/planeshift/planeshift/src/server/bulkobjects/dictionary.h,v retrieving revision 1.49 retrieving revision 1.50 diff -C2 -d -r1.49 -r1.50 *** dictionary.h 8 Dec 2005 19:22:14 -0000 1.49 --- dictionary.h 23 Dec 2005 23:39:34 -0000 1.50 *************** *** 31,34 **** --- 31,36 ---- #include "../server/iserver/idal.h" // Database Abstraction Layer Interface + #include <wn.h> + #define MAX_RESP 5 *************** *** 125,129 **** --- 127,134 ---- class NpcTerm { + + SynsetPtr hypernymSynNet; public: + /** * The recognized phrase/term *************** *** 141,163 **** NpcTerm* synonym; - /** - * Pointer to a more general term. - * - * If nonzero, it specifies more general phrase than this - * e.g. "apple" ---> "fruit". - * - * Phrases that have 'synonym' should have no 'moreGeneral' term, - * because 'moreGeneral' of their 'synonym' is used instead of it - */ - NpcTerm* moreGeneral; /** * Constructor for the term */ ! NpcTerm() { synonym = NULL; ! moreGeneral = NULL; } /** --- 146,169 ---- NpcTerm* synonym; /** * Constructor for the term */ ! NpcTerm(const char* term) { synonym = NULL; ! hypernymSynNet = NULL; ! this->term = term; } + ~NpcTerm() + { + if(hypernymSynNet) + free_syns(hypernymSynNet); + } + + const char* GetHypernym(size_t depth); + size_t GetHypernymDepth(); + + bool IsNoun(); /** Index: psnpcdialog.h =================================================================== RCS file: /cvsroot/planeshift/planeshift/src/server/bulkobjects/psnpcdialog.h,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** psnpcdialog.h 7 Dec 2005 21:23:42 -0000 1.23 --- psnpcdialog.h 23 Dec 2005 23:39:34 -0000 1.24 *************** *** 76,81 **** const csString& GetString(); void operator=(NpcTriggerSentence& other) { terms = other.terms; str=other.str; } ! NpcTerm*& Term(int i) { return terms[i]; } ! bool GeneralizeTerm(NPCDialogDict *dict,size_t level); }; --- 76,81 ---- const csString& GetString(); void operator=(NpcTriggerSentence& other) { terms = other.terms; str=other.str; } ! NpcTerm*& Term(size_t i) { return terms[i]; } ! const char* GeneralizeTerm(NPCDialogDict *dict,size_t which, size_t depth); }; *************** *** 145,150 **** */ NpcResponse *FindOrGeneralizeTrigger(Client *client,NpcTriggerSentence& trigger, ! NpcTriggerSentence& generalized, ! const csArray<int>& gen_terms, size_t level); NpcResponse * ErrorResponse(const psString & text); --- 145,150 ---- */ NpcResponse *FindOrGeneralizeTrigger(Client *client,NpcTriggerSentence& trigger, ! const csArray<int>& gen_terms); ! NpcResponse * ErrorResponse(const psString & text); |