@q @program findwho.muf 1 9999 d i ( findwho.muf v1.0 Jessy @ FurryMUCK 2/01 A who/WHO utility that allows filtering by species or other prop. INSTALLATION: Port the program and link a global exit with a name such as 'who' to it. USE: who ....................... List online players in current room who #all .................. List all online players who #find ................. Display info on #find option who #find <species> ....... List online <species> players who #find <prop>=<val> .... List online players with <prop> of <val> who #info <string> ........ Set your entry for the Info column who #info ................. Clear your entry for the Info column who #prop <prop> .......... Allow filter searches for <prop> [Wiz] who #!prop <prop> ......... Disallow filter searches for <prop> [Wiz] Filtering or searching by the 'species' prop is always allowed. Other props must be explicitly enabled by a wiz. findwho.muf may be freely ported, copied, or modified. Please comment any changes. ) (2345678901234567890123456789012345678901234567890123456789012345678901) lvar ourArg (* str: cmd arg *) lvar ourBoo (* int: 0|1 *) lvar ourCon (* int: connection number *) lvar ourObj (* dbref: player|puppet *) lvar ourOpt (* str: cmd #option *) lvar ourStr (* str: workspace var *) lvar ourVal (* str: workspaece var *) $define Tell me @ swap notify $enddef $define NukeStack begin depth while pop repeat $enddef : DoHeader ( -- ) (* display column heads *) "Player Sex Species Info" Tell "-----------------------------------------------------------------------------" Tell ; : DoSortStrings-r ( s ... s' i -- s .... s' ) (* bubble sort range of strings, reverse order *) dup begin (* begin outer loop *) dup while (* iterate as many times as items in range *) over begin (* begin inner loop *) dup 1 > while (* iterate up through range *) dup 3 + pick over 3 + pick over over strcmp 0 > if (* compare; swap if necesarry *) swap then 3 pick 3 + put (* put sorted pair back in place *) over 3 + put 1 - (* decrement inner loop *) repeat (* end inner loop *) pop (* pop inner loop counter *) 1 - (* decrement outer loop *) repeat (* end outer loop *) pop pop (* pop outer loop counter and range indicator *) ; : DoSortStrings ( s ... s' i -- s .... s' ) (* bubble sort range of strings *) dup begin (* begin outer loop *) dup while (* iterate as many times as items in range *) over begin (* begin inner loop *) dup 1 > while (* iterate up through range *) dup 3 + pick over 3 + pick over over strcmp 0 < if (* compare; swap if necesarry *) swap then 3 pick 3 + put (* put sorted pair back in place *) over 3 + put 1 - (* decrement inner loop *) repeat (* end inner loop *) pop (* pop inner loop counter *) 1 - (* decrement outer loop *) repeat (* end outer loop *) pop pop (* pop outer loop counter and range indicator *) ; : DoPad ( s i -- s' ) (* pad string s to i characters *) " " rot swap strcat swap strcut pop ; : remove_dir ( d s -- ) (* remove dir s from d; leave subdirs *) dup "*/" smatch not if "/" strcat then over over nextprop swap pop begin dup while over over nextprop 3 pick rot "" setprop repeat pop pop ; : 3-col ( {rng} i -- ) (* output the i top things on the stack in 3 columns; top item on stack will be shown last *) dup 3 % (* fill to multiple of 3 *) dup 1 = if pop 2 + " " " " rot else dup 2 = if pop 1 + " " swap else pop then then (* get next 3; format; show *) begin (* begin get-next-three loop *) dup 3 > while dup 1 + rotate swap dup 1 + rotate swap dup 1 + rotate swap 4 rotate 24 DoPad 4 rotate 24 DoPad strcat 3 rotate 24 DoPad strcat " " swap strcat me @ swap notify 3 - repeat (* end get-next-three loop *) pop (* format and show last 3 *) rot 24 DoPad rot 24 DoPad strcat swap strcat " " swap strcat me @ swap notify ; : DoMakeLine ( d -- s ) (* format data line for player|puppet d *) dup name over player? if over descriptors dup not if pop "[asleep]" else 0 ourBoo ! begin dup while swap descrcon conidle 300 > if 1 ourBoo ! then 1 - repeat pop ourBoo @ if "[idle]" else "" then then else over owner name "[" swap strcat "]" strcat then strcat 22 DoPad over "sex" getpropstr dup not if pop "---" then strcat 34 DoPad over "species" getpropstr dup not if pop "---" then strcat 46 DoPad swap "_prefs/findwho/info" getpropstr strcat ; : DoHelp ( -- ) (* display help screen *) prog name "(#" strcat prog intostr strcat ")" strcat Tell " " Tell " %com ....................... List players & puppets in current room" command @ "%com" subst Tell " %com #all .................. List all online players" command @ "%com" subst Tell " %com #find ................. Display info on #find option" command @ "%com" subst Tell " %com #find <species> ....... List online <species> players" command @ "%com" subst Tell " %com #find <prop>=<val> .... List online players with <prop> of <val>" command @ "%com" subst Tell " %com #info ................. Clear your entry for the Info column" command @ "%com" subst Tell " %com #info <string> ........ Set your entry for the Info column" command @ "%com" subst Tell " %com #prop <prop> .......... Allow filter searches for <prop> (Wiz)" command @ "%com" subst Tell " %com #!prop <prop> ......... Disallow filter searches for <prop> (Wiz)" command @ "%com" subst Tell ; : DoSetInfo ( -- ) (* set or clear info entry *) "#info" ourArg @ stringpfx if me @ "_prefs/findwho/info" remove_prop ">> Info string cleared." Tell else me @ "_prefs/findwho/info" ourArg @ setprop ">> Info string set." Tell then ; : DoAllowProp ( -- ) (* add a prop to the 'allowed to search list *) me @ "W" flag? not if (* check permission *) "Permission denied." Tell exit then ourArg @ if ourArg @ "@*" smatch (* check and warn for wiz props *) ourArg @ "/@" instr or prog "W" flag? not and if ">> recommended." ">> NOTE: Allowing players to check the " "value of wiz-only props is *not*" strcat ">> for that property." ">> ERROR: This program must be set " "Wizard in order to allow searches" strcat Tell Tell Tell Tell else (* set prop *) prog "_props/" ourArg @ strcat "yes" setprop ">> Property set." then else (* show syntax if needed *) ">> Syntax: %cmd #prop <prop to allow searches for>" command @ "%cmd" subst Tell then ; : DoNoAllowProp ( -- ) (* remove a prop from the 'allowed' list *) me @ "W" flag? not if (* check permission *) "Permission denied." Tell exit then ourArg @ if (* remove prop *) prog "_props/" ourArg @ strcat remove_prop ">> Property removed." Tell else (* show syntax if needed *) ">> Syntax: %cmd #!prop <prop to disallow searches for>" command @ "%cmd" subst Tell then ; : DoShowFindInfo ( -- ) (* show syntax and config for #find option *) " " Tell (* show syntax (* show syntax info *) ">> Syntax: %cmd #find <prop>=<value>" command @ "%cmd" subst Tell ">> Example: %cmd #find species=mink" command @ "%cmd" subst Tell ">> This example would list all " "online players whose species is 'mink'." strcat command @ "%cmd" subst Tell ">> The value for <prop> defaults to 'species'." Tell ">> So, the above search could be abbreviated as '%cmd #find mink'" command @ "%cmd" subst Tell (* show current config *) prog "_props/" nextprop if ">> Currently, you may search for the following props:" Tell " " Tell NukeStack "species" prog "_props/" nextprop begin dup while dup "" "_props/" subst swap prog swap nextprop repeat pop depth DoSortStrings-r depth 3-col " " Tell else ">> Currently, you may only search " "for matches with the species prompt." strcat Tell " " Tell then ; : DoWhoFind ( -- ) (* list online players matching <prop>=<val> *) (* '<prop>=' defaults to 'species' *) "#find" ourArg @ stringpfx not if (* parse arg string *) ourArg @ "=" instr if ourArg @ dup "=" instr strcut strip ourVal ! strip dup strlen 1 - strcut pop strip ourStr ! else (* default to species prop *) ourArg @ ourVal ! "species" ourStr ! then ourStr @ "@*" smatch (* check for wiz-only props *) ourStr @ "/@" instr or prog "W" flag? not and if ">> Sorry, searches for the prop '%prop' are not allowed." ourStr @ "%prop" subst Tell exit then (* check: is it an allowed prop? *) ourStr @ "species" smatch not if prog "_props/" ourStr @ strcat getpropstr not if ">> Sorry, searches for the prop '%prop' are not allowed." ourStr @ "%prop" subst Tell exit then then NukeStack online (* put online players on stack *) begin dup while (* loop through stack, looking for prop matches *) swap dup ourStr @ getpropstr dup if ourVal @ smatch if depth -1 * rotate else pop then else pop pop then 1 - repeat pop depth if (* if we got any results, show them *) depth 1 = if (* quick 'n easy if only one match... *) DoHeader DoMakeLine Tell else (* otherwise store and display *) (* set a temp propdir holding results; it's faster than softcoded sorting *) "_tmp/%me/" me @ intostr "%me" subst ourStr ! prog ourStr @ remove_dir (* make sure it's empty *) depth begin (* loop through stack, recording data as props *) dup while swap DoMakeLine prog ourStr @ rot strcat "1" setprop 1 - repeat pop DoHeader (* start display with header *) prog ourStr @ nextprop begin (* loop through propdir, displaying *) dup while dup "" ourStr @ subst Tell prog swap nextprop repeat pop prog ourStr @ remove_dir (* remove temp dir *) then else (* ... unless, of course, we got no matches *) ">> Currently, no online players have a %prop value of '%val'." ourStr @ "%prop" subst ourVal @ "%val" subst Tell then else DoShowFindInfo then ; : DoWhoAll ( -- ) (* show formatted list of online players *) DoHeader (* show column headings *) NukeStack (* clear stack *) online (* put online players on stack *) dup 1 = if (* show and exit if only one *) pop DoMakeLine Tell else (* otherwise format, store results as propdir, then display *) "_tmp/%me/" me @ intostr "%me" subst ourStr ! prog ourStr @ remove_dir (* make sure data dir is empty *) begin dup while me @ 3 pick controls not (* honor dark flag *) 3 pick "D" flag? and if swap pop else swap DoMakeLine (* convert connections to formatted lines *) (* store lines as props for fast sorting *) prog ourStr @ rot strcat "1" setprop then 1 - repeat pop prog ourStr @ nextprop begin (* display props as program output *) dup while dup "" ourStr @ subst Tell prog swap nextprop repeat pop prog ourStr @ remove_dir (* remove propdir *) then ; : DoWhoHere ( -- ) (* show all players&puppets in current room *) 0 ourBoo ! me @ location "D" flag? if (* check: is room dark? *) me @ dup location controls if 1 ourBoo ! else "It's too dark to see who's here." Tell exit then then DoHeader NukeStack me @ location contents (* set up a propdir to hold results *) "_tmp/%me/" me @ intostr "%me" subst ourStr ! prog ourStr @ remove_dir (* make sure it's empty *) begin (* loop through objs in room *) dup while dup "D" flag? if (* honor dark flag on objs *) ourBoo @ not if me @ over not if next continue then then then dup player? if (* make display lines for player&pup objs present *) dup DoMakeLine prog ourStr @ rot strcat "1" setprop else dup thing? over "Z" flag? and if dup DoMakeLine prog ourStr @ rot strcat "1" setprop then then next repeat pop prog ourStr @ nextprop begin (* loop through propdir, displaying *) dup while dup "" ourStr @ subst Tell prog swap nextprop repeat pop prog ourStr @ remove_dir (* remove temp dir *) ; : main "me" match me ! (* make sure I'm me *) dup if dup ourArg ! "#" stringpfx if ourArg @ " " instr if ourArg @ dup " " instr strcut strip ourArg ! strip ourOpt ! else ourArg @ ourOpt ! then ourOpt @ if "#help" ourOpt @ stringpfx if DoHelp else "#all" ourOpt @ stringpfx if DoWhoAll else "#find" ourOpt @ stringpfx if DoWhoFind else "#info" ourOpt @ stringpfx if DoSetInfo else "#prop" ourOpt @ stringpfx if DoAllowProp else "#!prop" ourOpt @ stringpfx if DoNoAllowProp else ">> Command #option not understood." Tell ">> See %com #help for help." command @ "%com" subst Tell then then then then then then else DoWhoHere then then else DoWhoHere then ; . c q