@q
@program MultiGuest.muf
1 9999 d
i
( MultiGuest.muf    v1.1    Jessy @ FurryMUCK    4/97, 2/99
  
  A multi-guest program, intended to be simple to set up... by 
  comparison, at least.
  
  INSTALLATION:
  
  Port this program, and set it W. Port a copy of con-callmultiguest
  if you do not already have it, and set it W and L.

  Ensure that you have a do-nothing program installed and @registered
  as $nothing.
  
  Edit the GuestPassWd definition in the section below, making the pass-
  word something unique for your MUCK. If you want Guests to be called 
  something other than 'Guests', edit the GuestName and GuestNames 
  definitions as well.
)
  
(*** EDIT THESE DEFS AS NEEDED ***)
$def GuestPassWd "fl0b^art!"        (* password of the actual Guests *)
$def GuestName "Guest"               (* name string shared by guests *)
$def GuestNames "guests"                (* plural form of guest type *)
  
( Create an action and link it to this program. Type the action name.
  This creates the Guests, sets a few props on them and the program,
  puts con-callmultiguest in the the Guest _connect queue, and attaches
  do-nothing actions to the Guests, locking out commands that could be
  used to change the MUCK or the Guest characters.
  
  The Guests will be moved and linked to the room you're in when you
  do the installation, so it's a good idea to do it in what will be
  the Guest player start room.
  
  Note: the installation routine forces the wizard doing the
  installation to create the characters and actions and set properties.
  A wizard *other than* God needs to do the installation.
  
  Players will then be able to log on, using GuestName, all lower-case,
  as the password. Ex:
  
      connect guest guest      or,
      connect visitor visitor
  
  By default, eight Guests are created. If you want more or fewer, 
  supply the number desired as an argument to the action name.
  
  MultiGuest.muf should not be set Link_OK, in order to keep the
  Guest password confidential.
  
  If for some reason you need to reinstall the Guest set up, first
  @toad all previous Guests, and clear the @ver prop from this
  program.
  
  MultiGuest.muf may be freely ported. Please comment any changes.
)
  
lvar ourCounter                           (* s: loop-control counter *)
lvar ourGuest                     (* d: dbref of Guest to connect to *)
 
$def ourVersion "1.0"
 
