; $Id: tdef.tf,v 1.18 1998/04/09 22:40:26 dmoore Exp $ ; v1.2 ; *** Requires tf4.0a2 or later to use. *** ; ; dmoore@ucsd.edu ;;; Structure of this file: ;;; 1. General usage instructions. ;;; 2. Internal macros, need not be read. ;;; 3. Default settings, you may want to look at. ;;; Section 1: General usage instructions. ;; You too can be like Julia, Colin, Gloria, Newt, OliverJones! ;; Pretend to be a Mas-Neotek robot in your spare time. ;; Just do something like this: ; /tdef -mglob -t'snausages*' snausages = /reply Yams!!! ; ;; Then you do the following "right" things: ; ; Rosminah says, "Snausages." ; You say, "Yams!!!" <- respond with 'say' ; ; Ben whispers, "Snausages taste good." ; You whisper, "Yams!!!" to Ben. <- respond with 'whisper' ; ; Hawkeye pages from Evil Patio: "snausages!" ; You page, "Yams!!!" to Hawkeye. <- respond with 'page' ; (see also: /help input) ; ; Codrus says, "What are snausages?" ; <- no response! ;; More complex example: ; /tdef -t'[Ww]hat time is it' current_time =\ ; /let time=$(/time \%I:\%M \%p \(\%Z\))%;\ ; /reply :thinks it's about %{time}, %{trig_actor}. ; ;; Then you get: ; ; Mizue says, "Hmm, what time is it?" ; Smurf thinks it's about 7:27 PM (PDT), Mizue. ; ; (DragonMUD page style.) ; Dietz pages: What time is it, d00d? ; Dietz senses that Smurf thinks it's about 7:27 PM (PDT), Dietz. ;; %{trig_actor} is the person who started the message. ;; %{trig_body} is the meat of the message (ie usually the part in ""). ;; %{trig_all} is the entire original line. ;; %{trig_class} lets you know what kind of message it was. ;; Use the macro '/reply' in your trigger body to respond. ;; It will be set to the correct method of responding. ;; Example of these variables: ; /tdef -mglob -t'snausages*' snausages = /reply Yams!!! ; ;; Rosminah says, "Snausages." ; trig_actor = Rosminah ; trig_body = Snausages. ; trig_all = Rosminah says, "Snausages." ; trig_class = public-say-local-builtin ; reply = /tdef_say_pose_reply %* ; ;; Ben whispers, "Snausages taste good." ; trig_actor = Ben ; trig_body = Snausages taste good. ; trig_all = Ben whispers, "Snausages taste good." ; trig_class = private-say-local-builtin ; reply = /send whisper Ben=%* ; ;; Hawkeye pages from Evil Patio: "snausages!" ; trig_actor = Hawkeye ; trig_body = snausages! ; trig_all = Hawkeye pages from Evil Patio: "snausages!" ; trig_class = private-say-remote-builtin ; reply = /send page Hawkeye=%* ; ;; Note: -mregexp is default ;; You can use () and %1, %*, %Pn subs in your patterns exactly as you want. ;; Your /tdef trigger pattern is compared against the main message (ie. ;; the same info in %{trig_body}). ;; Example of %Pn subs and setting up seperate local/remote responses. ; /tdef_local -t'^Smurf.*give ([^ ]*) (pennies|money|crowns)' pennies =\ ; /let who=%P1%;\ ; /if (who =/ "{me|us}") \ ; /let who=%{trig_actor}%;\ ; /endif%;\ ; /let amount=$[rand(35,45)]%;\ ; give %{who} = %{amount}%;\ ; /reply :gives %{who} %{amount} %P2. ; ; /tdef_remote -t'give ([^ ]*) (pennies|money|crowns)' pennies_2 =\ ; /reply Speak up, I can't hear you!%;\ ; /reply Maybe you should come here. ; ;; ; Druid says, "Smurf, give me pennies!" ; You give 37 pennies to Druid. ; Smurf gives Druid 37 pennies. ; ; Kyosuke pages from Fishbowl: "Smurf, give Storm pennies!" ; You page, "Speak up, I can't hear you!" to Kyosuke. ; You page, "Maybe you should come here." to Kyosuke. ; ;; Obviously this example doesn't check the validity of names, etc. ;;; Tdef trigger classes: ;;; display-form-location-userdefined ;;; display = private/public ;;; form = pose/say ;;; location = remote/local ;;; userdefined = builtin/anything you want ;;; Section 2: Internal macros, need not be read. ;;; Name space information: ;; User callable macros: ; tdef, untdef, tdef_pose, tdef_nopose, tdef_private, tdef_public, ; tdef_remote, tdef_local, tdef_say_pose_reply, tdef_add_pattern, ; reply (note that reply is also an ancient compat macro in stdlib.tf) ;; User definable macros: ; tdef_hook_* ;; User readable variables: ; trig_body, trig_actor, trig_all, trig_class ;; User settable variables: ; tdef_default_*, tdef_oj_time_hilite ;; Internal macros: ; tdef_pat_*, tdef_trig_*, other tdef_*. ;; Internal variables: (worst case you get a global shadow warning) ; opt_other, opt_*, name, body, wn /~loaded tdef.tf ;;; Note: -E allows you to provide an expression which must be true ;;; for the trigger to proceed. You probably want to check something ;;; that you've set in tdef_hook_before_trigger. /def -i tdef =\ /let opt_C=-default-%;\ /let opt_t=%;\ /let opt_i=0%;\ /let opt_q=0%;\ /let opt_F=0%;\ /let opt_m=regexp%;\ /let opt_p=1%;\ /let opt_c=100%;\ /let opt_n=0%;\ /let opt_w=%;\ /let opt_T=%;\ /let opt_E=%;\ /if (!getopts("iqFC:t:m:p:c:n:w:T:E:")) /break%;/endif%;\ /split %{*}%;\ /let name=%{P1}%;\ /let body=%{P2}%;\ /if (opt_C =~ "") \ /echo No tdef class. (-C)%;\ /break%;\ /endif%;\ /if (opt_t =~ "") \ /echo No trigger pattern. (-t)%;\ /break%;\ /endif%;\ /if (name =~ "") \ /echo Missing trigger name.%;\ /break%;\ /endif%;\ /if (strchr(name, " ") != -1) \ /echo Invalid trigger name: %{name}.%;\ /break%;\ /endif%;\ /if (body =~ "") \ /echo No trigger body. (= )%;\ /break%;\ /endif%;\ /: Ok, done checking all of the args. Now build everything up. %;\ /let opt_t=$(/escape ' %{opt_t})%;\ /if (opt_C =~ "-default-") \ /let opt_C=tdef_default_class%;\ /else \ /let opt_C='$(/escape ' %{opt_C})'%;\ /endif%;\ /if (opt_i) \ /let opt_other=-i%;\ /else \ /let opt_other=%;\ /endif%;\ /if (opt_F) \ /let tdef_fallthru=/:%;\ /else \ /let tdef_fallthru=/set tdef_already_matched=1%;\ /endif%;\ /if (opt_q) \ /let tdef_background=/:%;\ /else \ /let tdef_background=/tdef_background_handler%;\ /endif%;\ /let tdef_ck=(!tdef_already_matched)&(trig_class =/ %{opt_C})%;\ /if (opt_w !~ "") \ /let tdef_ck=%{tdef_ck}&(\${world_name} =~ '$(/escape ' %{opt_w})')%;\ /endif%;\ /if (opt_T !~ "") \ /let tdef_ck=%{tdef_ck}&(\${world_type} =/ '$(/escape ' %{opt_T})')%;\ /endif%;\ /if (opt_E !~ "") \ /let tdef_ck=%{tdef_ck}&(%{opt_E})%;\ /endif%;\ /def -wTDEF -F %{opt_other} -m%{opt_m} -p%{opt_p} -c%{opt_c} -n%{opt_n} -t'%{opt_t}' tdef_trig_%{name} =\ /if (%{tdef_ck}) \ %{tdef_fallthru}%%;\ %{tdef_background}%%;\ %{body}%%;\ /endif /def -i untdef = /undef tdef_trig_%1 /set tdef_class_pose={[^-]*-pose-[^-]*-*} /set tdef_class_nopose={[^-]*-say-[^-]*-*} /set tdef_class_private={private-[^-]*-[^-]*-*} /set tdef_class_public={public-[^-]*-[^-]*-*} /set tdef_class_remote={[^-]*-[^-]*-remote-*} /set tdef_class_local={[^-]*-[^-]*-local-*} /def -i tdef_pose = /tdef -C'%{tdef_class_pose}' %* /def -i tdef_nopose = /tdef -C'%{tdef_class_nopose}' %* /def -i tdef_private = /tdef -C'%{tdef_class_private}' %* /def -i tdef_public = /tdef -C'%{tdef_class_public}' %* /def -i tdef_remote = /tdef -C'%{tdef_class_remote}' %* /def -i tdef_local = /tdef -C'%{tdef_class_local}' %* ;;; #### when /trigger -hBACKGROUND shows the default message ;;; then echo can be replaced by it. /def -i tdef_background_handler =\ /if (!tdef_already_background_message) \ /set tdef_already_background_message=1%;\ /if (fg_world() !~ ${world_name}) \ /echo \% Trigger in world ${world_name}%;\ /endif%;\ /endif /def -i tdef_add_pattern =\ /let opt_F=0%;\ /let opt_q=0%;\ /let opt_t=%;\ /let opt_C=%;\ /let opt_A=%;\ /let opt_B=%;\ /let opt_a=%;\ /let opt_p=10%;\ /let opt_w=%;\ /let opt_T=%;\ /let opt_P=%;\ /if (!getopts("Fqt:C:A:B:a:p:w:T:P:")) /break%;/endif%;\ /split %{*}%;\ /let name=%{P1}%;\ /let body=%{P2}%;\ /if (opt_t =~ "") \ /echo No trigger pattern. (-t)%;\ /break%;\ /endif%;\ /if (opt_C =~ "") \ /echo No tdef class. (-C)%;\ /break%;\ /endif%;\ /if (opt_A =~ "") \ /echo No selector for trig_actor. (-A)%;\ /break%;\ /endif%;\ /if (opt_B =~ "") \ /echo No selector for trig_body. (-B)%;\ /break%;\ /endif%;\ /if (name =~ "") \ /echo Missing pattern name.%;\ /break%;\ /endif%;\ /if (strchr(name, " ") != -1) \ /echo Invalid pattern name: %{name}.%;\ /break%;\ /endif%;\ /if (body =~ "") \ /echo No reply function given. (= )%;\ /break%;\ /endif%;\ /: Ok, done checking all of the args. Now build everything up. %;\ /if (opt_a =~ "h" & tdef_oj_time_hilite) \ /let opt_other=-aGg%;\ /let tdef_hilite=/echo -w\${world_name} -a%{opt_a} -- \%* [\$(/time)]%;\ /let opt_a=%;\ /else \ /let opt_other=%;\ /let tdef_hilite=/:%;\ /endif%;\ /if (opt_q) \ /let tdef_background=/:%;\ /else \ /let tdef_background=/tdef_background_handler%;\ /endif%;\ /let opt_t=$(/escape ' %{opt_t})%;\ /if (opt_a !~ "") \ /let opt_other=%{opt_other} -a%{opt_a}%;\ /endif%;\ /if (opt_F) \ /let opt_other=%{opt_other} -F%;\ /endif%;\ /if (opt_w !~ "") \ /let opt_other=%{opt_other} -w%{opt_w}%;\ /endif%;\ /if (opt_T !~ "") \ /let opt_other=%{opt_other} -T%{opt_T}%;\ /endif%;\ /if (opt_P !~ "") \ /let opt_other=%{opt_other} -P%{opt_P}%;\ /endif%;\ /def -i -q -mregexp %{opt_other} -p%{opt_p} -t'%{opt_t}' tdef_pat_%{name} =\ /set tdef_already_background_message=0%%;\ %{tdef_background}%%;\ %{tdef_hilite}%%;\ /set trig_all=\%*%%;\ /edit -i reply=%{body}%%;\ /tdef_handle %{opt_C} %{opt_A} %{opt_B} ;;; Initial simple version of /trigger for tdef, doesn't support -w, -T, -C ;;; which it probably should?? Maybe also support setting the actor? /def -i ttrigger =\ /set tdef_already_background_message=0%%;\ /set trig_all=Internal says, "%*"%;\ /edit -i reply=/echo TDEF> %%*%;\ /tdef_handle public-say-local-builtin Internal %* ;;; FIX FIX FIX: can't I use /let instead of /set here? Or do /let's not ;;; make it through a /trigger? /def -i tdef_handle =\ /set trig_class=%1%;\ /set trig_actor=%2%;\ /set trig_body=%-2%;\ /tdef_hook_before_trigger%;\ /set tdef_already_matched=0%;\ /trigger -wTDEF -- %{trig_body} /addworld TDEF localhost echo /histsize -wTDEF 10 ;; On every line from the mud, we redefine the /reply macro to be the ;; means of communicating back with that person. /if /ismacro reply%;/then \ /undef reply%;\ /endif /def -i reply = /echo \% Initial setting for /reply: %* /def -i tdef_say_pose_reply =\ /if ({1} =/ ":*") \ /send -- %*%;\ /else \ /send -- say %*%;\ /endif /def tdef_isvar = /listvar -s %{*-@} %| /return %? /def tdef-set-default = /if /!tdef_isvar -m0 %1%;/then /set %1=%{-1}%;/endif /def tdef-def-default = /if /!ismacro -m0 %1%;/then /def %1=%{-1}%;/endif ;;; Section 3: Default settings, you may want to look at. ;;; The normal default is to accept anything except local poses. /tdef-set-default tdef_default_class {[^-]*-say-local-*|[^-]*-[^-]*-remote-*} ;;; If tdef_oj_time_hilite is true, then incoming pages and whispers ;;; will be hilited and have the current time placed on the end. ;;; However, it doesn't work if you want partial hilites on these ;;; messages. /tdef-set-default tdef_oj_time_hilite 0 ;;; tdef_hook_before_trigger is called after trig_actor, trig_body, and ;;; reply are setup, but before any attempt is done to call the ''real'' ;;; trigger. It will be called on any line which matches any of ;;; the basic tdef patterns, whether or not a specific match exists. ;;; FIX FIX FIX: true?: You can use this hook to change any of those items. /tdef-def-default tdef_hook_before_trigger /: empty tdef_hook_before_trigger ;;; Normal & french says & dragon mud broadcast. ;;; FIX FIX FIX: should dragon broadcast be remote? /tdef_add_pattern \ -t'^([^ ]*) (says?,? "|dits? <<)(.*)("|>>)( to everyone\\.)?$' \ -Cpublic-say-local-builtin \ -A'%P1' \ -B'%P3' \ -p10 \ -q \ builtin_1 = \ /tdef_say_pose_reply \%* ;;; Cavemuck thinknet say. /tdef_add_pattern \ -t'^([^ ]*) thinks,? "(.*)" on brainwave (.*)\\.$' \ -Cpublic-say-remote-builtin \ -A'%P1' \ -B'%P2' \ -p10 \ -q \ builtin_2 = \ /send think -out %P3%%;think \%* ;;; Cavemuck thinknet pose. /tdef_add_pattern \ -t'^([^ ]*) (.*) \\(on brainwave ([^)]*)\\)$' \ -Cpublic-pose-remote-builtin \ -A'%P1' \ -B'%P2' \ -p10 \ -q \ builtin_3 = \ /send think -out %P3%%;think \%* ;;; A page format. /tdef_add_pattern \ -t'^([^ ]*) pages from .*: "(.*)"$' \ -Cprivate-say-remote-builtin \ -A'%P1' \ -B'%P2' \ -p10 \ -ah \ builtin_4 = \ /send page %P1=\%* ;;; Another page format. /tdef_add_pattern \ -t'^([^ ]*) pages(,|:) (.*)$' \ -Cprivate-say-remote-builtin \ -A'%P1' \ -B'%P3' \ -p10 \ -ah \ builtin_5 = \ /send page %P1=\%* ;;; Yet another page. ;;; Must have priority higher than builtin_5. /tdef_add_pattern \ -t'^([^ ]*) pages(,|:) "(.*)"( to you.)?$' \ -Cprivate-say-remote-builtin \ -A'%P1' \ -B'%P3' \ -p11 \ -ah \ builtin_6 = \ /send page %P1=\%* ;; And another higher than builtin_5. /tdef_add_pattern \ -t'^([^ ]*) pages(,|:) (.*) $' \ -Cprivate-say-remote-builtin \ -A'%P1' \ -B'%P3' \ -p11 \ -ah \ builtin_7 = \ /send page %P1=\%* ;;; Page-pose format. dragon (& mufpage?) /tdef_add_pattern \ -t'^(In a page-pose to you,|You sense that) ([^ ]*) (.*)$' \ -Cprivate-pose-remote-builtin \ -A'%P2' \ -B'%P3' \ -p10 \ -ah \ builtin_8 = \ /send page %P2=\%* ;;; Whisper pattern. /tdef_add_pattern \ -t'^([^ ]*) whispers?,?:? "(.*)"( to you.)?$' \ -Cprivate-say-local-builtin \ -A'%P1' \ -B'%P2' \ -p10 \ -ah \ builtin_9 = \ /send whisper %P1=\%* ;;; Carinah sing pattern. /tdef_add_pattern \ -t'^([^ ]*) sings, o/~ (.*) ~\\\\o$' \ -Cpublic-say-local-builtin \ -A'%P1' \ -B'%P2' \ -p10 \ -q \ builtin_10 = \ /tdef_say_pose_reply \%* /undef tdef_isvar /undef tdef-set-default /undef tdef-def-default ;;; TO DO: ;;; The general matching triggers are at priority 10&11. This will let ;;; you stick some things below and above it as needed. ;;; FIX FIX FIX: how can anyone use a lower priority? (especially ;;; once poses are included) Should use fallthrus? ;;; FIX FIX FIX: Doesn't like people with space in their names. ;;; FIX FIX FIX: should /tdef default to -mregexp or not? ;;; Allow for /tdef -ah, and maybe others. This requires the pattern ;;; matchers to gag everything, and then a matching tdef to display it ;;; in the appropriate way, and then have the pattern display it ;;; normally if no one else has shown it. Or have each matcher ;;; contribute it's little piece of the -a, and then display it once ;;; afterwards. This would allow for -F -aG with -F -ah to work and ;;; stuff. Kind of a pain.