Planeshift

psnpcdialog.h

Go to the documentation of this file.
00001 /*
00002  * psnpcdialog.h
00003  *
00004  * Copyright (C) 2001 Atomic Blue ([email protected], http://www.atomicblue.org)
00005  *
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation (version 2 of the License)
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017  *
00018  *
00019  */
00020 #ifndef __PS_IMP_NPC_DIALOG__
00021 #define __PS_IMP_NPC_DIALOG__
00022 //=============================================================================
00023 // Crystal Space Includes
00024 //=============================================================================
00025 #include <cstypes.h>
00026 #include <iutil/comp.h>
00027 #include <iutil/eventh.h>
00028 #include <csutil/scf.h>
00029 #include <cstool/collider.h>
00030 #include <ivaria/collider.h>
00031 
00032 //=============================================================================
00033 // Project Includes
00034 //=============================================================================
00035 #include "util/psconst.h"
00036 #include "util/psstring.h"
00037 
00038 #include <idal.h>
00039 
00040 
00041 //=============================================================================
00042 // Local Includes
00043 //=============================================================================
00044 #include "dictionary.h"
00045 
00046 class gemNPC;
00047 class NPCDialogDict;
00048 class NpcResponse;
00049 class GemActor;
00050 class Client;
00051 
00052 struct iObjectRegistry;
00053 
00054 struct KnowledgeArea
00055 {
00056     csString area;
00057     int      priority;
00058 
00059     bool operator==(KnowledgeArea &other)
00060     {
00061         return (priority==other.priority && area == other.area);
00062     };
00063     bool operator<(KnowledgeArea &other)
00064     {
00065         if(priority<other.priority)
00066         {
00067             return true;
00068         }
00069         else if(priority>other.priority)
00070         {
00071             return false;
00072         }
00073         // Priority is equal so check area.
00074         if(strcmp(area,other.area)<0)
00075         {
00076             return true;
00077         }
00078         else
00079         {
00080             return false;
00081         }
00082     };
00083 };
00084 
00088 class NpcTriggerSentence
00089 {
00090 protected:
00091     csArray<NpcTerm*> terms;  
00092     csString str;             
00093 
00094 public:
00095     NpcTriggerSentence()  {};
00096     void AddToSentence(NpcTerm* next_word);
00097     size_t TermLength()
00098     {
00099         return terms.GetSize();
00100     }
00101     const csString &GetString();
00102     void operator=(NpcTriggerSentence &other)
00103     {
00104         terms = other.terms;
00105         str=other.str;
00106     }
00107     NpcTerm* &Term(size_t i)
00108     {
00109         return terms[i];
00110     }
00111 };
00112 
00113 
00119 class DialogHistory
00120 {
00121 protected:
00122     struct DialogHistoryEntry
00123     {
00124         int playerID;    
00125         int responseID;  
00126         csTicks when;    
00127     };
00128     csArray<DialogHistoryEntry> history;
00129     int counter;                          
00130 public:
00131     DialogHistory()
00132     {
00133         counter=0;
00134     }
00135 
00136     void AddToHistory(int playerID, int responseID, csTicks when);
00137     bool EverSaid(int playerID, int responseID, csTicks &howLongAgo, int &times);
00138 };
00139 #define MAX_HISTORY_LEN 100
00140 
00146 class psNPCDialog
00147 {
00148 protected:
00149     gemNPC* self;
00150     csArray<KnowledgeArea*> knowareas;
00151 
00152     psString antecedent_her,
00153              antecedent_him,
00154              antecedent_it,
00155              antecedent_them;
00156     iDataConnection* db;
00157     csRandomGen* randomgen;
00158     gemActor* currentplayer;
00159     Client* currentClient;
00160     DialogHistory dialogHistory;
00161 
00162     NpcResponse* FindResponse(csString &trigger,const char* text, int questID = -1);
00163     NpcResponse* FindResponseWithAllPrior(const char* area,const char* trigger, int questID = -1);
00164     bool CheckPronouns(psString &text);
00165     void UpdateAntecedents(NpcResponse* resp);
00166     void AddBadText(const char* text,const char* trigger);
00167 
00168 protected:
00169     void CleanPunctuation(psString &str, bool cleanQMark = true);
00170 
00175     void FilterKnownTerms(const psString &text, NpcTriggerSentence &trigger, Client* client);
00176 
00181     NpcResponse* FindOrGeneralizeTrigger(Client* client,NpcTriggerSentence &trigger,
00182                                          csArray<int> &gen_terms, int word);
00183 
00184 
00185     NpcResponse* ErrorResponse(const psString &text, const char* trigger);
00186     NpcResponse* RepeatedResponse(const psString &text, NpcResponse* resp, csTicks when, int times);
00187 
00188 public:
00189     psNPCDialog(gemNPC* npc);
00190     virtual ~psNPCDialog();
00191 
00192     bool Initialize(iDataConnection* db, PID npcID);
00193     bool Initialize(iDataConnection* db);
00194     bool LoadKnowledgeAreas(PID npcID);
00195 
00196     NpcResponse* Respond(const char* text,Client* client);
00197 
00198     NpcResponse* FindXMLResponse(Client* client, csString trigger, int questID = -1);
00199 
00200     bool AddWord(const char* word);
00201     bool AddSynonym(const char* word,const char* synonym);
00202     bool AddKnowledgeArea(const char* ka_name);
00203     bool AddResponse(const char* area,const char* words,const char* response,const char* minfaction);
00204     bool AssignNPCArea(const char* npcname,const char* areaname);
00205 
00206     void SubstituteKeywords(Client* player, csString &response) const;
00207 
00208 
00210     //    void AddNewTrigger( int databaseID );
00211 
00213     //    void AddNewResponse ( int databaseID );
00214 
00215     void DumpDialog();
00216 };
00217 
00218 class psDialogManager;
00219 
00220 class psTriggerBlock;
00221 class psAttitudeBlock;
00222 class psSpecialResponse;
00223 class psResponse;
00224 
00228 class psDialogManager
00229 {
00230 public:
00234     void AddTrigger(psTriggerBlock* trigger);
00235 
00239     void AddSpecialResponse(psSpecialResponse* response);
00240 
00244     void PrintInfo();
00245 
00252     csArray<psTriggerBlock*> triggers;
00253 
00254 
00261     csArray<psSpecialResponse*> special;
00262 
00271     int GetPriorID(int internalID);
00272 
00276     csArray<int> triggerIDs;
00277 
00281     csArray<int> responseIDs;
00282 
00283     csString    area;
00284 
00285     bool WriteToDatabase();
00286 
00287     int  InsertResponse(csString &response);
00288     int  InsertResponseSet(psResponse &response);
00289     int  InsertTrigger(const char* trigger, const char* area, int maxAttitude,
00290                        int minAttitude, int responseID, int priorID, int questID);
00291 };
00292 
00293 
00294 //--------------------------------------------------------------------------
00295 
00306 class psSpecialResponse
00307 {
00308 public:
00312     psSpecialResponse(csRef<iDocumentNode> responseNode, int questID);
00313 
00314     csString type;        
00315 
00316     csString response;    
00317 
00318     int attMin;           
00319 
00320     int attMax;           
00321 
00322     int questID;
00323 };
00324 
00325 
00326 //--------------------------------------------------------------------------
00327 
00336 class psTriggerBlock
00337 {
00338 public:
00339     psTriggerBlock(psDialogManager* mgr)
00340     {
00341         manager = mgr;
00342         priorResponseID = 0;
00343         questID = -1;
00344     }
00345 
00351     csStringArray phraseList;
00352 
00358     csArray<psAttitudeBlock*> attitudes;
00359 
00360     psTriggerBlock()
00361     {
00362         priorResponseID = 0;
00363     }
00364 
00368     void Create(csRef<iDocumentNode> triggerNode, int questID);
00369 
00373     void SetPrior(int id)
00374     {
00375         priorResponseID = id;
00376     }
00377 
00378     int priorResponseID;              
00379 
00380     int databaseID;                   
00381 
00382     csString area;                    
00383 
00384     psDialogManager* manager;         
00385 
00386     int questID;                      
00387 };
00388 
00389 
00390 //--------------------------------------------------------------------------
00391 
00395 class psResponse
00396 {
00397 public:
00404     csStringArray responses;
00405 
00406     csString script;
00407     csString pronoun_him,
00408              pronoun_her,
00409              pronoun_it,
00410              pronoun_them;
00411 
00412     int givenID;              
00413 
00414     int databaseID;           
00415 
00416     int questID;              
00417 
00418 };
00419 
00420 
00421 //--------------------------------------------------------------------------
00422 
00429 class psAttitudeBlock
00430 {
00431 public:
00432     static int responseID;    
00433 
00434     psAttitudeBlock(psDialogManager* mgr)
00435     {
00436         manager = mgr;
00437         responseSet.givenID = ++responseID;
00438     }
00439 
00440     psResponse responseSet;    
00441 
00445     void Create(csRef<iDocumentNode> attitudeNode, int questID);
00446 
00447     int maxAttitude;           
00448 
00449     int minAttitude;           
00450 
00451     psDialogManager* manager;  
00452 };
00453 
00454 #endif
00455 
00456 
00457