@@ @@ This is a port of Joshua Bell's Dynamic Space 2.8 to PennMUSH 1.6.9 @@ @@ Joshua is the author and deserves the credit for anything that works right. @@ Javelin just did this port, and it's his fault if things are broken. @@ The most notable change is that the Dynamic Exit Parent is an object, @@ not an exit, and that both zoning and parenting is used. @@ @@ However, Javelin will *NOT* support this code and there's no @@ warranty expressed or implied here. Don't even ask @@ for help with it. You're on your own, but at least you've got @@ a headstart. :) @@ @@ - Javelin 10/15/96 @@ @@ And I've fixed some timing problems. Might need Penn 1.7.6 or later @@ now. - Javelin 3/14/2004 @@ @@ P.S. A copy of mpp-1.1.c is needed to preparse this file. It's @@ at ftp.tinymush.org somewhere, or pennmush.tinymush.org (in @@ /pub/PennMUSH/Accessories) @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ 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 @set here=!NO_COMMAND @create Dynamic Array Object @set dynamic array object=NAME-0.0.0:[name(here)] @set dynamic array object=NUM-0.0.0:[num(here)] @@ Create the relevant objects @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @set me=parent-room:[dig(Dynamic Room Parent,to,from)] @lock/zone [v(parent-room)] = =me @chzone here=[v(parent-room)] @parent here=[v(parent-room)] @nuke to @nuke to @tel [v(parent-room)] @nuke from @nuke from @create Dynamic Exit Parent @set [v(parent-room)]=SAFE @set [v(parent-room)]=!NO_COMMAND @set Dynamic Exit Parent=SAFE @set Dynamic Array Object=SAFE @@ Store object dbref#s @@ ~~~~~~~~~~~~~~~~~~~~ @set [v(parent-room)]=ARRAY:[num(Dynamic Array Object)] @set dynamic exit parent=ARRAY:[num(Dynamic Array Object)] @set [v(parent-room)]=VA:[num(Dynamic Array Object)] @set dynamic exit parent=VA:[num(Dynamic Array Object)] @set dynamic exit parent=ROOM_PARENT:[num(V(parent-room))] @set [v(parent-room)]=EXIT_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 [v(parent-room)]=|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 [v(parent-room)] @@ enter [v(parent-room)] @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. @Desc Up= [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)] )] @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. @Desc Down= [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)] )] @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 [v(parent-room)]=[hasflag(%#,builder)] &ISBUILDER [v(parent-room)]=[hasflag(%#,wizard)] @lock/Use [v(parent-room)]=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=1 &Y-LIMITS Dynamic Array Object=1 &Z-LIMITS Dynamic Array Object=1 @@ For X, 0 is the middle of the River @@ For Y, 0 is the equator @@ For Z, 0 is the ground &MAXX Dynamic Array Object=10 &MINX Dynamic Array Object=-10 &MAXY Dynamic Array Object=100 &MINY Dynamic Array Object=-100 &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) &DIM_LOCK Up=[hasflag(%#,Wizard)] @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ 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 [v(parent-room)]=The plane is featureless. @Adesc [v(parent-room)]= @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 [v(parent-room)]= 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 [v(parent-room)]= 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 [v(parent-room)]=$desc here=*: @desc me=%0; &desc-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=%0; @pemit %#=Desc set. &SUCC_HERE [v(parent-room)]=$succ here=*: @succ me=%0; &succ-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=%0; @pemit %#=Succ set. &NAME_HERE [v(parent-room)]=$name here=*: @name me=%0; &name-[v(XCOOR)].[v(YCOOR)].[v(ZCOOR)] %va=%0; @pemit %#=Name set. &COORDS_HERE [v(parent-room)]=$coords: @pemit %#=X coordinate = [v(XCOOR)], Y coordinate = [v(YCOOR)], Z coordinate = [v(ZCOOR)] &FIX_HERE [v(parent-room)]=$fix here: @aleave me=@@; @pemit %#=Room fixed. &PARENT_HERE [v(parent-room)]=$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 [v(parent-room)] (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 [v(parent-room)]=$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 [v(parent-room)]=$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 [v(parent-room)]=$list hidden exits: @pemit %#=Hidden exits: [edit(v(DARK_EXITS),|,%b%b)] &CMD_BLOCK_EXIT [v(parent-room)]=$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 [v(parent-room)]=$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 [v(parent-room)]=$list BLOCKED exits: @pemit %#=Blocked exits: [edit(v(BLOCKED_EXITS),|,%b%b)] @parent [v(parent-room)]=Dynamic Exit Parent &CMD_TELTO [v(parent-room)]=$telto * * *: @wait %va={ @trigger v(EXIT_PARENT)/ [switch(0, u(INBOUNDS,%0,%1,%2),DUMMY, comp(get(%va/NUM-%0.%1.%2),),ALLOC_ROOM, TEL_TO_ROOM )]=%#,%L,%N,%0,%1,%2 } &CMD_DS_HELP [v(parent-room)]= $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 [v(parent-room)]= @switch and(eq(words(lcon(me)),0),eq(words(lexits(me)),0))=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; @chzone me; @parent me; @dolist lattr(me)={&## me}; @trigger %va/RECYCLE } @@ In case of spurious rooms, force a check on startup. @Startup [v(parent-room)]=@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)], { @nuke first(v(RECYCLE_LIST)); @nuke 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; @set %vn=!NO_COMMAND; @name %vn=u(GETNAME,%3,%4,%5); @desc %vn=u(GETDESC,%3,%4,%5); @succ %vn=u(GETSUCC,%3,%4,%5); @chzone %vn=u(GETPARENT,%3,%4,%5); @parent %vn=u(GETPARENT,%3,%4,%5); @aleave %vn=xget(u(GETPARENT,%3,%4,%5),ALEAVE); @startup %vn=xget(u(GETPARENT,%3,%4,%5),STARTUP); &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 [v(parent-room)]=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)