From f0b340ef3d24580f75903386c3b8b76111a67f72 Mon Sep 17 00:00:00 2001 From: "False.Genesis" Date: Wed, 17 Oct 2007 10:59:01 +0000 Subject: [PATCH] * finally fixed + enabled chatAI scripting! * added core funcs "bigger_eq/greater_eq, smaller_eq" in addition to "bigger/greater, smaller & equal" * added scripted func "lfind" - return position of element in a list. --- bin/scripts/__core_chatAI.def | 186 ++++++++++-------- bin/scripts/__core_list_extensions.def | 51 ++++- bin/scripts/chatAI_HelloWorld.def | 23 ++- src/Client/DefScript/DefScript.cpp | 3 + src/Client/DefScript/DefScript.h | 2 + src/Client/DefScript/DefScriptFunctions.cpp | 10 + .../DefScript/DefScriptListFunctions.cpp | 1 + 7 files changed, 182 insertions(+), 94 deletions(-) diff --git a/bin/scripts/__core_chatAI.def b/bin/scripts/__core_chatAI.def index ae54b98..5ac4423 100644 --- a/bin/scripts/__core_chatAI.def +++ b/bin/scripts/__core_chatAI.def @@ -9,83 +9,133 @@ // @3: channel name. empty string if the chat message was not sent in a channel (for example say, yell or whisper) //-------------------------------------------- -// not using this yet, still more or less bugged. add stuff manually if you relly need. -// processchatai,{${@0}},{${@1}},{${@2}},{${@3}} ${@def} +processchatai,{${@0}},{${@1}},{${@2}},{${@3}} ${@def} + +// ----------------------------------- +#script=FlushChatAI +#permission=255 +// ----------------------------------- +// purpose: remove all registered chat AI scripts. usable as command. +logdebug flushing chat AI scripts. +lclean #processchatai::pattern_list +lclean #processchatai::script_list +lclean #processchatai::cond_list +lclean #processchatai::register_list + +// ---------------------------------- +#script=DropChatAIScript +// ---------------------------------- +// purpose: drop all entries registered to call the script specified in @def +set,amount 0 +loop + set,pos ?{lfind,#processchatai::script_list,true ${@def}} + if ?{not ?{strlen ${pos}}} + exitloop + endif + set,what_sc ?{lerase,#processchatai::script_list ${pos}} + set,what_cond ?{lerase,#processchatai::cond_list ${pos}} + set,what_ptn ?{lerase,#processchatai::pattern_list ${pos}} + lerase,#processchatai::register_list ${pos} + logdetail Dropped ChatAI for script '${what_sc}', cond [${what_cond}], pattern [${what_ptn}] + add,amount 1 +endloop +unset what_sc +unset what_cond +unset what_ptn +unset pos +return ${amount} + + // ---------------------------------- #script=processchatai // ---------------------------------- -// purpose: iterate over registered AI scripts, test if the chat message matches the condition, -// and execute appropriate script with predefined arguments +// purpose: iterate over registered AI scripts, test if the chat message matches a given condition, +// and execute appropriate script with predefined arguments. +// returns: false if the incoming chatmessage was invalid, else true // TODO: get object name (player or creature) and pass it to the called scripts // filter out chat messages that came from us if ?{equal,${@myguid} ${@2}} - return false + return false endif // filter out CHAT_MSG_WHISPER_INFORM ("whisper to ... : blah blah") if ?{equal,${@0} 7} - logdebug -- chat is whisper inform, skipping - return false + return false endif -// split the msg into a list containing only words. remove special characters also. -lcsplit,wlist,{ !?,;.:-_\\/<>()[]"$=+&} ${@def} +set,msg ?{lowercase ${@def}} -logdebug JOIN: ?{ljoin,wlist +} +default,filter { !?,;.:-_\\/<>()[]"$=+&#'*~`´^°} + +// split the msg into a list containing only words. remove special characters also. +lcsplit,wlist,{${filter}} ${msg} // remove empty entries lclean,wlist -// obtain name of the language that was used -set,langname ?{GetSCPValue,lang,${@1} name} -default,langname UNK LANG -set,msg ?{lowercase ${@def}} +// obtain name of the language that was used +set,langname ?{GetSCPValue,language,${@1} name} +default,langname UNKNOWN + set,i 0 set,len ?{llen pattern_list} loop - if ?{equal,${i} ${len}} - exitloop - endif - - set,script ?{lindex,script_list ${i}} - set,cond ?{lindex,cond_list ${i}} - set,pattern ?{lindex,pattern_list ${i}} - - set,call false - - if ?{equal,NONE ${cond}} - set,call true - else - if ?{equal,ALL ${cond}} - set,call ?{lcontains_ext,{${pattern}},{ } ${msg}} - else - if ?{equal,EXACT ${cond}} - out ${pattern} - out ${msg} - set,call ?{equal,{${pattern}} ${msg}} - else - if ?{equal,EXACT_PARTIAL ${cond}} - set,call ?{strlen ?{strfind,{${pattern}} ${msg}}} - endif - endif - endif - endif - - if ${call} - logdebug DEBUG: ChatAI: calling script ${script}, condition ${cond} matched. - ${script},{${@0}},{${@1}},{${@2}},{${@3}},{${langname}} ${@def} - else - logdebug DEBUG: ChatAI: NOT called script ${script}, condition ${cond} not matched. - endif - - add,i 1 + if ?{equal,${i} ${len}} + exitloop + endif + + set,script ?{lindex,script_list ${i}} + set,cond ?{lindex,cond_list ${i}} + set,pattern ?{lindex,pattern_list ${i}} + + set,call false + + if ?{equal,NONE ${cond}} + set,call true + else + if ?{equal,ANY ${cond}} + set,call ?{lcontains_ext,wlist,{ } ${pattern}} + else + if ?{equal,EXACT ${cond}} + set,call ?{equal,{${pattern}} ${msg}} + else + if ?{equal,EXACT_PARTIAL ${cond}} + set,call ?{strlen ?{strfind,{${pattern}} ${msg}}} + else + if ?{equal,ALL ${cond}} + // split the pattern into a list, then get its size. the amount of words matching the pattern list must be + // equal or greater then the amount of words in the pattern list + lcsplit,tmpl,{${filter}} ${pattern} + lclean,tmpl + set,pattln ?{llen tmpl} + set,matched ?{lcontains_ext,wlist,{ } ${pattern}} + set,call ?{greater_eq,${matched} ${pattln}} + unset pattln + unset matched + ldelete tmpl + endif + endif + endif + endif + endif + + logdebug AI call: ${call} + + if ${call} + // logdebug DEBUG: ChatAI: calling script ${script}, condition ${cond} matched. + ${script},{${@0}},{${@1}},{${@2}},{${@3}},{${langname}} ${@def} + //else + // logdebug DEBUG: ChatAI: NOT called script ${script}, condition ${cond} not matched. + endif + + add,i 1 endloop @@ -105,7 +155,7 @@ return true // @0: script name that has to be called if the condition is matched // @1: condition. allowed values are: // ALL - the chat message must contain all words provided -// ANY - the chat message must contain any word provided -- NOT WORKING YET [didnt find the reason yet :( ]-- +// ANY - the chat message must contain any word provided // ALL_ORDER - same like all, but in the order provided -- NOT YET IMPLEMENTED // ALL_CONSECUTIVE - same like ALL_ORDER, but the words must follow exactly one after another -- NOT YET IMPLEMENTED // EXACT - the chat message must be exactly equal to the string supplied. @@ -114,8 +164,8 @@ return true // note that @def is not case sensitive! if ?{not ?{strlen ${@0}}} - logerror Script error: RegisterChatAIScript: no function defined (called by '${@caller}') - return false + logerror Script error: RegisterChatAIScript: no function defined (called by '${@caller}') + return false endif set,pattern ?{lowercase ${@def}} @@ -124,34 +174,16 @@ set,cond ?{uppercase ${@1}} default,cond NONE -if ?{isset [${@0};${pattern};${cond}]} - logdebug Chat AI script already registered. script: '${@0}', condition: ${cond}, pattern: '${@def}' - return false +if ?{lcontains,#processchatai::register_list {[${@0};${pattern};${cond}]}} + logdebug Chat AI script already registered. script: '${@0}', condition: ${cond}, pattern: '${@def}' + return false endif -if ?{strlen ?{strfind,ALL ${cond}}} - - set,lname ${@0}_pattern - lcsplit,{${lname}},{ } ${pattern} - if ?{not ?{llen ${lname}}} - logerror Script error: RegisterChatAIScript: pattern is empty, but required! (called by '${@caller}') - return false - endif - lpushback,#processchatai::pattern_list ${lname} - -else - - lpushback,#processchatai::pattern_list ${pattern} - -endif - +lpushback,#processchatai::pattern_list ${pattern} lpushback,#processchatai::script_list ${@0} lpushback,#processchatai::cond_list ${cond} +lpushback,#processchatai::register_list {[${@0};${pattern};${cond}]} -set,[${@0};${pattern};${cond}] - -logdetail Chat AI script registered. script: '${@0}', condition: ${cond}, pattern: '${@def}' [now ?{llen #processchatai::pattern_list} registered] +logdetail Chat AI script registered. script: '${@0}', condition: ${cond}, pattern: '${pattern}' [now ?{llen #processchatai::pattern_list} registered] return true - - \ No newline at end of file diff --git a/bin/scripts/__core_list_extensions.def b/bin/scripts/__core_list_extensions.def index 9f9ab0f..fe8c49c 100644 --- a/bin/scripts/__core_list_extensions.def +++ b/bin/scripts/__core_list_extensions.def @@ -34,7 +34,7 @@ return ${result} // ----------------------------------------- #script=lcontains_ext // ----------------------------------------- -// return true if any substring in @def matches any element in list @0. +// returns the amount of matched substrings of @def in list @0. // default delimiter is space, override with @1. // by default, any char in @1 serves as delimiter. // if you set @2 to true, the exact string @1 is used as delimiter (no default is set) @@ -57,15 +57,15 @@ ${engine},myl,{${delim}} ${@def} // list to check must at least contain 1 element if ?{not ?{llen ${l}}} - return + return 0 endif // and our pattern list must contain 1 element also if ?{not ?{llen myl}} - return + return 0 endif -set,result false +set,result 0 loop if ?{equal,${i} ?{llen ${l}}} @@ -79,14 +79,10 @@ loop endif set,myelem ?{lindex,myl ${j}} if ?{equal,{${elem}} ${myelem}} - set,result true - exitloop + add,result 1 endif add,j 1 endloop - if ${result} - exitloop - endif add,i 1 endloop @@ -101,3 +97,40 @@ unset delim return ${result} + +//-------------------------------------------- +#script=lfind +//-------------------------------------------- +// return the position of the first element matching @def +// @0: list name, @def: search string +// @1: ignore case? +// if nothing is found, return empty string + +set,i 0 +set,l ?{globname,{${@caller}} ${@0}} + +if ?{not ?{llen ${l}}} + return +endif + +set,result +loop + if ?{equal,${i} ?{llen ${l}}} + exitloop + endif + set,elem ?{lindex,{${l}} ${i}} + if ${@1} + set,eq ?{equal,{?{lowercase ${elem}}} ?{lowercase ${@def}}} + else + set,eq ?{equal,{${elem}} ${@def}} + endif + if ${eq} + set,result ${i} + exitloop + endif + add,i 1 +endloop +unset i +unset l +unset elem +return ${result} diff --git a/bin/scripts/chatAI_HelloWorld.def b/bin/scripts/chatAI_HelloWorld.def index e590c5d..175617f 100644 --- a/bin/scripts/chatAI_HelloWorld.def +++ b/bin/scripts/chatAI_HelloWorld.def @@ -7,21 +7,22 @@ // @3: channel name // @4: language name -#onload -// call us only if somebody says a text containing "hello" and "world" -RegisterChatAIScript,chat_ai_helloworld,EXACT hello world -#/onload - // --------------------------------------- #script=chat_ai_helloworld // --------------------------------------- +#onload +// call us only if somebody says a text containing "hello" and "world" +RegisterChatAIScript,{${@myname}},ALL hello world +set,counter 0 +#/onload + if ?{equal,${@0} 0} // say some stuff is the language that was used by the sender - say,${@1} Hello World! This is an example! + say,${@1} Hello World! This is an example! You used ${@4} language. else - // else shout back in our default language + // or shout back in our default language if ?{equal,${@0} 5} - yell Yah "Hello World!" is widely used to proof that something is working!! + yell Yah "Hello World!" is widely used to proof that something is working!! You used ${@4} language. else if ?{equal,${@0} 14} chan,{${@3}} Recieved a nice "Hello World" in channel ${@3} ;) @@ -29,4 +30,10 @@ else endif endif +add,counter 1 + +// after 5 times of calling this script, it might get annoying, drop it +if ?{greater_eq,${counter} 5} + DropChatAIScript ${@myname} +endif diff --git a/src/Client/DefScript/DefScript.cpp b/src/Client/DefScript/DefScript.cpp index fb6fa6d..d1b9817 100644 --- a/src/Client/DefScript/DefScript.cpp +++ b/src/Client/DefScript/DefScript.cpp @@ -105,11 +105,14 @@ void DefScriptPackage::_InitFunctions(void) AddFunc("removeevent",&DefScriptPackage::func_removeevent); AddFunc("abs",&DefScriptPackage::func_abs); AddFunc("greater",&DefScriptPackage::func_bigger); + AddFunc("greater_eq",&DefScriptPackage::func_bigger_eq); AddFunc("bigger",&DefScriptPackage::func_bigger); + AddFunc("bigger_eq",&DefScriptPackage::func_bigger_eq); AddFunc("equal",&DefScriptPackage::func_equal); AddFunc("isset",&DefScriptPackage::func_isset); AddFunc("not",&DefScriptPackage::func_not); AddFunc("smaller",&DefScriptPackage::func_smaller); + AddFunc("smaller_eq",&DefScriptPackage::func_smaller_eq); AddFunc("strlen",&DefScriptPackage::func_strlen); AddFunc("tohex",&DefScriptPackage::func_tohex); AddFunc("and",&DefScriptPackage::func_and); diff --git a/src/Client/DefScript/DefScript.h b/src/Client/DefScript/DefScript.h index 33e0000..81c8247 100644 --- a/src/Client/DefScript/DefScript.h +++ b/src/Client/DefScript/DefScript.h @@ -187,10 +187,12 @@ private: DefReturnResult func_removeevent(CmdSet&); DefReturnResult func_abs(CmdSet&); DefReturnResult func_bigger(CmdSet&); + DefReturnResult func_bigger_eq(CmdSet&); DefReturnResult func_equal(CmdSet&); DefReturnResult func_isset(CmdSet&); DefReturnResult func_not(CmdSet&); DefReturnResult func_smaller(CmdSet&); + DefReturnResult func_smaller_eq(CmdSet&); DefReturnResult func_strlen(CmdSet&); DefReturnResult func_tohex(CmdSet&); DefReturnResult func_and(CmdSet&); diff --git a/src/Client/DefScript/DefScriptFunctions.cpp b/src/Client/DefScript/DefScriptFunctions.cpp index c7afdb3..a135905 100644 --- a/src/Client/DefScript/DefScriptFunctions.cpp +++ b/src/Client/DefScript/DefScriptFunctions.cpp @@ -369,6 +369,16 @@ DefReturnResult DefScriptPackage::func_bigger(CmdSet& Set) return toNumber(Set.arg[0]) > toNumber(Set.defaultarg); } +DefReturnResult DefScriptPackage::func_smaller_eq(CmdSet& Set) +{ + return toNumber(Set.arg[0]) <= toNumber(Set.defaultarg); +} + +DefReturnResult DefScriptPackage::func_bigger_eq(CmdSet& Set) +{ + return toNumber(Set.arg[0]) >= toNumber(Set.defaultarg); +} + DefReturnResult DefScriptPackage::func_not(CmdSet& Set) { return !isTrue(Set.defaultarg); diff --git a/src/Client/DefScript/DefScriptListFunctions.cpp b/src/Client/DefScript/DefScriptListFunctions.cpp index 53bbe55..7e21575 100644 --- a/src/Client/DefScript/DefScriptListFunctions.cpp +++ b/src/Client/DefScript/DefScriptListFunctions.cpp @@ -239,6 +239,7 @@ DefReturnResult DefScriptPackage::func_lmclean(CmdSet& Set) return toString((uint64)r); } +// erase element at position @def, return erased element DefReturnResult DefScriptPackage::func_lerase(CmdSet& Set) { DefList *l = lists.GetNoCreate(_NormalizeVarName(Set.arg[0],Set.myname));