: DoInstall ( [i] --  )(* creates an log-in character, and i Guest
                          characters. i defaults to 8. creates
                          do-nothing actions for un-Guestlike commands,
                          attached to the guests. registers this 
                          program and sets the log-in character's
                          _connect/multiguest prop to call 
                          con-callmultiguest.                        *)
    
    me @ "W" flag? not if
        "Permission denied." .tell exit
    then
              (* GOD_PRIV is most likely defined. God can't do this. *)
    me @ #1 dbcmp if
        "Sorry, the installation routine requires forcing you "
        "to create guest characters and set props on them. "
        "God can't be forced. Have one of your minion wizards "
        "do this." strcat strcat strcat .tell exit
    then
                                                 (* register program *)
    #0 "_reg/con/multiguest" prog setprop
    
                                         (* pcreate log-in character *)
    me @ "@pcreate " GuestName strcat
    "=" strcat GuestName 1 strcut swap tolower swap strcat strcat
    force    
                 (* blind log-in char, so users won't see room twice *)
    GuestName .pmatch dup ourGuest !
    "look;loo;lo;l" newexit
    "$nothing" match setlink
    
                          (* find con-callmultiguest. An inefficient
                             loop, but it will only need to run once *)
    2 ourCounter !
    begin
        ourCounter @ dbref dbtop dbcmp if
            0 break
        then
        ourCounter @ dbref dup ok? if
            dup program? if
                 dup name "con-callmultiguest" smatch if
                      pop 1 break
                      else
                          pop
                 then
                 else
                     pop
            then
            else
                pop
        then
        ourCounter @ 1 + ourCounter ! 
    repeat
    
                                  (* set log-in char to call program *)
    if
       ourGuest @ "_connect/multiguest" ourCounter @ dbref setprop
       ourCounter @ dbref "L" set
       else
           " " .tell
           "NOTE: con-callmultiguest not found. You will need to port "
           "it, @set it Link_OK and Wizard, and set " strcat
           GuestName strcat 
           "'s _connect/multiguest property to its dbref" strcat .tell
           " " .tell
    then
                                   (* get number of Guests to create *)
    dup if
        dup number? if
            ourCounter !
            else
                "8" ourCounter !
        then
        else
            "8" ourCounter !
    then
                                                   (* create guests *)
    begin
        ourCounter @ atoi while
    
        me @ "@pcreate " GuestName strcat ourCounter @ strcat
        "=" strcat GuestPassWd strcat force
    
        GuestName ourCounter @ strcat .pmatch ourGuest !
        
                                  (* lock out unGuest-like commands *)
        ourGuest @
        "@chown;@chow;@cho;@ch;@contents;@content;@conten;@conte;"
        "@cont;@describe;@describ;@descri;@descr;@desc;@des;@de;"
        "@drop;@dro;@dr;@entrances;@entrance;@entranc;@entran;@entra;"
        "@entr;@ent;@en;@exits;@exit;@exi;@ex;@fail;@fai;@fa;@flock;"
        "@floc;@flo;@fl;@idescribe;@idescrib;@idescri;@idescr;@idesc;"
        "@ides;@ide;@id;@link;@lin;@li;@lock;@loc;@lo;@name;@nam;@na;"
        "@odrop;@odro;@odr;@od;@ofail;@ofai;@ofa;@of;@osuccess;@osucces;"
        "@osucce;@osucc;@osuc;@osu;@os;@propset;@propse;@props;@prop;"
        "@recycle;@recycl;@recyc;@recy;@rec;@re;@r;@register;@registe;"
        "@regist;@regis;@regi;@reg;@doing;@doin;@doi;@do"
        strcat strcat strcat strcat strcat strcat strcat strcat strcat 
        newexit
        dup "$nothing" match setlink
        "Sorry, " GuestNames strcat " can't do that." strcat setsucc
        
        ourGuest @    
        "@relink;@relin;@reli;@rel;@set;@se;@shout;@pshout;@success;"
        "@succes;@succe;@succ;@suc;@su;@teleport;@telepor;@telepo;"
        "@telep;@tele;@tel;@te;@unlink;@unlin;@unli;@unl;@unlock;"
        "@unloc;@unlo;actions;act;autosweep;as;change;chang;chan;"
        "cha;ch;c;edit;edi;ed;examine;examin;exami;exam;exa;ex;exits;"
        "give;giv;gi;gripe;grip;gri;gr;g;kill;kil;ki;laston;@laston;"
        "@last;+laston;+last;lsedit;listedit;listedit;lsedi;lsed;lse;"
        "propcopy;propcp;pcopy;cp;propmove;propmv;pmove;mv;pwho;pwh;"
        "pw;rob;ro;r;sweep;swee;swe;spoof;spoo;spo;sp;@emit;@emi;@em;"
        "watchfor;wf;announce"
        strcat strcat strcat strcat strcat strcat strcat strcat strcat 
        newexit
        dup "$nothing" match setlink
        "Sorry, " GuestNames strcat " can't do that." strcat setsucc
        
                          (* move and link guests to user's location *)
        ourGuest @ me @ location moveto
        ourGuest @ me @ location setlink
        
                                    (* set some 'I'm a Guest!' props *)
        ourGuest @ "@guest/player?" "yes" setprop
        ourGuest @ "guest_player?" "yes" setprop
        ourGuest @ "A Guestatian! Be nice to it." setdesc
        ourGuest @ "sex" "Hardly" setprop
        ourGuest @ "species" GuestName setprop
        
        ourCounter @ atoi 1 - intostr ourCounter !
    repeat
    
    prog "@ver" ourVersion setprop
    "Installed. Please recycle #" trig intostr strcat .tell
;
  
: BootMe  (  --  )   (* too many guests... boot newly connected user *)
 
    preempt background
    me @ descriptors
    begin
        dup while
        1 - swap
        descrcon conboot
    repeat
;
  
: GetNextGuest  (  -- i )  (* store dbref of next available Guest
                              character in lvar ourGuest. Return
                              true if one is available, false if not *)
     "1" ourCounter !
    begin
        GuestName ourCounter @ strcat .pmatch dup not if
            pop 0 break
        then
        dup awake? if
            pop
            else
                ourGuest ! 1 break
        then
        ourCounter @ atoi 1 + intostr ourCounter !
    repeat
;
 
: main
 
    "me" match me !
    
    prog "@ver" getprop not if
        DoInstall exit
    then
                     (* get next available Guest... bail out if none *)
    GetNextGuest not if
        "Sorry, there are too many "
        GuestNames strcat
        " connected right now." strcat .tell
        "Please try again later." .tell
        BootMe exit
    then
                                               (* get descriptors... *)
    me @ descriptors 1 - swap
    
                        (* connect top descriptor to available Guest *)
    ourGuest @ GuestPassWd descr_setuser pop
    
                                   (* boot any remaining descriptors *)
    begin
        dup while
        1 - swap
        descrcon conboot
    repeat
;        
.
c
q