@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Dynamic Space - The Next Generation @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ Release: 2.8 @@ Date: 95-04-14 @@ @@ Requires: TinyMUSH 2.2 or later @@ mpp MUSH Pre-processor (distributed as mpp.c) @@ @@ Author: Joshua Bell, jsbell@acs.ucalgary.ca @@ Algol@NarniaGolden, dobest.lib.virginia.edu 6250 @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Changes: @@ ~~~~~~~~ @@ 2.8 @@ - Rewrote the whole damn exit-display stuff @@ - Made dimension-locks easier to add @@ - Lots of internal reorganizations of comments and config stuff @@ - Conversion to TinyMUSH 2.2isms (NOT COMPLETE!) @@ @@ See "HISTORY" section at end of file for a complete list. @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Dynamic Space: @@ ~~~~~~~~~~~~~~ @@ This code lets you set up rectilinear grids of rooms that only @@ exist when needed. This is useful for doing sky areas, oceans, @@ terrain, or even the surfaces of entire planets! @@ @@ This code runs under TinyMUSH 2.2 or later, and does NOT require @@ Wizard powers. Its internal recycling queue allows it to operate @@ with limited quota or limited funds (although having lots of @@ money is a major advantage), and for the technically inclined, @@ requires only two queue cycles per movement inside the semaphore @@ protection. @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Installation notes: @@ ~~~~~~~~~~~~~~~~~~~ @@ The script will have to be piped through my mpp.c "MUSH Pre- @@ Processor" to get rid of the comments and formatting. @@ The source code is available from the MUSHcode archive site @@ located at: ftp://caisr2.caisr.cwru.edu/pub/mush/mushcode @@ @@ Read the CONFIGURATION AND SETUP NOTES @@ section *before* running this script! @@ @@ The script as written will run without changes, but it is @@ doubtful that you will like, or be able to use the results. @@ @@ You may also want to grab and read: Dynamic_Space_Map-1.2 @@ which is the optional map module. @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Features: @@ ~~~~~~~~~ @@ @@ - Up to three dimensions of movement. Locks can be applied to any @@ direction of travel. @@ @@ - Space can be limited to a fixed size, made to wrap around, or extended @@ infinitely in each dimension. @@ @@ - Individual exits within a room can be blocked or hidden. @@ @@ - Exits are transparent to those who pass them. @@ @@ - The desc, succ, name, parent, and transient-status of a room can be @@ altered using simple commands within the DS. @@ @@ - Permission to alter the DS can be granted via as something as simple @@ as a flag or lock, or any function you wish. @@ @@ - Administrators can teleport to any valid location within the DS @@ volume. @@ @@ - The size of the room queue (used to avoid actual creation/destruction @@ of rooms) can be adjusted to suit the traffic expected. @@ @@ - An optional map module which allows you to "sketch" areas in ASCII @@ and have them realized in the DS. @@ @@ - Using the map, rooms can be eliminated entirely leaving "walls" @@ behind in the space. @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Conditions of use and disclaimer @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ @@ I make no claims as to the safety, reliability, or usefulness @@ of this code, other than: it has worked for me, and has not caused @@ any harm to the MUSHes I have tried it on. There are probably @@ still bugs in it, although I attempt to patch these as I find them. @@ @@ I'm willing to answer questions about setting up DS, modifying it @@ for custom use, or how portions of the code work. I'm not willing @@ to set it up for you, or to teach you everything required to @@ do it yourself (this is not for the beginner!). @@ @@ Permission is granted to run this code on any platform you chose, @@ with the provision that you let me know if you port it to another @@ server platform, find bugs, patch bugs, or add functionality that @@ may be of interest to others. @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Available Ports @@ ~~~~~~~~~~~~~~~ @@ @@ TinyMUSH 2.0.9p2 @@ ~~~~~~~~~~~~~~~~ @@ The last dedicated code for the 2.0 line of TinyMUSH @@ is Dynamic_Space-2.7p2. Look for it where you found this code. @@ Development on this line probably won't continue. @@ @@ PennMUSH 1.5p10 @@ ~~~~~~~~~~~~~~~ @@ Joe Bui has ported DS 2.7 to PennMUSH. @@ "I doubt that it will work with lower versions of PennMUSH since I @@ used db-modifying functions." @@ Joshua Bell has applied patches to bring it in line with 2.7p2 @@ code but these have not been tested. @@ @@ TinyMUSE @@ ~~~~~~~~ @@ A MUSE port (of sorts) is also available. Contact @@ czar@Wittenberg.EDU for more information @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Credits: @@ ~~~~~~~~ @@ Code: Algol@NarniaGolden (was Tash@Narnia) @@ Concept: Talek@PernMUSH @@ Instigator: Ehlrick@TooMUSH @@ Suggestions: The Hermit@Narnia, Tangent@TooMUSH, Edmund@Narnia, @@ Pomona@TooMUSH, Talek@PernMUSH, Fumblethumb@Narnia, @@ Andrew Molitor, Rilian@Narnia, Maud@Narnia, @@ Drayton@Narnia, Frank@Narnia, Kent Jenkins @@ @@ PennMUSH Ports: Rilian@Narnia (2.3) @@ Joe Bui (2.7) @@ @@ TinyMUSE Port: czar@Wittenberg.EDU (2.?) @@ -----8<----CUT HERE----8<--------8<--------8<--------8<--------8<---- @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Create the Origin Room @@ ~~~~~~~~~~~~~~~~~~~~~~ @dig/tel Center of a Vast Plane &XCOOR here=0 &YCOOR here=0 &ZCOOR here=0 @set here=FLOATING @@ Create the relevant objects @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @create Dynamic Room Parent @create Dynamic Exit Parent @create Dynamic Array Object @parent here=Dynamic Room Parent @set Dynamic Room Parent=SAFE @set Dynamic Room Parent=HALTED @set Dynamic Exit Parent=SAFE @set Dynamic Array Object=SAFE @@ Store object dbref#s @@ ~~~~~~~~~~~~~~~~~~~~ @fo me=&NAME-0.0.0 Dynamic Array Object=[name(here)] @fo me=&NUM-0.0.0 Dynamic Array Object=[num(here)] @fo me=&ARRAY Dynamic Room Parent=[num(Dynamic Array Object)] @fo me=&ARRAY Dynamic Exit Parent=[num(Dynamic Array Object)] @fo me=@va Dynamic Room Parent=[num(Dynamic Array Object)] @fo me=@va Dynamic Exit Parent=[num(Dynamic Array Object)] @fo me=&ROOM_PARENT Dynamic Exit Parent=[num(Dynamic Room Parent)] @fo me=&EXIT_PARENT Dynamic Room Parent=[num(Dynamic Exit Parent)] @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@ CONFIGURATION AND SETUP NOTES SECTION @@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Entry and Exit to/from a DS @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ ...should be done via normal exits linked to/from the DS, or @@ teleportation to rooms which are "fixed" using the "fix here" @@ building command. @@ @@ All non-dynamic exits in a DS should be set DARK; use the @@ "hide exit=" building command to conceal them. @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Set up the Inherited Exits @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ Note: If you only want N/S/E/W, just delete the NE/NW/SE/SW code. @@ Similarly, if you only want two dimensions, delete out U/D @@ If you want more exits (to have the 26 possible 3D directions, say) @@ add lines to make and parent the new exits, and just add the @@ appropriate X/Y/ZNEW attributes. North, East, and Up should be @@ add(), South, West, and Down should be sub(). All exits need to @@ be set DARK. To hide exits (say, Up and Down) add: @@ @@ &DARK_EXITS Dynamic Room Parent=|Up|Down @@ @Succ, @Osucc, @Odrop work like they normally do, but %0 is the @@ dbref# of the player attempting the exit; to emulate %p you need @@ to use [poss(%0)]. FAKE_FAIL is the same as @fail (which cannot @@ be used!), again with %0 being the player dbref#. @@ The exits attempt to be transparent to those who can pass through; @@ NO_DESC is seen if the target room is out of range, and the @@ FAIL_DESC is seen if the exit is blocked or not passable. drop Dynamic Room Parent enter Dynamic Room Parent @open Up;u @set Up=DARK @parent Up=Dynamic Exit Parent @lock Up=me&!me @link Up=here &ZNEW Up=add(get(%0/ZCOOR),1) @set Up=DARK @Succ Up=You head upwards. @Osucc Up=heads upwards. @Odrop Up=comes up from below. &FAKE_FAIL Up=You find you cannot travel further upward. &NO_DESC Up=You cannot discern anything further above you. &FAIL_DESC Up=It appears impossible to travel further upwards. @open Down;d @set Down=DARK @parent Down=Dynamic Exit Parent @lock Down=me&!me @link Down=here &ZNEW Down=sub(get(%0/ZCOOR),1) @set Down=DARK @Succ Down=You head downwards. @Osucc Down=heads downwards. @Odrop Down=comes down from above. &FAKE_FAIL Down=You find you cannot travel further downward. &NO_DESC Down=You cannot discern anything further below you. &FAIL_DESC Down=It appears impossible to descend further. @open Northwest;nw @set Northwest=DARK @parent Northwest=Dynamic Exit Parent @lock Northwest=me&!me @link Northwest=here &YNEW Northwest=add(get(%0/YCOOR),1) &XNEW Northwest=sub(get(%0/XCOOR),1) @Succ Northwest=You head northwest. @Osucc Northwest=heads northwest. @Odrop Northwest=comes in from the southeast. &FAKE_FAIL Northwest=You find you cannot travel further northwest. &NO_DESC Northwest=You cannot discern anything further to the northwest. &FAIL_DESC Northwest=Travel to the northwest appears blocked. @open North;n @set North=DARK @parent North=Dynamic Exit Parent @lock North=me&!me @link North=here &YNEW North=add(get(%0/YCOOR),1) @Succ North=You head north. @Osucc North=heads north. @Odrop North=comes in from the south. &FAKE_FAIL North=You find you cannot travel further north. &NO_DESC North=You cannot discern anything further to the north. &FAIL_DESC North=Travel to the north appears blocked. @open Northeast;ne @set Northeast=DARK @parent Northeast=Dynamic Exit Parent @lock Northeast=me&!me @link Northeast=here &YNEW Northeast=add(get(%0/YCOOR),1) &XNEW Northeast=add(get(%0/XCOOR),1) @Succ Northeast=You head northeast. @Osucc Northeast=heads northeast. @Odrop Northeast=comes in from the southwest. &FAKE_FAIL Northeast=You find you cannot travel further northeast. &NO_DESC Northeast=You cannot discern anything further to the northeast. &FAIL_DESC Northeast=Travel to the northeast appears blocked. @open East;e @set East=DARK @parent East=Dynamic Exit Parent @lock East=me&!me @link East=here &XNEW East=add(get(%0/XCOOR),1) @Succ East=You head east. @Osucc East=heads east. @Odrop East=comes in from the west. &FAKE_FAIL East=You find you cannot travel further east. &NO_DESC East=You cannot discern anything further to the east. &FAIL_DESC East=Travel to the east appears blocked. @open Southeast;se @set Southeast=DARK @parent Southeast=Dynamic Exit Parent @lock Southeast=me&!me @link Southeast=here &XNEW Southeast=add(get(%0/XCOOR),1) &YNEW Southeast=sub(get(%0/YCOOR),1) @Succ Southeast=You head southeast. @Osucc Southeast=heads southeast. @Odrop Southeast=comes in from the northwest. &FAKE_FAIL Southeast=You find you cannot travel further southeast. &NO_DESC Southeast=You cannot discern anything further to the southeast. &FAIL_DESC Southeast=Travel to the southeast appears blocked. @open South;s @set South=DARK @parent South=Dynamic Exit Parent @lock South=me&!me @link South=here &YNEW South=sub(get(%0/YCOOR),1) @Succ South=You head south. @Osucc South=heads south. @Odrop South=comes in from the north. &FAKE_FAIL South=You find you cannot travel further south. &NO_DESC South=You cannot discern anything further to the south. &FAIL_DESC South=Travel to the south appears blocked. @open Southwest;sw @set Southwest=DARK @parent Southwest=Dynamic Exit Parent @lock Southwest=me&!me @link Southwest=here &XNEW Southwest=sub(get(%0/XCOOR),1) &YNEW Southwest=sub(get(%0/YCOOR),1) @Succ Southwest=You head southwest. @Osucc Southwest=heads southwest. @Odrop Southwest=comes in from the northeast. &FAKE_FAIL Southwest=You find you cannot travel further southwest. &NO_DESC Southwest=You cannot discern anything further to the southwest. &FAIL_DESC Southwest=Travel to the southwest appears blocked. @open West;w @set West=DARK @parent West=Dynamic Exit Parent @lock West=me&!me @link West=here &XNEW West=sub(get(%0/XCOOR),1) @Succ West=You head west. @Osucc West=heads west. @Odrop West=comes in from the east. &FAKE_FAIL West=You find you cannot travel further west. &NO_DESC West=You cannot discern anything further to the west. &FAIL_DESC West=Travel to the west appears blocked. leave @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Builder Lock @@ ~~~~~~~~~~~~ @@ Look at the ISBUILDER code - anything for which that function @@ returns a 1 is allowed to use the commands in the next section. @@ You could do a member list, or whatever. &ISBUILDER Dynamic Room Parent=[hasflag(%#,builder)] @lock/UseLock Dynamic Room Parent=ISBUILDER/1 @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Limits @@ ~~~~~~ @@ You can define the limits of the Dynamic Space in three ways for @@ each of the three dimensions. Set the corresponding *-LIMITS to: @@ 0 - No Limits. Object may travel forever in that direction. @@ 1 - Hard Limits. Objects hit a 'wall' when they reach the boundary. @@ 2 - Wrapping. Objects that reach one edge pass through to the opposite @@ edge of the plane. &X-LIMITS Dynamic Array Object=2 &Y-LIMITS Dynamic Array Object=1 &Z-LIMITS Dynamic Array Object=1 &MAXX Dynamic Array Object=10 &MINX Dynamic Array Object=-10 &MAXY Dynamic Array Object=10 &MINY Dynamic Array Object=-10 &MAXZ Dynamic Array Object=5 &MINZ Dynamic Array Object=0 @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Room Queue @@ ~~~~~~~~~~ @@ The default is between 3 and 6 rooms on the queue at any one time, @@ create or destroy any extra as needed. If you anticipate heavy use, @@ you can up the lower end. I don't think more than 5 will ever be @@ needed. The maximum limit is just an 'in case', and should never be @@ set too high, although it should be at least 3 more than the minimum. &QUEUE-MIN Dynamic Array Object=3 &QUEUE-MAX Dynamic Array Object=6 @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Dimension Locks @@ ~~~~~~~~~~~~~~~ @@ The default to allow anyone to move in any direction. To restrict @@ motion in certain directions, do something like this: @@ @@ &DIM_LOCK Up=strmatch(get(%#/HAS_WINGS),Yes) @@ @@ Travel is permitted if this function returns a true value (non-0) @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Null Rooms @@ ~~~~~~~~~~ @@ While the code for these is built in here, the best description @@ and implementation is in the optional Map Module. If you want to @@ use this feature without maps, you need to write something like this: @@ @@ &ISNULL Dynamic Exit Parent= @@ @@ %0, %1 and %2 are preset to the X, Y and Z coords of the target room. @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ SEE ALSO: @@ ~~~~~~~~~ @@ There's a section later in the code titled "Generic Attributes" that @@ you should look at. @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@ END OF CONFIGURATION AND SETUP NOTES SECTION @@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Description Generation @@ ~~~~~~~~~~~~~~~~~~~~~~ @@ All exits must be kept dark, so the Adesc provides both the @@ exit list and instructions on how builders can see a command @@ list. TERSE players see neither, you may want to alter that. @Desc Dynamic Room Parent=The plane is featureless. @Adesc Dynamic Room Parent=@pemit %#=[switch(hasflag(%#,TERSE),0,[setq(1,setunion(v(DARK_EXITS),u(DE_HIDE_BORDER),|))][setq(0,filter(DE_FILTER,lexits(%!)))][switch(words(%q0),0,,Obvious exits:%r[iter(%q0,name(##)%b)])][switch(u(ISBUILDER),1,%rType "DS Help" for DS Builder commands.)])] &DE_FILTER Dynamic Room Parent=switch(member(lcstr(%q1),lcstr(name(%0)),|),0,1,0) @@ Border exits are hidden if you're using hard limits. @@ If you don't want this. just remove DE_HIDE_BORDER &DE_HIDE_BORDER Dynamic Room Parent=edit(trim(squish([switch(11,[get(%va/X-LIMITS)][eq(v(XCOOR),get(%va/MAXX))],East|Northeast|Southeast)]%b[switch(11,[get(%va/X-LIMITS)][eq(v(XCOOR),get(%va/MINX))],West|Northwest|Southwest)]%b [switch(11,[get(%va/Y-LIMITS)][eq(v(YCOOR),get(%va/MAXY))],North|Northwest|Northeast)]%b[switch(11,[get(%va/Y-LIMITS)][eq(v(YCOOR),get(%va/MINY))],South|Southwest|Southeast)]%b[switch(11,[get(%va/Z-LIMITS)][eq(v(ZCOOR),get(%va/MAXZ))],Up)]%b[switch(11,[get(%va/Z-LIMITS)][eq(v(ZCOOR),get(%va/MINZ))],Down)])),%b,|) @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Building Commands @@ ~~~~~~~~~~~~~~~~~ @@ You can add to these, just remember to add code to the Afail code @@ of the Exit Parent. &DESC_HERE Dynamic Room Parent=$desc here=*:@desc me=%0;&desc-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=%0;@pemit %#=Desc set. &SUCC_HERE Dynamic Room Parent=$succ here=*:@succ me=%0;&succ-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=%0;@pemit %#=Succ set. &NAME_HERE Dynamic Room Parent=$name here=*:@name me=%0;&name-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=%0;@pemit %#=Name set. &COORDS_HERE Dynamic Room Parent=$coords:@pemit %#=X coordinate = [v(XCOOR)], Y coordinate = [v(YCOOR)], Z coordinate = [v(ZCOOR)] &FIX_HERE Dynamic Room Parent=$fix here:@aleave me=@@;@pemit %#=Room fixed. &PARENT_HERE Dynamic Room Parent=$parent here=*:@parent me=%0;&parent-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=%0;@pemit %#=Parent set. @@ WARNING! If you change the Parent on a room, you MUST be sure that @@ the Dynamic Room Parent (or a close copy) occurs SOMEWHERE in the @@ new Parent chain, otherwise the room will not have the proper exits. @@ You'll also want to make sure you change the GETDESC function @@ and replace the {Default description.} with {} &CMD_HIDE_EXIT Dynamic Room Parent=$hide exit=*:@switch locate(%L,%0,c)=#-1,{@pemit %#=I don't see that exit here.},#-2,{@pemit %#=I don't know which exit you mean!},{&DARK_EXITS %!=setunion(v(DARK_EXITS),lcstr(name(locate(%L,%0,c))),|);&DARK_EXITS-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=v(DARK_EXITS);@pemit %#=Exit hidden. } &CMD_SHOW_EXIT Dynamic Room Parent=$show exit=*:@switch locate(%L,%0,c)=#-1,{@pemit %#=I don't see that exit here.},#-2,{@pemit %#=I don't know which exit you mean!},{&DARK_EXITS %!=setdiff(v(DARK_EXITS),lcstr(name(locate(%L,%0,c))),|);&DARK_EXITS-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=v(DARK_EXITS);@pemit %#=Exit revealed.} &CMD_HIDDEN_EXITS Dynamic Room Parent=$list hidden exits:@pemit %#=Hidden exits: [edit(v(DARK_EXITS),|,%b%b)] &CMD_BLOCK_EXIT Dynamic Room Parent=$BLOCK exit=*:@switch locate(%L,%0,c)=#-1,{@pemit %#=I don't see that exit here.},#-2,{@pemit %#=I don't know which exit you mean!},{&BLOCKED_EXITS %!=setunion(v(BLOCKED_EXITS),lcstr(name(locate(%L,%0,c))),|);&BLOCKED_EXITS-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=v(BLOCKED_EXITS);@pemit %#=Exit blocked. } &CMD_OPEN_EXIT Dynamic Room Parent=$OPEN exit=*:@switch locate(%L,%0,c)=#-1,{@pemit %#=I don't see that exit here.},#-2,{@pemit %#=I don't know which exit you mean!},{&BLOCKED_EXITS %!=setdiff(v(BLOCKED_EXITS),lcstr(name(locate(%L,%0,c))),|);&BLOCKED_EXITS-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=v(BLOCKED_EXITS);@pemit %#=Exit opened.} &CMD_BLOCKED_EXITS Dynamic Room Parent=$list BLOCKED exits:@pemit %#=Blocked exits: [edit(v(BLOCKED_EXITS),|,%b%b)] @parent Dynamic Room Parent=Dynamic Exit Parent &CMD_TELTO Dynamic Room Parent=$telto * * *:@wait %va={@trigger v(EXIT_PARENT)/[setq(7,add(%0,0))][setq(8,add(%1,0))][setq(9,add(%2,0))][switch(0,u(INBOUNDS,%q7,%q8,%q9),DUMMY,comp(get(%va/NUM-%q7.%q8.%q9),),ALLOC_ROOM,TEL_TO_ROOM)]=%#,%L,%N,%q7,%q8,%q9} &CMD_DS_HELP Dynamic Room Parent=$DS Help:@pemit %#={%rYou can use the following commands:%r%b'name here='%b %b'coords' - find out your current coordinates%r%b'desc here='%b %b'fix here' - stop this room from being recycled%r%b'succ here='%b %b'parent here=' - be careful!!%r%b'hide exit='%b %b'show exit=' %b 'list hidden exits'%r%b'block exit='%b 'open exit=' %b 'list blocked exits'%r%b'telto ' - teleport to those coordinates, if they're valid%r} @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Recycling Code @@ ~~~~~~~~~~~~~~ @@ This code allows you to get away with not @digging at every step. @@ The system keeps a short queue of rooms to reuse. @@ Rooms get recycled when they have no contents, and only their @@ inherited exits remain, unless they have been 'fixed'. @Aleave Dynamic Room Parent=@switch and(eq(words(lcon(me)),0),eq(words(lexits(me)),words(lexits(parent(me)))))=1,{&num-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=setdiff(get(%va/num-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)]),num(me));&recycle_list %va=setunion(get(%va/RECYCLE_LIST),num(me));@name me=DS Recycled Room;@parent me;@dolist lattr(me)={&## me};@trigger %va/RECYCLE} @@ In case of spurious rooms, force a check on startup. @Startup Dynamic Room Parent=@trigger me/Aleave @@ The Array Object itself handles the queue, creation and destruction @@ of rooms as needed. &RECYCLE Dynamic Array Object=@switch words(v(RECYCLE_LIST))=<[v(QUEUE-MIN)],{@dig DS Recycled Room;@trigger me/RECYCLE},>[v(QUEUE-MAX)],{@destroy first(v(RECYCLE_LIST));&recycle_list me=rest(v(RECYCLE_LIST));@trigger me/RECYCLE} @Listen Dynamic Array Object=* created with room number *. @Amhear Dynamic Array Object=&RECYCLE_LIST me=cat(v(RECYCLE_LIST),#%1);@set #%1=FLOATING @@ Generate an Initial Queue @@ ~~~~~~~~~~~~~~~~~~~~~~~~~ @trigger Dynamic Array Object/RECYCLE @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Locks and Defaults @@ ~~~~~~~~~~~~~~~~~~ @@ No Fail message - the &FAKE_FAIL takes care of that. @Fail Dynamic Exit Parent=\ @@ The lock for exits - non-blocked and non-null and valid dimension lock &PASS_LOCK Dynamic Exit Parent=[and(not(member(lcstr(get(%L/BLOCKED_EXITS)),lcstr(name(%!)),|)),not(u(ISNULL,%q7,%q8,%q9)),u(DIM_LOCK))] @@ Default dimension lock, everyone passes &DIM_LOCK Dynamic Exit Parent=1 @@ Default null-room status &ISNULL Dynamic Exit Parent=0 @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Transparent Exit Description @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ The desc and succ are seen if the exit is passable to the looker, @@ defaulting to the parent room if nothing can be found in the array. @@ The NO_DESC attrib is seen if the target room is out of range, and @@ the FAIL_DESC is seen if the exit is blocked or not passable. @@ @@ If you are modelling sky, you may wish to copy the @desc attribute to @@ your up/down exits, and comment out the chunk: @@ not(u(PASS_LOCK)),v(FAIL_DESC), @@ This will allow unpassable exits (eg, to non-fliers) to be seen @@ from the ground. @@ The second [setq(... line handles the @succ view. Remove if unwanted. @Desc Dynamic Exit Parent=[setq(7,u(DXNEW,u(XNEW,%L)))][setq(8,u(DYNEW,u(YNEW,%L)))][setq(9,u(DZNEW,u(ZNEW,%L)))][switch(1,not(u(INRANGE,%q7,%q8,%q9)),v(NO_DESC),not(u(PASS_LOCK)),v(FAIL_DESC),[setq(0,s(u(GETDESC,%q7,%q8,%q9)))][switch(%q0,,get_eval(u(GETPARENT,%q7,%q8,%q9)/Desc),%q0)][setq(0,s(u(GETSUCC,%q7,%q8,%q9)))][switch(%q0,,setq(0,get_eval(u(GETPARENT,%q7,%q8,%q9)/Succ)))][switch(%q0,,,%r%q0)])] @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Target Room Calculation Functions @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ &INRANGE Dynamic Exit Parent=and(or(neq(get(%va/X-LIMITS),1),u(IS_IN_X,%0)),or(neq(get(%va/Y-LIMITS),1),u(IS_IN_Y,%1)),or(neq(get(%va/Z-LIMITS),1),u(IS_IN_Z,%2))) &INBOUNDS Dynamic Exit Parent=and(or(not(get(%va/X-LIMITS)),u(IS_IN_X,%0)),or(not(get(%va/Y-LIMITS)),u(IS_IN_Y,%1)),or(not(get(%va/Z-LIMITS)),u(IS_IN_Z,%2))) &IS_IN_X Dynamic Exit Parent=and(lte(%0,get(%va/MAXX)),gte(%0,get(%va/MINX))) &IS_IN_Y Dynamic Exit Parent=and(lte(%0,get(%va/MAXY)),gte(%0,get(%va/MINY))) &IS_IN_Z Dynamic Exit Parent=and(lte(%0,get(%va/MAXZ)),gte(%0,get(%va/MINZ))) @@ These three are generic, actual exits modify the values with add/sub &XNEW Dynamic Exit Parent=get(%0/XCOOR) &YNEW Dynamic Exit Parent=get(%0/YCOOR) &ZNEW Dynamic Exit Parent=get(%0/ZCOOR) @@ Compute the new location, if wrapping is enabled and relevant. &DXNEW Dynamic Exit Parent= switch(get(%va/X-LIMITS), 2,switch(1, gt(%0,get(%va/MAXX)),get(%va/MINX), lt(%0,get(%va/MINX)),get(%va/MAXX), %0 ), %0 ) &DYNEW Dynamic Exit Parent=switch(get(%va/Y-LIMITS),2,switch(1,gt(%0,get(%va/MAXY)),get(%va/MINY),lt(%0,get(%va/MINY)),get(%va/MAXY),%0),%0) &DZNEW Dynamic Exit Parent=switch(get(%va/Z-LIMITS),2,switch(1,gt(%0,get(%va/MAXZ)),get(%va/MINZ),lt(%0,get(%va/MINZ)),get(%va/MAXZ),%0),%0) @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Do the Dynamic Thing @@ ~~~~~~~~~~~~~~~~~~~~ @@ ALLOC_ROOM is responsible for the snatching of new rooms from the @@ queue, if necessary. Semaphores are used on the internal loop here; @@ when the Afail is called upon, it puts the commands on the semaphore @@ queue and uses the Array Object as the file lock. When the Array @@ Object gets @notified, one batch of waiting commands gets run. @Afail Dynamic Exit Parent=@wait %va={@trigger me/[setq(7,u(DXNEW,u(XNEW,%L)))][setq(8,u(DYNEW,u(YNEW,%L)))][setq(9,u(DZNEW,u(ZNEW,%L)))][switch(0,u(INRANGE,%q7,%q8,%q9),DUMMY,u(PASS_LOCK),DUMMY,comp(get(%va/NUM-%q7.%q8.%q9),),ALLOC_ROOM,TEL_TO_ROOM)]=%#,%L,%N,%q7,%q8,%q9} &DUMMY Dynamic Exit Parent=@pemit %0=u(FAKE_FAIL,%0,%3,%4,%5);@notify %va @@ This FAKE_FAIL is seen by admins trying to teleport. &FAKE_FAIL Dynamic Exit Parent=Sorry, you can't go to (%1,%2,%3). &ALLOC_ROOM Dynamic Exit Parent=@VN me=first(cat(get(%va/num-%3.%4.%5),get(%va/recycle_list)));&RECYCLE_LIST %va=setdiff(get(%va/RECYCLE_LIST),%vn);@trigger %va/RECYCLE;&num-%3.%4.%5 %va=%vn;&XCOOR %vn=%3;&YCOOR %vn=%4;&ZCOOR %vn=%5;@set %vn=FLOATING;@name %vn=u(GETNAME,%3,%4,%5);@desc %vn=u(GETDESC,%3,%4,%5);@succ %vn=u(GETSUCC,%3,%4,%5);@parent %vn=u(GETPARENT,%3,%4,%5);&DARK_EXITS %vn=u(GETDARKEXITS,%3,%4,%5);&BLOCKED_EXITS %vn=u(GETBLOCKEDEXITS,%3,%4,%5);@pemit %0=switch(hasflag(%0,TERSE),1,,u(Succ,%0));@tel %0=%vn;@pemit/contents %1=%2 [u(Osucc,%0)];@notify %va &TEL_TO_ROOM Dynamic Exit Parent=@VN me=get(%va/num-%3.%4.%5);@pemit/contents %vn=%2 [u(Odrop,%0)];@pemit %0=switch(hasflag(%0,TERSE),1,,u(Succ,%0));@tel %0=%vn;@pemit/contents %1=%2 [u(Osucc,%0)];@notify %va @@ Since we need it to run the first time through, notify the Array Object. @notify Dynamic Array Object @@ And on each startup. Also attempt to purge rooms. @Startup Dynamic Array Object=@drain me;@notify me;@wait 1200={@dolist lattr(%!/NUM-*)={@trigger v(##)/Aleave}} @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Generic Attributes @@ ~~~~~~~~~~~~~~~~~~ @@ These functions are used to grab names, descs, etc from the Array @@ Object. If nothing is present, they default to something silly. @@ To customize, modify whatever is in the {} inside the [switch()]. @@ %0, %1 and %2 hold the X, Y, and Z coordinates. @@ A common thing to do is have an auto-name function, or even an @@ auto-desc, that uses a map or other form of table instead of the @@ array storage, and allows a more intuitive customization. If many @@ rooms will have the same desc, however, the use of parents to @@ provide the descs will lighten the load on the server. @@ SHAMELESS PLUG: See the Dynamic Space Mapping Module add on! &GETNAME Dynamic Exit Parent=[setq(1,get(%va/NAME-%0.%1.%2))][switch(%q1,,{Dynamic Room %0 %1 %2},%q1)] &GETDESC Dynamic Exit Parent=[setq(1,get(%va/DESC-%0.%1.%2))][switch(%q1,,{Default description.},%q1)] &GETSUCC Dynamic Exit Parent=[setq(1,get(%va/SUCC-%0.%1.%2))][switch(%q1,,{},%q1)] &GETPARENT Dynamic Exit Parent=[setq(1,get(%va/PARENT-%0.%1.%2))][switch(%q1,,v(ROOM_PARENT),%q1)] &GETDARKEXITS Dynamic Exit Parent=[setq(1,get(%va/DARK_EXITS-%0.%1.%2))][switch(%q1,,{},%q1)] &GETBLOCKEDEXITS Dynamic Exit Parent=[setq(1,get(%va/BLOCKED_EXITS-%0.%1.%2))][switch(%q1,,{},%q1)] @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ Cleanup @@ ~~~~~~~ @@ Set these to point to somewhere Safe and Inaccessable. You DON'T @@ want people screwing with these. Do NOT put the Array Object inside @@ anything that will do @digging. @tel Dynamic Room Parent=me @tel Dynamic Exit Parent=me @tel Dynamic Array Object=me @@ If you aren't planning to open an exit from 0,0,0, or fix it manually, @@ make sure you link or fix SOMEWHERE in the Dynamic Space, or it will @@ all vanish when you leave it. For safety, you might want to uncomment @@ the following line: @aleave here=@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @pemit me=Script Complete at [time()] @@ -----8<----CUT HERE----8<--------8<--------8<--------8<--------8<---- @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ HISTORY @@ 2.8 @@ - Changed exit locks to me&!me from #0 @@ - Made dimension-locks easier to add @@ - Lots of internal reorganizations of comments and config stuff @@ - Rewrote the whole damn exit-display stuff @@ - Conversion to TinyMUSH 2.2isms (NOT COMPLETE!) @@ 2.7p2 @@ - Exit-display patch retrofit from 2.8 @@ 2.7p1 @@ - DE_FILTER buglet (hides all owned local exits) fixed @@ 2.7 @@ - "Null rooms" added, which allow things like mazes or @@ impassable terrain (or terrain passable only by certain @@ types of creatures). @@ - use of %va, setq() and r() to minimize DB accesses @@ (although that could doubtless be improved further) @@ - telto admin command added @@ - hide/show/block/open exit commands actually error check @@ their arguments now. Oooooh. Ooooh. :) @@ - border exits (for areas with limits) automagically hidden, @@ if desired @@ 2.6 @@ @@ - Descs added to exits (semi-transparency) @@ - Patched some silly bugs in the block/hide code @@ - Rooms now wipe attributes/parent upon recycling @@ 2.5 @@ - Startup purge of misplaced rooms added @@ - Converted to MPP format @@ - Room Parent created HALTED for safety @@ - Added blocked and darkened exits (doc'd in header) @@ - Patched DE_FILTER to handle non-dynamic exits properly @@ 2.4 @@ - Sempahores added - slightly slower but MUCH more secure @@ - Internal allocation error protection @@ - Improved/added commenting all over the code @@ - SUCC/OSUCC/ODROP/FAIL messages redone, pros and cons @@ - Some internals changed to speed up the code @@ - Optional Map Module @@ 2.3 @@ - Problem with room allocation patched. (Afail) @@ - Room recycling loophole fixed. (Aleave) @@ - Various typos fixed and some small code bits enhanced. @@ - A few new comments. @@ 2.2p1 @@ - Problem with room allocation patched. (Afail) @@ - Room recycling loophole fixed. (Aleave) @@ 2.2 @@ - Third dimension (Z) added. @@ - "Locks" on parent exits can restrict travel. @@ - Limits can now wrap in X, Y or Z. @@ - The initial room is set FLOATING. @@ - Parent exits are linked to something (security). @@ 2.1 @@ - Limits can now wrap in X or Y. @@ - The initial room is set FLOATING @@ - Parent exits are linked to something (security)