This community web book is the new official home of the WARPEDcore project. Here, within this collaborative book, you will find ...
This section of this book was originally derived from The WARPEDcore Manifesto and will henceforth be referred to as the Manifest. This is now a living document, intended to be tweaked, modified, updated, etc... basically, the intent is that this project take on a life of its own (I planted the seed. I hope it grows.)
As this project progresses, this section can be referenced as a guide when resolving conflicts between design theory and design application (some things work great in theory, but when it boils down to applying them they just... don't work as intended).
Welcome to The WARPEDcore
INTRODUCTION
The world changes. And as the world changes, some things stay the same. A number of changes in the MU-niverse in recent years have resulted in a great deal of this document becoming technically obsolete. But this document was never intended as a technical manual. It's a starting philosophy... an illustration of a far off land as seen from a local mountaintop. With that in mind, I have made notes within this document (in bold italics like this message) as well as a few comments below specific pages. I have, for the most part, left the 'theory' in place... even in those places where it's become technically inaccurate.
This document should now be considered a combination of "history" and "planning"... a sort of snapshot image of where this project came from and where it intended to be going (and should sort of still be intending to go).
For years there have been some rumblings about making a decent set of 'core components' for a 'slightly more than minimal db' for PennMUSH. I'm fairly certain there have been similar rumblings among other MUD server flavors. Some evidence of that can be seen in the recent emergence of the Sandbox Globals Project (kudos to Audumla and her team for their diligence in bringing that to fruition). Nonetheless, there is still a 'core' lacking in even this development.
This page attempts to explain what is meant by the concept of a MUD 'core' within the context of this web book, and outlines the goals of the WARPEDcore project.
This history of this project is, for the most part, restricted to M*U*S*H (the Social MUSH run by Javelin, former maintainer of the PennMUSH source) and several players there who expressed their interest. Twice in the history of M*U*S*H, there have been very intense discussions and bboard interactions on various aspects of this whole 'core' notion. What should it contain? How should it be designed? Who should be responsible for it? Etc. Although both of these more intense discussions eventually degraded into a thousand different opinions, a great deal of overall insight was shared. And from that experience (I, Trispis@M*U*S*H, attempted to actually coordinate the second of those interactions -- sorta like trying to harness a thunderstorm in a paper sack.), I learned that most of the people involved just wanted "something". Their differences of opinion were not nearly as significant as their common desires.
And just what were those 'common desires'? Well, mostly it boiled down to some sort of standardization -- some natural and/or intuitive means of standardizing certain components of MUSH (to reduce inter-MUSH disparities, to reduce the 're-learning' requirements when changing from one game to another, or any number of other syntactic versions of the same thought).
With that in mind, I studied the various individual requests and assertions, and I discovered something. In order to provide *any* form of standardization at an inter-MUSH level, there needed to be a 'core'... far deeper than simply a 'common set of globals' (+finger, +who, etc.). There needed to be a central, interactive, accessible, maintenance feature. Something that even disassociated softcode packages (Myrrdin's Bulletin Board, Places/Mutter, Keran's Weather, softcoded dynamic space systems, etc.) can 'hook' themselves to.
So, that's where I decided I needed to apply myself -- to the creation of a MUSH 'core'. And I began to outline some conceptual approaches to this. And, in so doing, I found myself inevitably returning to the concept of a 'db kernel' with a 'registry' -- a system of tracking and maintaining installed softcode packages (such as those mentioned in the previous paragraph).
A 'db kernel with a registry', yeah... and some maintenance utilities, yeah.
THAT's what a MUSH "core" is... It's something that is central to *any* and *all* installed packages. Even if a softcoded package isn't designed around the concept of a 'core', the core itself can still provide useful services around and/or for that package.
OVERVIEW
What is the 'core'? In theory, it's a THING which records and, via a simple function, reports the dbrefs of all the various packages installed on a MUSH. But, in practice, it's a little more than that. Once it builds some momentum,... once all of the 'feep' has had a chance to ripen, it has the potential to become a full-fledged MUSH maintenance utility. Therefore, in order to retain perspective on what actually constitutes the "core", great care must be taken in the development process to ensure that only "core items" get packaged with the core.
This brings us to the development process. This core will be developed as a bunch of very small components, focused around the central 'registry object'. That is, in an effort to retain focus on what has been determined to be the 'core' (the 'one object linking all other objects'), all of the installation scripts for various additional features (maintenace tools, whatever) will be maintained and developed individually and separately.
It is conceivable -- even highly likely -- that there will emerge some interdependencies between these separate packages. This is only natural (one package being a frill for another package, and so on and so forth). This further emphasizes the need to keep the 'core' isolated and protected from 'feep'.
Yet, by maintaining packages individually in this way, there is also a great deal of freedom afforded to the user... freedom to decide which features and how many of them they want and/or need. And due to the 'script' quality of softcode installation, creating a larger package out of the smaller components becomes a relatively trivial task.
There will, of course, need to be a few 'ground rules', in order to provide inter-operable standardization. These will be kept, as much as possible, to a bare minimum. And will further be divided into two groups:
DESIGN PHILOSOPHY
The WARPEDcore is designed around two primary features of MUSH coding. The object and the attribute.
The WARPEDcore Project concerns itself with five (5) primary object groups.
PLANNED OBJECTS Group # objects Global Command Objects 6-9 @function Objects 3 The WARPEDcore 1 Parents 10-13 Utilities ? Total 20-26 (plus utilities)
Each user group tends to need $command objects with powers equal to or greater than their own power level. There is some debate as to whether or not admins and wizards need $command objects for power levels less than they possess. Nonetheless, the WARPEDcore assumes it is a possibility and accounts for it as such.
NOTE: The WARPEDcore does not recommend, nor does it account for, optional objects having specific @powers (e.g., see_all, tport_anywhere, tport_anything). The inside track from one MUSH developer asserts that privilege checking is more robust and reliable when checking for a flag, than when checking for a @power. Therefore, the WARPEDcore restricts its design assumptions to only the above three power categories: mortal (no additional powers/privs), royalty flag, and wizard flag.
Using the above categories of users and powers, the following nine THINGs can be derived:
The "users" below are assumed to be upwardly inclusive (i.e., mortals == mortals, royalty, and wizards; royalty == royalty and wizards; wizards == wizards only).
In summary, as far as objects are concerned, the WARPEDcore Project focuses on the fact that a MUSH requires a certain number of objects to build a game's global infrastructure (not including: add-in packages like Myrddin's BBoard, or custom-built packages like chargen). In common practice, as a game grows in size, more and more objects become part of the infrastructure. How many THINGs are in your game's Master ROOM? How many THINGs does your game use for @functions? How quickly can you locate the code for any given feature on your game? The WARPEDcore attempts to provide a paradigm for an infrastructure which uses a fixed number of objects in a versatile and well-organized manner.
The WARPEDcore assumes, and is designed to accomodate and account for, several specific types of attributes. Each type has been assigned a four-digit identifier for use in other aspects of the WARPEDcore (explained later in this document).
Type 4dig For...
COMMAND CMND attributes containing $commands
LISTEN LSTN attributes containing ^listen patterns
UFUN UFUN attributes called via u(), filter(), etc.
TRIGGER TRIG non-$command and non-^listen attribs
which should be triggered with @trigger.
DATA DATA attribs which contain data elements or
data structures
LIST LIST attribs which contain delimited lists
LOCK LOCK attributes used in indirect locks
ZONE ZONE zone-specific or zone-related attributes
HELP HELP attributes containing help files
NOTE NOTE attributes containing notes, comments, etc.
TEMP TEMP temporary storage (users should be able
to expect to freely delete these without
disrupting functionality)
**** DBREF - One person who reviewed this document suggested that there be a four-digit prefix for indicating storage of a #dbref pointer, such as DBRF. After lengthy consideration, it has been decided that "DBREF" is not actually an attribute category. Rather, when storing a #dbref in an attribute, that attribute is more correctly categorized as a DATA attribute (or, in the case of a list of #dbrefs, a LIST attribute). Furthermore, in any instance other than a PREFIX, it would likely not be used in the four-digit form (e.g., DATA.SUPPORT_FUNCS.DBREF). Thus, there is no reason (at least not within the design of WARPEDcore guidelines) to truncate DBREF any shorter than the five characters which have become standard and common (DBREF == DataBase REFerence number, aka #dbref). -- If, however, you disagree with this and wish to have a separate category and four-digit identifier for #dbrefs, there is sufficient flexibility in the documentation options to allow this in a WARPEDcore compliant manner (see the documentation options in later sections)
NOTE: It is possible for a single attribute to belong to more than one of the above types (e.g., 'help' files for a specfic 'zone'). Which type is primary to the attribute is, of course, a subjective assessment. This issue is further addressed later in this document.
The introduction of attribute trees creates a new behavioral model for exploration and exploitation.
An implication worth noting is the emphatic new conceptual distinction between a single attribute
&example me=this is an example
and the single attribute which also serves as the root segment of an attribute tree
&example me=these are my examples
&example`a me=these are my 'a' examples
&example`a`1 me=this is example 'a1'
&example`a`2 me=this is example 'a2'
&example`b me=these are my 'b' examples
&example`b`1 me=this is example 'b1'
&example`b`2 me=this is example 'b2'
This is a new conceptual imperative: Any single attribute can, at any time, conceivably be (become, be treated as, and/or behave as) a portion of an attribute tree.
This imperative's potential lends itself somewhat naturally to subroutine management such as that illustrated by the ~reboot module in which @startup behaves both as a single attribute (containing code which is triggered at startup)
@startup #1=<this code is automatically triggered and it retrieves code from attribs in the startup` tree without directly triggering those attribs>
and as the root of a tree of other attributes (each containing code to be placed in the queue by the code in the @startup attribute).
&startup`0000 #1=<this is the first piece of code retrieved for execution by me/startup>
(Changes to ~reboot pending.)
Other implications resulting from this imperative can be found, coincidentally, within god's startup actions: specifically those actions involving the @attrib command and its family.
Give me where to stand and I will move the earth.
A remark attributed to Archimedes by Pappus of Alexandria (in his "Collection") and commonly called "Archimedes Lever", this simple assertion of relativity long predates that of Einstein's mathematical equations. Furthermore, Archimedes assertion better illustrates the reality of human experience.
In a very 'human experience' way, Archimedes Lever describes this new imperative of attribute trees with tremendous precision.
An examination of a minimalist example can illuminate this for us quite nicely, so let us look at a tree based on single-character name segments. To explore this concept, we'll use our special attribute, the tilde (~), as the root of the tree, then expand it with other common single characters (0-9, a-z, possibly others) as branches and leaves.
Let us first work with 0-9 as leaves, directly attached to the root.
~
~`0
~`1
~`2
etc...
This imperative carries one set of implications if the root attribute needs different attribute flags than the numbered leaf attributes, and another set of implications if the root attribute is flag-indifferent (e.g., it's empty - the default, since it's automatically generated whether you intend to use it or not).
Once again, our startup` tree, if applied to a player ancestor, illustrates this well -- you want the basic processing code (the startup attribute) to be available to all players, yet you also want the remainder of ancestor's startup' leaves to not be inherited (i.e., only apply directly to ancestor) -- you can do this by setting the branch (startup`) no_inherit.
If the tree is expanded to more levels (e.g., the addition of a-z as leaves on the 0-9 branches), the aforementioned implications remain present. However, as the number of levels increase (at least the first few branches beyond the first branch) these same implications can become organizational organizational variables. For example, ...
~
~`0
~`0`a
~`0`b
...
~`1
~`1`a
~`1`b
...
It's important to remember, at this time, that restrictions are inherited but privs are not, and that restrictions are only inherited by the leaves of the branch to which they're applied.
Adding to this, entire trees can be completely veiled from a default examine by simply veiling their root attribute.
So, one of potentially countless applications of our 'where to stand' philosophy is that at any single branch point (where to stand) we have the ability to control (restrict) all of its leaves (move the world)... all the while leaving the branch point itself (which may be an in-use leaf of a lower branch) and all subsequent branches (leaves of the current branch which are also branch points for subsequent branches and/or leaves) and their leaves unaffected.
And this is as good a time as any to complicate the overall situation even further (at least initially) by re-introducing the attribute naming concepts from the original version of this section. (Until I add a more updated and relevant version of these concepts, you can review the 'Old' subpage of this page.)
NAMING CONVENTIONS
One of the key components of 'standardizing' relates to attribute naming conventions. For example: If you wanted to find all attributes on a given object which contain $commands, you would either:
or...
If this example is extended to include other attribute types (HELP, UFUN, etc.), it becomes obvious that the latter method (standardized naming) is the preferable approach. And, as you will see in further reading of this document, it becomes THE key component in management of globals. In fact, standardized attribute naming is the crux of the entire WARPEDcore project. By utilizing a functional and intuitive standardized naming convention, it becomes possible to easily manage and coordinate a large number of objects, including those not written expressly under these documented conventions.
The WARPEDcore will use the following naming conventions. And, although these are recommended for all softcoders (simply to provide easy readability in the event someone else might have to sort through your code someday), it is understood that pre-existing style and/or habit may be difficult to circumvent. Therefore, in addition to these recommended conventions, the WARPEDcore also provides a means of documenting pre-existing code and pre-existing attribute naming conventions.
Type 4dig For...
COMMAND CMND attributes containing $commands
LISTEN LSTN attributes containing ^listen patterns
UFUN UFUN attributes called via u(), filter(), etc
TRIGGER TRIG non-$command and non-^listen attribs
which should be triggered with @trigger.
DATA DATA attribs which contain data elements or
data structures
LIST LIST attribs which contain delimited lists
LOCK LOCK attributes used in indirect locks
ZONE ZONE zone-specific or zone-related attributes
HELP HELP attributes containing help files
NOTE NOTE attributes containing notes, comments, etc.
TEMP TEMP temporary storage (users should be able to
expect to freely delete these without
disrupting functionality)
NOTE: It is conceivable that an attribute might belong to more than one of the above types. In such situations, it is recommended that the broader category (per the object's purpose) be considered the PREFIX for that attribute (e.g., LOCK`ZONE -- as an object may have numerous locks, but only one zone). Nevertheless, it remains a subjective decision. Think about it in terms of where you want attributes grouped when listed in a default, lexicographical sort.
All attribute name components should be separated by the back-tick (`) character.
Syntax Summary:
<PREFIX>`<PRIMARY>[`<SECONDARY>][`<TERTIARY>][`<SUFFIX>]
This section acknowledges the enormous burden of rewriting existing code to comply with the above recommended conventions. Additionally, it also acknowledges the difficulty in changing existing behaviors (old habits are hard to break). Therefore, in order to simplifying the conversion of pre-existing code (and, thus, pre-existing attribute names), personal preference, and/or habitual behavior to WARPEDcore managable structures, the following Adaptation Options have been established (NOTE: Even I, the author of this document, do not *always* use the same standards from one project to another. Ever since I started coding, I've experimented with different ways to benefit from structured attribute naming conventions. Thus, my own coded systems aren't even compatible with each other. Yet, it is out of this experimentation and in direct response to that universal disparity, that I present these conventions... and these Adaptation Options. I may or may not eventually rewrite my existing code using the conventions recommended above, but I will certainly use the Adaptation Options listed herein to make them WARPEDcore managable). The hope here is that rewrites can be reduced to a bare minimum, by simply providing a WARPEDcore compliant documentation of existing attribute naming conventions.
The following documentation conventions are recommended for adapting existing code or existing coding styles (ref: attribute names) to WARPEDcore managable structures. These conventions are divided into two sections. The first section covers the conventions for identifying general attribute types. The second section covers some special 'personal attributes' which are recommended for all objects which are intended to be registered with the WARPEDcore.
Based on the above list of recommended PREFIX components to denote attribute types, the following documentation conventions are recommended for adapting pre-existing code to WARPEDcore managable structures. In summary, you should provide a ~. attribute for each attribute type relevant to your code (i.e., if you don't have any LIST-type attributes, there is no need to document them). And each attribute should indicate your code's conventions for that attribute type, using the following procedures (derived partially from regular expression syntax).
Some examples:
Other examples:
The following is a list of special 'personal attributes' which are recommended to be included - at least as many as are applicable - in all softcode packages, regardless of whether or not you use any of the other aforementioned conventions
NOTE: Use the single tilde attribute to denote the presence of these special attribs. Do not, however, confuse the presence of these 'personal attributes' with 'being WARPEDcore compliant'. That is, if all you have done is add these attributes for personal reference or credit, then the single tilde attribute's contents' first character should NOT be a tilde. The attributes listed below are for package identification only and bear no relevance whatsoever to overall WARPEDcore compliance.
Since much of this is still in early development, some of these procedures may be subject to modification. And the list of 'special attributes' is certainly likely to grow in time.
NOTE: This page is out of date and will soon be updated to include the new (since the time this document was originally released) 'attribute trees' feature of PennMUSH as part of these design concepts. (Thanks, Talek!)
Although I see many option and combinations, these are my notes to illustrate the direction I see going with this...
Wise Man Say: Flowering Shrub uses Attribute Tree features to organize code for examination.
Sample Template:
<grandpackage>`<package>`<attr_type>.<syntax>
In this template,
<grandpackage> would be the equivalent of any one of: The Sandbox Globals Project, all of Myrddin's stuff bundled together, The mythical MUDcore supposedly written by Amberyl, etc., &c. Ideally, this would be an abbreviated version thereof (e.g., SGP for The Sandbox Globals Project). The WARPEDcore Project will use the single tilde (~) for this.
<package> would be the equivalent of a category of commands. In order to see this properly, one must envision the product as it could be at some point just just beyond what one would think of as 'complete'. Let's take, for example, a +finger command. No matter how much stuff you pack into and/or around this, in the end, it's just a single command. However, history shows that there are a number of 'social information' commands related to this (i.e., +who, +where, etc.), each of which could be quite robust in its own right yet each also just a single command. As single commands, they'd not be individual members of this category; but, as a group of 'social information' commands, together they become a <package>, such as 'socials' For example:
&SGP`SOCIALS`CMND.FINGER_X
Although I may not have presented this perfectly in this initial draft of my thoughts, the point here is that when you start writing attribute names, think bigger than the immediate feature -- place the immediate feature (whether it be a command such as +finger, or a unique ufun to sort-by-avg-idle-over-last-2-hours) into the context of a larger picture and include your 'maximum package name' appropriately as part of your attribute naming process. This sets your code up in a way such that it can be 'grafted' (copy/paste-migrated) onto yet a larger package than what you might have planned (<greatgrandpackage>?). For example, assuming licensing permits, SGP could be adapted to this design such that very little modification would be needed to make it 'attachable' to the WARPEDcore as a compatible module, yet still retaining it's separateness in development maintainership. E.g.,
~`SGP`SOCIALS`CMND.FINGER_X
And, please... if you see a better way of doing this, by all means, do it... but PLEASE... POST SOMETHING HERE! Share your insight!
I have been intermittently refining my installer for the warpedcore cron (for details, ref: most recent innovations conference presentation).
Two issues have sort of emerged (in my mind) from this refinement process.
1) purifying the cron concept (i.e., making sure that the installer only does things necessary for the cron itself, independent of any warpedcore ideas I may also have),
and as a direct result of that,
2) ways to extend the cron into the itbg discussed vision.
There's also a third issue that tends to arise every time I do an installer, and it is this issue thing I want to discuss (now having teased you with my cron, which is really irrelevant to this).
Every time I try to create an intelligent (self-monitoring, featureful, whatever) installer, there's one thing I keep concluding as 'necessary' -- an attribute on the player... a place to store and/or update installation status data.
And every time I think of this, I encounter the same problem...
What if the player happens to be using (regardless of how remote the possibility is, it nonetheless exists) the attribute name I'm using in my installer?
So, I've written a version which tries to determine a 'safe' attribute name from a limited selection of options (e.g., A B or C), as a solution for this. Specifically, to temporarily store 'their attribute contents' somewhere else while I use my static attribute name for my installation purposes (and at the end of the installer, I move their contents back).
What I'm wondering is ... is there any way to get a pulse on the MU* community to determine if "<an attribute reserved in some way for installers>" is a desirable and/or feasibly implementable fixed feature.'
At present, I am only thinking of a single reserved attrib; but, for the sake of general inquiry, it's probably appropriate to consider a larger scale implementation (a set of standardized reserved attribs for technical use/needs).
I discussed this with Javelin on M*U*S*H, and he proposed some ideas. I've included his input below.
* From afar, Javelin [...] can think of at least one algorithm for generating an attrib that's not on the current player for sure. Or, [if] this is for admin use, you could do an attrib tree rooted at [<string>`].
* From afar, Javelin would be inclined to suggest the attrib tree approach a la "registry". Attrib settable only from port descriptor is kind of a nasty hack.
* Javelin pages: Well, you could promote a conventional attribute hierarchy called "EXTSYSTEM" or something, and have people who write external systems claim a subhierarchy with their name (TRISPIS) or system name (WARPEDCORE), and then use an attribute named EXTSYSTEM`WARPEDCORE`OBJS or whatever. If God does @attrib/access on EXTSYSTEM to make it wizard-only or whatever, mortals won't be able to muck with any of the attributes beneath that label.
* Javelin pages: You still have a problem on sites where someone's using EXTSYSTEM`WARPEDCORE already, but that seems more than highly unlikely.
* From afar, Javelin was going to write an object integrity checker using a similar principle, actually. Each object's attrib would get hashed with SHA() and then the hash stored under SHA`, so you could quickly see if any attribs had changed since you last generated the hashes.
* From afar, Javelin *could* see a point in a hardcode function like tmpname(obj) that would return a valid unused attribute name for obj.
* Javelin pages: But it wouldn't return the same name every time, necessarily.
* From afar, Javelin (also knows how to softcode such a function)
* Javelin pages: Do you just need an attrib name known not to exist, or does the same name have to persist over time? (Answer: for my purposes it only needs to persist for the duration of the install, but I can certainly envision more extended duration needs).
* Javelin pages: Well, you can secure ~ as a special on a per-game basis, obviously, by warning Gods to use @attrib to do so. That's a bit specific to put in the distribution, though
* Javelin pages: [...] The @attrib command would be something like: @attrib/access/retroactive ~=wizard
* Javelin pages: The certain safe attrib algorithm is pretty simple. Sort the existing attribs by length, and iterate through them from shortest to longest. Make your new attrib name by taking the n'th character of the n'th shortest attribute and incrementing it (A->B, B->C,... Z->A, similar for symbols). If there is no n'th character of the n'th shortest attrib, assume it's an A. When finished, check to see if the attrib is on the object. If so, add an A to the end and check again (if it's still on the object, you lose, but that's highly pathological, as it means people are using extremely long attrib names to screw with you.)
* Javelin pages: The concept of that algorithm is you're creating an attrib that's known to be different from the first attrib, known to be different from the second, known to be different from the third, etc.
* SYNC: Mon Mar 08 10:05:00 2004
attribute trees are presently part of the development branch and about to be merged into the stable branch (see Jav's latest post about this), so now might be a very good time to be investigating these options in that frame of reference.
Ciao
@FUNCTIONS
The WARPEDcore creates and utilizes two libraries of custom @functions, generally categorized as core functions (~functions) and module functions (.functions).
The REGISTRY
See the comments below this page.
As indicated in several places throughout this document, the WARPEDcore is intended to serve as a registry for any and/or all of your global objects ($command globals in the Master Room, as well as global @function objects). This section covers the procedures and standards for registering such objects, and lists any reserved module names (intended solely for standardization purposes).
As indicated in the section on attribute naming conventions, the WARPEDcore is intended to record the #dbrefs of your globals and other key objects of your game. This is accomplished by storing said #dbrefs in attributes on the WARPEDcore itself, using a special attribute naming convention. When registering an object, the following guidelines must be observed.
Examples:
The registry attributes (those beginning with DB_) only contain #dbrefs. Furthermore, the #dbrefs stored in these attributes should be efficiently kept to a minimum. When registering a module, only register the lowest 'child' #dbrefs of any parented systems. Furthermore, do not register objects which are spontaneously created by other registered #dbrefs. Some examples...
The following module names (in the form of attribute names) have been reserved in an effort to promote standardization growth.
These reserved names will allow installation packages to locate the appropriate objects for writing their attributes, rather than creating a new object.
This page replaces the section of the Manifesto called "UTILITIES". Somewhere on this site is a post I made about the cron; and, since I have code written for the core and the cron, I've decided to relegate the remaining previously-documented piece (the Debug Zone) to a potential contributor module.
You can read my whole ITBG Presentation for a philosophical history of this module. I've included the currently pertinant points here. The URL's referenced below can be retrieved from www.archive.org, if you really need to see them.
We need an optimized cron. Something which provides maximum potential to both the core, and the game in general. Yet which also must be inter-connected with a registry (a MU* portions maintenance and accounting widget).
Are there cron systems available? Of course. Myrddin has a nice one. Raevnos wrote a pretty nifty one for M*U*S*H a couple years ago which even uses an internal registry. So why not use one of these? Especially Raev's... which superficially appears almost to have been written specifically for the warpedcore design (described above) ??? why not? Raev's a good guy,... surely he'd be open to some sort of contribution negotiation...
But wait...
Javelin implemented a cron of a wholly different type on M*U*S*H. A chat channel broadcast based cron. Objects can connect to this channel and listen for the various and sundry broadcasts. Jav's also has a very intrigunig side-effect -- systems using the cron all happen to be conveniently connected to a specific chat channel -- or, phrased a bit more organically: objects using the cron have created a sort of registry of their own via the cwho() function.
Raev's has an added benefit of having objects registered in various 'intervals', but Jav's is a simpler implementation which doesn't need any maintenance after a purge.
Jav's can also be easily extended to do broadcasts as frequently as once a minute, (Jav's currently is only once an hour) without any noticable increase in overhead or workload (even more frequently, if you're careful).
A channel based system could be expanded to have multiple channels for the various frequencies (hourly, 2hourly, whatever). Plus, channels for other broadcasts (core system messages, if such a need arises, perhaps?). But is channel proliferation desireable? probably not.
But, a channel based system does allow for a significantly larger amount of information to be broadcast each 'tick'.
Jav's version does multiple emits for hours which fit multiple categories. For example...
<-Clock-> HOURLY: Wed Oct 22 20:00:04 2003 <-Clock-> HOUR20: Wed Oct 22 20:00:04 2003 <-Clock-> FOURHOURLY: Wed Oct 22 20:00:06 2003
like that. This isn't bad on an hourly basis. But if broadcasts were every minute, the ticks on the hour would be hugely spammy... especially if a wider variety of less frequent intervals were included (5min, 10min, etc.)
So, I played around with the channel concept and came up with some modifications and enhancements.
First, I dabbled with a bit-based system which uses 1's and 0's to indicate whether or not a given broadcast tick was a member of the various intervals (daily, 12hourly, 8hourly, 6hourly, 4hourly 3hourly, 2hourly, hourly, 30m, 20m, 15m, 10m, 5m).
http://www.elsemu.net/~nemo/cron_bits.txt
The objections to this mainly pertained to the fact that a bit-based system (strings of 1's and 0's) isn't conducive to human implementation.
So, I dabbled with another version using an alphanumeric (more 'human readable') implementation, using the same intervals.
http://www.elsemu.net/~nemo/cron_alphanum.txt
They each have their advantages.
The alphanumeric would be easier to document/explain in a help file, and easier for most folks to get adjusted to using.
But the one with bits allows you to do a few things the other doesn't, such as listen for 5m intervals that AREN'T also 15m intervals (*0?1).
So, I combined them and added a snippet of code which tells you the number of the weekday (3rd Monday in October, for example)...
http://www.elsemu.net/~nemo/cron_both.txt
The only questions I haven't investigated too deeply so far are:
Nonetheless, this particular cron design appears to fulfill the core's needs quite nicely... flexibly... thoroughly... efficiently.
CONTRIBUTED CODE
In an effort to keep the 'core' and its primary modules from becoming excessively large and/or complex as an overall package, the "substance" of this project will (hopefully) manifest in the form of 'contributed code' or 'contributed modules'. These contributions will mainly take the form of .function()s (see the section on @functions above) and should be installed on one of the three @functions THINGs, depending on the privs required. Some proposed suggestions for what I envision contributions to look like have already been briefly illustrated above, but I feel this deserves a little more attention and am dedicating this section to further enhancing this aspect of the WARPEDcore.
Some examples of what I anticipate seeing are as follows...
@osucc =.verb(osucc,indoor,outdoor)
... which would return an OSUCC message appropriate for an indoor exit which leads to an outdoor room. (other variations might be written for dealing with second story windows -- where it's not likely that you 'walk through the window to main street')
The whole idea here being that of creating some basic, optional utilities and features.
Any code, other than Official WARPEDcore Code (see below), referenced or listed in this document is licensed by its respective author. The author of this document claims no affiliation with such code other than that of 'fair use reference' based on general knowledge of its existence (i.e., licensing for SGP, Keran's Weather, Myrddin's Bulletin Board, etc. is deferred to their respective authors and/or maintainers).
Talk trash about me if you must, but... while I'm alive, please show me respect for having done the initial work to make this available to the public by retaining my asserted claim thereto, therewith, and/or therein.
The WARPEDcore Community Enforced, Documentation and Inspired Application of Softcode License.
WCEDIASL? Okay. that's just... excessive. Back to The WARPEDcore Softcode and Documentation License (WSDL).
We're talking about credit for the inspired application of pieces of a larger work (namely, features of the softcoding platforms of the MUD family). It's like talking about patenting something you made out of tinker toys. It's TINKER TOYS, for crying out loud! But still... that is a pretty darned cool thing you made out of them.
Due to the nature of its programming environment, Softcode requires that (except in the 'proverbial vaccuum') its produced 'programs' be published (or, more precisely, made visible to someone other than the author). As such, it falls in the realm of text (as opposed to virtual machinery or other newfangled concepts of the digital age, which include binary executables and such). As text, the only area of relevant applicable law is copyright law. And, because of the "near-public-domain" mandated state of this particular programming environment, there is little room to make any meaningful 'enforcible' claim (meaning - proving measurable damage in a court of law, without being charged oneself for making a mockery of a Judge's court).
We have to assume that people (potentially even crooked, malicious, or spitefully mean-spirited people that you don't like) are gonna use your code. I mean.. that's the point, right? You're wanting to let SOMEONE use it... and because of that, there's potential for others (to whom you may not have explicitly, in person, mano a mano, granted such permission) to procure use of it as well.
And, knowing that, you'd like to somehow ensure that you're properly credited for your effort... and to further ensure that this credit is carried along with your product, wherever it ends up going.
At first this might seem like a pointlessly overwhelming challenge for such a relatively inconsequential programming environment. But there is a silver lining. The MU-niverse is rather small. At a generous estimate, I'd start with a population of say 1,000,000 people: less than 10,000 active/serious softcoders (who would care a nit about a license), less than 1,000 active game gods with more than a year experience, and less than 100 currently active people with more than 10 years experience. In a MU-niverse so small and tightly-interconnected (everyone knows someone on some other game, etc. - heh, the seven degrees of separation from Javelin?), there is much more room for placing emphasis on respect for the person, rather than respect for the position. That is, we don't have to respect every game god of every game regardless how small as though they were the president of an independent 500 year old nationstate just because s/he had a spare $25/mo to lease a server somewhere - instead, respect is something hard-earned (in the sense that it can be earned through positive contribution and/or effort) and time-honored (time-honored in two senses: 1. that it is inheritable/transferrable in 'long-standing games', and 2. it is based on, and honors, longevity/experience in the MU-niverse itself).
Thus, the MU-niverse is both 'infinite in potential' yet simultaneously small enough that it naturally retains a community feel... and, thus, some of the innate features and qualities of the community social environment. Of specific relevance to this topic (copyright/license), is the fact that, if you are discovered to be using someone else's product in a manner which disrespects that person, you are subject to (and likely to actually suffer from) social consequences (peer pressure is very powerful in the MU-niverse). And it is upon these features of the MU-niverse that the WARPEDcore will build its license. The WARPEDcore will assume that the MU-niverse protects its members as an innate survival feature. Specifically, with reference to the crediting and/or licensing of softcode, it will be assumed that very little effort needs be placed into asserting one's rights - they are, for the most part, assumed (assumed to at least follow the spirit of larger, related U-niverses, such as - in relation to this topic - real life copyright laws and licenses). That is, to say... if you create some original work, put your name on it, and put it 'out there for others to use', there is a strong enough force in the MU-niverse to enforce certain 'implied rights' (e.g., if Fubar B. Wibblemeep strips my name off of my product and starts distributing it, verbatim, as though it were his own, the MU-niverse would catch him... probably quite quickly... and not for violation of any documented 'law' in any country - but more for a violation of community trust-spirit).
Borrowing from Moses' famous document,
To users: Thou shalt not covet, nor steal, thy neighbor's softcode. (Use it, distribute it, build upon it and/or otherwise change it to suit thy needs. Just don't claim it as wholly thine own... lest "the court of public opinion" shalt surely catch thee and punish thee.)
To producers: Thou shalt contribute thy softcode freely, and in full confidence that thou shalt receive retained credit for thy contributions.
And from this, we arrive at the ~`legal attribute. A single attribute in which to assert, assign, delineate, specify, and/or document authorship/maintainership credit and terms of use. For WARPEDcore, it is deemed appropriate to include the following:
* a URL pointing to further information (and optionally, name of a person or group).
Examples
&~`legal foo=Joe Softcoder http://my.softcode.mush
&~`legal foo=The WARPEDcore Project. See: http://community.pennmush.org
&~`legal foo=Trispis @ M*U*S*H, License: WSDL http://community.pennmush.org.
As the author of this document, I have full faith in the MU-niverse that no more than this is required (in fact, I explicitly don't think a link to the specific page of this specific book is necessary) and, further, that removal of such documenation in the spirit of fraud would violate a community value so powerfully self-preserving that it is capable of being its own deterrent. (I can't force you not to remove the above attribute. It's like the 'do not remove under penalty of law' tags on your livingroom throw pillows - you removed them. so what. no one cares. just don't go bragging that you made the pillows by hand from antique material you inherited from your great grandmother; and if you inherit a situation where such documentation was removed prior to your inheritance, don't claim your grandmother made the pillows. The MU-niverse will simply laugh at you and possibly make a public example of you... possibly for a very long time, too, at least until you "get it".) I'll leave the details of this philosophy to the MU-niverse itself to maintain.
There's a nifty 'audio tagline' used by Ten Thirteen Productions (The X-Files, Millenium). It is simply the voice of a young boy proudly asserting, "I made this." (ref. TV Acres)
That's the perfect expression of what we, both as individuals and as a community-oriented MU-niverse, want to protect. I believe this.
And now, here's our 'legal-eze' to which the WARPEDcore "~`legal" pointer attribute will be pointing... Based on the BSD and MIT templates, I leave in place the WARPEDcore Softcode and Documentation License as it was originally written, the only modification being adaptation to this web-book format.
The WARPEDcore Manifesto (the document on which this book is based), this collaborative web-book, and all softcode (including softcode installation scripts) referenced in this document as being "Official" WARPEDcore Modules (i.e., ~reboot, ~cron, and other softcode scripts designated as portions of the WARPEDcore Project), unless otherwise specified in their individual documentation, are released and maintained under the terms of the following License, DISCLAIMER, and Copyright.
The WARPEDcore Softcode and Documentation License (WSDL)
Redistribution and use of WARPEDcore materials (the original manifesto, this collaborative web-book, scripts, modules, etc.) in text or digital forms, with or without modification, are permitted provided that the following conditions are met:
THIS MATERIAL IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS MATERIAL, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This community web-book is copyrighted to it's current author and/or maintainer, presently Chuc McGuire (aka Trispis @ community.pennmush.org).
In the event of a transfer of this copyright to some potential subsequent maintainer, the remainder of this page will include a complete, reverse-cronological copyright history.
Copyright 2007, Chuc McGuire
Copyright 2002-2006, Chuc McGuire
A few recent events to which I have been subjected, or which I have witnessed objectively, have reminded me of an event from my gradeschool days. I'm going to relate this story with fictional names (to protect the innocent, as well as the guilty).
Trudy's Candy Bar
Trudy was seven years old when she entered second grade. And, for the first time in her education, she finally got to have her own private storage bin (basically a plastic tub about the size of two breadboxes), in which to store her books and personal belongings.
One day, Trudy's mother put a chocolate candy bar in with Trudy's lunch as a special treat. Trudy was so excited that, the moment she arrived at school, she showed it to her teacher and all of her classmates. Oh, what a wonderful chocolate treat she was going to have for dessert at lunch time. She placed her lunch into her personal storage bin, just like every morning, exchanging it for the writing pad, pencils, etc. which had been stored there overnight, and proceeded with her daily lesson as normal.
When lunchtime finally arrived, much to Trudy's dismay (as well as her teacher and the rest of her classmates), there was no candy bar in her lunchpail. The teacher, almost enraged, but trying to maintain composure, stood and addressed the entire classroom as they ate lunch, "we all know Trudy brought a chocolate candy bar with her lunch today. everyone saw it. now it is gone. if you know who has taken it, please come and tell me."
At that very moment, Johnny emerged from the bathroom, his hands and face smeared with chocolate, and he proclaimed loud enough for all to hear, "Don't ask me who took it. I was in the bathroom the whole time!"
This alternative license addendum is specifically intended for installations under development, and/or testbed installations.
Often (more often than not?), softcoders do not have games of their own on which to develop their widgets and what-nots in the privacy of a protected environment. This license is intended to protect a softcoder's rights in those situations where necessity and/or opportunity place their project's development on a game or server over which they do not have control.
NOTE: Although this is the primary intent of this license, it is not the exclusive range of its potential applicability.
NOTE: It is possible, even highly likely, that the author of the package governed by this license may have a public (i.e., non-development) version of the same system released under a completely different license. This is another specific intent of this alternative license - to protect the private development process of an otherwise publicly released package (i.e., Joe Coder doesn't want his latest and greatest features becoming public until he's darned well ready - this license is intended to protect his development time-table ... his right to guide and control the development process of his own coded systems).
NOTE: In an ideal world, this license would be unnecessary. But, as Jethro Tull so clearly stated it "He who made kittens put snakes in the grass" -- i.e., it's definitely NOT an ideal world. So, the world being as it is, this license will be developed as the "Gentleman's Agreement" which should exist without being written, but which apparently also needs to be documented for reference.
CREDITS
Credit and thanks for contribution in the form of discussion, critique, philosophical commentary, recommended additions and changes, motivational kudos, and/or any other form of constructive input toward the creation of the original Manifesto and Code pieces is extended to the following people:
Credit for specific individual contributions should be documented within the contributions themselves.
Credit for bug reports and patches will be maintained in this book in some way.
This page lists specific additional credit pertaining to rewrites of and/or modifications to the content of this web-book.
joan stark - jgs
www.ascii-art.com
.'\ /`.
.'.-.`-'.-.`.
..._: .-. .-. :_...
.' '-.(o ) (o ).-' `.
: _ _ _`~(_)~`_ _ _ :
: /: ' .-=_ _=-. ` ;\ :
: :|-.._ ' ` _..-|: :
: `:| |`:-:-.-:-:'| |:' :
`. `.| | | | | | |.' .'
`. `-:_| | |_:-' .'
jgs `-._ ```` _.-'
``-------''
... she went on. "Would you tell me, please, which way I ought to go from here?"
"That depends a good deal on where you want to get to," said the Cat.
-- Lewis Carroll
This section of this book contains the code, available for viewing, editing, contributing, tweaking, etc.
That is to say, the code will be developed within this collaborative book paradigm. The 'official installation packages' will be released on ftp.pennmush.org for public download (no need to copy/paste bits and pieces out of this book - whole package compilations will be available for that purpose).
Each module will have a subsection to itself, with optional subsections thereunder (e.g., a module with 5 objects might have an intro page with 5 sub-pages, one for each object).
At least that's the initial plan. We'll see how things go, after we get some code online and some participation started.
This section will include all pieces of contributed code which have been selected for inclusion in the official release of the WARPEDcore.
This section's activity should, for the most part, be limited to either...
or...
At least that's the plan. We'll see how it goes...
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ WARPED ~~~~~~~~~~~~~~~~ ~
@@ ~~~~~~~~~ ~~~~~~~~~ WARPEDcore ~~
@@ ~~~~~~ ~~~~~~ ~reboot ~~~
@@ ~~~~ Adoption ~~~~ 200609250b ~~~~
@@ ~~~ Date ~~~~~~ ~~~~~~
@@ ~~ 2006.09.25 ~~~~~~~~~ ~~~~~~~~~
@@ ~ ~~~~~~~~~~~~~~~~ core
@@ ------------------------------------------------------------------------
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ========================================================================
@@
@@ LEGAL
@@
@@ This material is released under the terms of the
@@ WARPEDcore Softcode and Documentation License (WSDL).
@@ For details, see: http://community.pennmush.org
@@
@@ USE AT YOUR OWN RISK.
@@
@@ Copyright 2006, The WARPEDcore Project
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ README
@@
@@ PLEASE READ THIS SECTION. It is IMPORTANT!
@@
@@
@@ This is a very powerful and delicate piece of code. PLEASE read ALL
@@ of the comments VERY CAREFULLY. Most of this code must be manually
@@ installed (edit a line appropriately, copy/paste).
@@
@@ DO NOT, I repeat, DO NOT attempt to quote this file into your game!
@@
@@
@@ USE AT YOUR OWN RISK.
@@
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ BEGIN REQUIREMENTS
@@
@@ * PennMUSH version 1.7.7p21 or newer.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ The Theory
@@
@@ Unless you've tweaked a great deal, your #1/startup contains one of the
@@ following:
@@
@@ a) a very long string of @<command>;@<command>;@<command>[;etc]'s.
@@
@@ b) at least one @dolist.
@@
@@ c) a combination of the above.
@@
@@ If startup sequencing is highly important, you probably have "c"
@@ (above), in which you have the most crucial items done as direct
@@ commands, followed by a dolist or two for the rest.
@@
@@ Depending on how much tweaking you've done, you may or may not have a
@@ well-organized and easily managed process.
@@
@@ That's what this package attempts to provide - a well-organized and
@@ easily managed god/startup - while also retaining as much startup
@@ precidence as possible.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ The 'cut' line.
@@
@@ The text above this point contains no code, and should be removed
@@ if you intend to /quote this file in some way. The recommended procedure
@@ is to read and follow the instructions and to copy, line by line, the
@@ needed pieces as you go; however, I did attempt to write this so that it
@@ could be /quoted if done so with care and responsibility. And, even if
@@ you do /quote it, you will inevitably have some manual adjustments to
@@ make when it's done.
@@
@@ ========================================================================
@@ . . C . . u . . t . . H . . e . . r . . e . .
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ authorship, credit, and copyright information.
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
&~.legal #1=WARPEDcore~reboot, see: http://community.pennmush.org
&~.version #1=200609250b
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ data attributes
@@
@@ ------------------------------------------------------------------------
@@
@@ configs
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ god configs
@@
@@
@@
&~`ORDER #1=0:First 1:Attribute 2:Function 3:Command 4:Hook 5-8:Unused 9:Last
@@
&~`ORDER.NOTE #1=Neither this attribute nor its contents is used by the @startup and/or ~`<reboot> code in any way. It's simply a way to store your design plan for reference (e.g., "okay, it's been 3 years since I had to make any changes to this -- now, which numeric group was I using for @commands again?"). It contains a suggested default arrangement. If you don't need it (and plan to dump everything into ~`0???), ignore it.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ local configs
@@
@@
&~`RENUM`INTERVAL #1=10
@@
&~`RENUM`INTERVAL.NOTE #1=This is the renumbering interval used for the auto-renumbering.
@@
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ the code.
@@
@@ ------------------------------------------------------------------------
@@
@@ functions
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ the renumbering function
@@
@@
&~`RENUM`UFUN #1=iter(lnum(0,9), setq(0,itext(0))[iter(setr(1, filter(me/~`NNNN`FILTER, lattr(me/~`%q0???))), set(me, itext(0).TEMP:[v(itext(0))])[attrib_set(me/[itext(0)])])][iter(%q1, set(me, %q0[rjust(mul(inum(0), v(~`RENUM`INTERVAL)), 3, 0)]:[v(itext(0).TEMP)])[attrib_set(me/[itext(0)].TEMP)])])
@@
&~`RENUM`UFUN.NOTE #1=this function divides the possible 10,000 attribs into groups of 1000, by managing the first number as a separate iteration process, renumbering each group of 1000 (possible) attribs as a separate sub-process. This allows you, if you so choose, to manage groups of processes separately. For example, putting all "really super important" startup commands in STARTUP`0??? attributes, all remaining @attribute commands in STARTUP`1??? attributes, all remaining @command commands in STARTUP`2??? attributes, etc. (or, if don't have very many and don't need such subdivisions, you can put them all into the 0??? category and be done with it - you just won't be utilizing this subdividing feature). It must be operated manually (Logged into god, think u(me/~`RENUM`UFUN))
@@
&~`NNNN`FILTER #1=isnum(rest(%0,`))
@@
&~`NNNN`FILTER.NOTE #1=This is the filter to ensure that only ~`#### attributes are processed, just in case someone adds a ~`NOTE or whatever without thinking. It is used by ~`RENUM`UFUN and @startup.
@@
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ globals
@@
@@ ------------------------------------------------------------------------
@@
@@ @attribs
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ These are @attribs needed by the WARPEDcore
@@
@@ &~`0010 #1=@attribute/access/retroactive ~=safe veiled visual no_clone
@@
@@ This prepares the ~ attribute (and subsequent tree features) for use
@@ with the WARPEDcore.
@@
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ Help
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ No such animal.
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ activation
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ the @startup attribute
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ simplest conversion is...
@@
@@ first, make a backup copy of your existing #1/startup.
@@
@cpattr #1/STARTUP=#1/STARTUP.BACKUP
@@
@@ confirm the operation..
@@
ex #1/STARTUP
ex #1/STARTUP.BACKUP
@@
@@ next, copy your existing glob of goo from #1/startup to this system's
@@ "Last" numeric group, in the last entry (this assumes a 'failsafe'
@@ position for all your pre-existing code)...
@@
@cpattr #1/STARTUP=#1/~`9999
@@
@@ then, at your leisure, proceed to gradually migrate things from their
@@ current location (#1/~`9999) into their appropriate new separate
@@ attributes.
@@
@@ give #1 an appropriate new @startup.
@@
@startup #1=@dolist/delimit | [iter(sort(filter(me/~`NNNN`FILTER, lattr(me/~`????)), a), v(itext(0)), %b, |)]=##
@@
&STARTUP`NOTE #1=This makes something like "@dolist/delimit | @<command>|@<command>|@<command>[&c]=##"; and it does so in a manner which prevents non-god insertion of malicious commands. YMMV.
@@
@@ When you finish migrating everything from ~`9999 into appropriate
@@ individual attribute placements (deleting each piece from this
@@ attribute as you do so, eventually deleting this attribute as well),
@@ you can delete #1/STARTUP.BACKUP (the failsafe backup I made you create
@@ earlier in the script).
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ The end result should be a game which, during a game restart, processes
@@ "all startup commands" in the earliest possible queue cycle that such a
@@ single action can occur. God is granted five (5) initial queue cycles
@@ during startup, in which it is allowed the unique privilege of freely
@@ cramming stuff into the queue at will, before anyone else's @startup is
@@ processed. This code attempts to use a single @dolist to get as much
@@ 'stuff' into the queue as early as possible.
@@
@@ ALSO NOTE: This code is not restricted only to #1/startup. It can be
@@ used in anything's @startup, or in @aconnect, or any other place you
@@ need to process several commands in sequence.
@@ ------------------------------------------------------------------------
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ========================================================================
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ WARPED ~~~~~~~~~~~~~~~~ ~
@@ ~~~~~~~~~ ~~~~~~~~~ WARPEDcore ~~
@@ ~~~~~~ ~~~~~~ ~cron ~~~
@@ ~~~~ Adoption ~~~~ 200601110b ~~~~
@@ ~~~ Date ~~~~~~ ~~~~~~
@@ ~~ 2007.01.11 ~~~~~~~~~ ~~~~~~~~~
@@ ~ ~~~~~~~~~~~~~~~~ core
@@ ------------------------------------------------------------------------
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ LEGAL
@@
@@ This material is released under the terms of the
@@ WARPEDcore Softcode and Documentation License (WSDL).
@@ For details, see: http://community.pennmush.org
@@
@@ USE AT YOUR OWN RISK.
@@
@@ Copyright 2007, The WARPEDcore Project
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ SYSTEM REQUIREMENTS
@@
@@ * PennMUSH version 1.7.4p21 or newer.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ The 'cut' line.
@@
@@ It is safe to remove everything above the following line, before quoting
@@ this script into your MUSH.
@@
@@ ========================================================================
@@ . . . . C . . . u . . . t . . . . . . H . . . e . . . r . . . e . . . .
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ create ~cron
@@
@create ~cron
@set ~cron=NO_COMMAND
@describe ~cron=WARPEDcore~cron
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ legal reference and version
@@
&~`legal ~cron=http://community.pennmush.org
@@
&~`version ~cron=200701110b
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ data
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ variables: configurable.
@@
@@ documentation is provided.
@@
&CONF`INTERVAL ~cron=300
&NOTE`CONF`INTERVAL ~cron=This value represents the frequency of emits in a number of SECONDS. Note, setting this to anything other than an appropriate multiple of sixty (60) will have very screwy results. Recommended values are the following: 60 300 600 900 1200 1800 3600 (1m 5m 10m 15m 20m 30m and 60m, respectively). Default: 300 (5m)
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ the code.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ the loop.
@@
@@ fix this so that the emit is caculated before the final wait length.
@@
@STARTUP ~cron=@wait/until [cemit(~, if(gt(sub(secs(),convtime(starttime())),10),Re-)Started., 1)][setr(s, mul(setr(i, v(CONF`INTERVAL)), inc(div(secs(), %qi))))]=@tr me/TRIG`CRON`LOOP=%qs
@@
&NOTE`STARTUP ~cron=triggers TRIG.CRON.LOOP to start the cron
@@
@@
&TRIG`CRON`LOOP ~cron=@wait/until [cemit(~, ufun(UFUN`CEMIT,%0), 1)][setr(s, mul(setr(i, v(CONF`INTERVAL)), inc(div(secs(), %qi))))]=@tr me/TRIG`CRON`LOOP=%qs
@@
&NOTE`TRIG`CRON`LOOP ~cron=this cemits cron message and reinitiates loop.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ the functions
@@
&UFUN`CEMIT ~cron=[u(UFUN`TZ)][@@(UFUN`TZ sets and returns %qz - the timezone offset based on system configuration)]~%0~[u(UFUN`ETIMESTRING, %0)][@@(UFUN`ETIMESTRING sets and returns %qt - the enhanced time string value for %0)][if(hasattrval(me/UFUN`IC),~[u(UFUN`IC, %0)])][@@(does whatever you write UFUN`IC to do)]
@@
&NOTE`UFUN`CEMIT ~cron=this calculates, arranges, and returns the message for the cron cemit, using the subsequent UFUN.* attribs. %0 is the secs() value of the current emit sent to all subsequent functions.
@@
@@
&UFUN`TZ ~cron=[setr(z, div(sub(secs(), convtime(utctime())), 3600))]
@@
&NOTE`UFUN`TZ ~cron=determines sets %qz to the timezone offset in hours, based on your system's configuration.
@@
@@
&UFUN`ETIMESTRING ~cron=[setq(t, convsecs(%0))][inc(div(dec(elements(%qt, 3)), 7))][@@(<-- this calculates N for 'Nth <Weekday> of the month')][if(not(strmatch(elements(%qt, 2), elements(convsecs(add(%0, lmath(mul,60 60 24 7))), 2))), .0)][@@(<-- this appends '.0' to the previously calculated 'N' if and only if this is also the 'last <Weekday> of the month')] %qt
@@
&NOTE`UFUN`ETIMESTRING ~cron=sets %qt to the timestring value for %0 and emits %qt preceded by the <N[.0]> enhancement.
@@
@@
&UFUN`IC ~cron=
@@
&NOTE`UFUN`IC ~cron=write this for your IC cron data. it is sent %qs - the UTSECS value of current emit .
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ create the cron broadcast channel and configure its locks on the ~cron.
@@
@chan/add ~=object player quiet
@@
@dolist join speak see hide mod=@clock/## ~=@[num(~cron)]
@dolist Join Speak See Hide Mod=@lock/user:Chan##Lock ~cron=LOCK`CHAN`[ucstr(##)]/1
@@
@@
&LOCK`CHAN`JOIN ~cron=cor(orflags(owner(%#), Wr), not(t(member(iter(cwho(~), owner(%i0)), owner(%#)))), u(LOCK`CHAN`JOIN.CUSTOM))
@@
&NOTE`LOCK`CHAN`JOIN ~cron=join-locks the channel to wizards and royalty, mortal players who don't already have an object on channel, and whatever you write in LOCK`CHAN`JOIN.CUSTOM
@@
&LOCK`CHAN`JOIN.CUSTOM ~cron=0
@@
&NOTE`LOCK`CHAN`JOIN.CUSTOM ~cron=write your own truth value test here.
@@
@@
&LOCK`CHAN`SPEAK ~cron=strmatch(%#, num(me))
@@
@@
&LOCK`CHAN`SEE ~cron=1
@@
@@
&LOCK`CHAN`HIDE ~cron=strmatch(%#, num(me))
@@
@@
&LOCK`CHAN`MOD ~cron=0
@@
@@
@chan/on ~=~cron
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ Help
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ Help files
@@
&HELP`CRON ~cron=%r<~> <TZ>~<SECS>~<ETIMESTRING>~<IC>%r%r [ljust(<~>,12)] this is the channel name.%r [ljust(<TZ>,10)] TimeZone offset in hours>%r [ljust(<SECS>,12)] secs() of the current emit%r [ljust(<ETIMESTRING>,12)] includes <#wkday> and <time()> of current emit%r [ljust(<IC>,10)] includes whatever is custom written by the game gods%r%rexample...%r%r<~> -6 1067209500~4.0 Sun Oct 26 17:05:00 2003~<IC stuff>%r%rSee also the +help on: ic_time%r
@@
&HELP`IC_TIME ~cron=%rthe <IC> section of the ~cron includes whatever softcoded "IC time" data your local wizards have configured for this portion.%r%r[get(me/note`ufun`cron`ic)]
@@
@@
@@ The following regexp listen patterns were contributed by Mike @ M*U*S*H
@@ for some common listen intervals. Although it's not necessary to use
@@ regexp listen patterns, it can be very useful especially if you wanted
@@ to combine a few of the effects (e.g., opening a secret exit only
@@ on the third Wednesday of the month at precisely midnight).
@@
@@ In each one,
@@ %1 is <TZ~SECS>
@@ %2 is the <N>th Weekday of the month
@@ %3 is the Weekday itself,
@@ %4 the month,
@@ %5 the Day of the Month,
@@ %6 the HH,
@@ %7 the MM,
@@ %8 the SS,
@@ %9 the YYYY
@@ (%0 is the entire com message)
@@ if all the individual %<1-9> registers aren't needed, you can of course
@@ write shorter code.
@@
@@ These are untested, but I think they should work, with the caveat that
@@ if you ever broadcast at intervals of less than one minute,
@@ things will get nasty.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ &1M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(..):(..) (....)$:blah
@@ &2M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(.[02468]):(..) (....)$:blah
@@ &5M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(.[05]):(..) (....)$:blah
@@ &10M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(.0):(..) (....)$:blah
@@ &15M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(00|15|30|45):(..) (....)$:blah
@@ &20M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):([024]0):(..) (....)$:blah
@@ &30M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):([03]0):(..) (....)$:blah
@@ &1H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(00):(..) (....)$:blah
@@ &2H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (.[02468]):(00):(..) (....)$:blah
@@ &3H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|03|06|09|12|15|18|21):(00):(..) (....)$:blah
@@ &4H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|04|08|12|16|20):(00):(..) (....)$:blah
@@ &6H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|06|12|18):(00):(..) (....)$:blah
@@ &8H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|08|16):(00):(..) (....)$:blah
@@ &12H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|12):(00):(..) (....)$:blah
@@ &24H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00):(00):(..) (....)$:blah
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ activate
@@
@restart ~cron
@@
@@ The End.
This section is where user contributions will be run through the paces as they are considered for inclusion in the official release versions. Each and every line of code in the WARPEDcore will start its life here. This section is where MOST of the activity of this entire book SHOULD take place.
At the most basic explanation (as I am presently understanding this book format), the procedure should work something like this...
NOTE: Just because a contribution isn't immediately considered for inclusion in the official release does not necessarily mean it's been rejected therefrom. I suspect many contributions will go through a very long period of 'not quite ready'-ness, for whatever reason (maybe the core isn't really ready to deal with the larger implications of adding some specific module - whatever). Point being: don't be discouraged if your really cool idea version 42.b5 just hangs out here for a while in the 'debug, comment, and abuse' phase.
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ WARPED ~~~~~~~~~~~~~~~~ ~
@@ ~~~~~~~~~ ~~~~~~~~~ WARPEDcore ~~
@@ ~~~~~~ ~~~~~~ ~reboot ~~~
@@ ~~~~ Adoption ~~~~ 200609250b ~~~~
@@ ~~~ Date ~~~~~~ ~~~~~~
@@ ~~ 2006.09.25 ~~~~~~~~~ ~~~~~~~~~
@@ ~ ~~~~~~~~~~~~~~~~ core
@@ ------------------------------------------------------------------------
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ========================================================================
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ WARPEDcore~cron Version 20070107a1
@@
@@ ------------------------------------------------------------------------
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ LEGAL
@@
@@ This material is released under the terms of the
@@ WARPEDcore Softcode and Documentation License (WSDL).
@@ For details, see: http://community.pennmush.org
@@
@@ USE AT YOUR OWN RISK.
@@
@@ Copyright 2007, The WARPEDcore Project
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ SYSTEM REQUIREMENTS
@@
@@ * PennMUSH version 1.7.4p21 or newer.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ The 'cut' line.
@@
@@ It is safe to remove everything above the following line, before quoting
@@ this script into your MUSH.
@@
@@ ========================================================================
@@ . . . . C . . . u . . . t . . . . . . H . . . e . . . r . . . e . . . .
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ create ~cron
@@
@create ~cron
@set ~cron=NO_COMMAND
@describe ~cron=WARPEDcore~cron
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ legal reference and version
@@
&~`legal ~cron=http://community.pennmush.org
@@
&~`version ~cron=20070107a1
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ data
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ variables: configurable.
@@
@@ documentation is provided.
@@
&CONF`INTERVAL ~cron=300
&NOTE`CONF`INTERVAL ~cron=This value represents the frequency of emits in a number of SECONDS. Note, setting this to anything other than an appropriate multiple of sixty (60) will have very screwy results. Recommended values are the following: 60 300 600 900 1200 1800 3600 (1m 5m 10m 15m 20m 30m and 60m, respectively). Default: 300 (5m)
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ the code.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ the loop.
@@
@@ fix this so that the emit is caculated before the final wait length.
@@
@STARTUP ~cron=@wait/until [cemit(~, if(gt(sub(secs(),convtime(starttime())),10),Re-)Started., 1)][setr(s, mul(setr(i, v(CONF`INTERVAL)), inc(div(secs(), %qi))))]=@tr me/TRIG`CRON`LOOP=%qs
@@
&NOTE`STARTUP ~cron=triggers TRIG.CRON.LOOP to start the cron
@@
@@
&TRIG`CRON`LOOP ~cron=@wait/until [cemit(~, ufun(UFUN`CEMIT,%0), 1)][setr(s, mul(setr(i, v(CONF`INTERVAL)), inc(div(secs(), %qi))))]=@tr me/TRIG`CRON`LOOP=%qs
@@
&NOTE`TRIG`CRON`LOOP ~cron=this cemits cron message and reinitiates loop.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ the functions
@@
&UFUN`CEMIT ~cron=[u(UFUN`TZ)][@@(UFUN`TZ sets and returns %qz - the timezone offset based on system configuration)]~%0~[u(UFUN`ETIMESTRING, %0)][@@(UFUN`ETIMESTRING sets and returns %qt - the enhanced time string value for %0)][if(hasattrval(me/UFUN`IC),~[u(UFUN`IC, %0)])][@@(does whatever you write UFUN`IC to do)]
@@
&NOTE`UFUN`CEMIT ~cron=this calculates, arranges, and returns the message for the cron cemit, using the subsequent UFUN.* attribs. %0 is the secs() value of the current emit sent to all subsequent functions.
@@
@@
&UFUN`TZ ~cron=[setr(z, div(sub(secs(), convtime(utctime())), 3600))]
@@
&NOTE`UFUN`TZ ~cron=determines sets %qz to the timezone offset in hours, based on your system's configuration.
@@
@@
&UFUN`ETIMESTRING ~cron=[setq(t, convsecs(%0))][inc(div(dec(elements(%qt, 3)), 7))][@@(<-- this calculates N for 'Nth <Weekday> of the month')][if(not(strmatch(elements(%qt, 2), elements(convsecs(add(%0, lmath(mul,60 60 24 7))), 2))), .0)][@@(<-- this appends '.0' to the previously calculated 'N' if and only if this is also the 'last <Weekday> of the month')] %qt
@@
&NOTE`UFUN`ETIMESTRING ~cron=sets %qt to the timestring value for %0 and emits %qt preceded by the <N[.0]> enhancement.
@@
@@
&UFUN`IC ~cron=
@@
&NOTE`UFUN`IC ~cron=write this for your IC cron data. it is sent %qs - the UTSECS value of current emit .
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ create the cron broadcast channel and configure its locks on the ~cron.
@@
@chan/add ~=object player quiet
@@
@dolist join speak see hide mod=@clock/## ~=@[num(~cron)]
@dolist Join Speak See Hide Mod=@lock/user:Chan##Lock ~cron=LOCK`CHAN`[ucstr(##)]/1
@@
@@
&LOCK`CHAN`JOIN ~cron=cor(orflags(owner(%#), Wr), not(t(member(iter(cwho(~), owner(%i0)), owner(%#)))), u(LOCK`CHAN`JOIN.CUSTOM))
@@
&NOTE`LOCK`CHAN`JOIN ~cron=join-locks the channel to wizards and royalty, mortal players who don't already have an object on channel, and whatever you write in LOCK`CHAN`JOIN.CUSTOM
@@
&LOCK`CHAN`JOIN.CUSTOM ~cron=0
@@
&NOTE`LOCK`CHAN`JOIN.CUSTOM ~cron=write your own truth value test here.
@@
@@
&LOCK`CHAN`SPEAK ~cron=strmatch(%#, num(me))
@@
@@
&LOCK`CHAN`SEE ~cron=1
@@
@@
&LOCK`CHAN`HIDE ~cron=strmatch(%#, num(me))
@@
@@
&LOCK`CHAN`MOD ~cron=0
@@
@@
@chan/on ~=~cron
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ Help
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ Help files
@@
&HELP`CRON ~cron=%r<~> <TZ>~<SECS>~<ETIMESTRING>~<IC>%r%r [ljust(<~>,12)] this is the channel name.%r [ljust(<TZ>,10)] TimeZone offset in hours>%r [ljust(<SECS>,12)] secs() of the current emit%r [ljust(<ETIMESTRING>,12)] includes <#wkday> and <time()> of current emit%r [ljust(<IC>,10)] includes whatever is custom written by the game gods%r%rexample...%r%r<~> -6 1067209500~4.0 Sun Oct 26 17:05:00 2003~<IC stuff>%r%rSee also the +help on: ic_time%r
@@
&HELP`IC_TIME ~cron=%rthe <IC> section of the ~cron includes whatever softcoded "IC time" data your local wizards have configured for this portion.%r%r[get(me/note`ufun`cron`ic)]
@@
@@
@@ The following regexp listen patterns were contributed by Mike @ M*U*S*H
@@ for some common listen intervals. Although it's not necessary to use
@@ regexp listen patterns, it can be very useful especially if you wanted
@@ to combine a few of the effects (e.g., opening a secret exit only
@@ on the third Wednesday of the month at precisely midnight).
@@
@@ In each one,
@@ %1 is <TZ~SECS>
@@ %2 is the <N>th Weekday of the month
@@ %3 is the Weekday itself,
@@ %4 the month,
@@ %5 the Day of the Month,
@@ %6 the HH,
@@ %7 the MM,
@@ %8 the SS,
@@ %9 the YYYY
@@ (%0 is the entire com message)
@@ if all the individual %<1-9> registers aren't needed, you can of course
@@ write shorter code.
@@
@@ These are untested, but I think they should work, with the caveat that
@@ if you ever broadcast at intervals of less than one minute,
@@ things will get nasty.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ &1M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(..):(..) (....)$:blah
@@ &2M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(.[02468]):(..) (....)$:blah
@@ &5M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(.[05]):(..) (....)$:blah
@@ &10M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(.0):(..) (....)$:blah
@@ &15M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(00|15|30|45):(..) (....)$:blah
@@ &20M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):([024]0):(..) (....)$:blah
@@ &30M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):([03]0):(..) (....)$:blah
@@ &1H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(00):(..) (....)$:blah
@@ &2H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (.[02468]):(00):(..) (....)$:blah
@@ &3H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|03|06|09|12|15|18|21):(00):(..) (....)$:blah
@@ &4H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|04|08|12|16|20):(00):(..) (....)$:blah
@@ &6H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|06|12|18):(00):(..) (....)$:blah
@@ &8H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|08|16):(00):(..) (....)$:blah
@@ &12H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|12):(00):(..) (....)$:blah
@@ &24H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00):(00):(..) (....)$:blah
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ activate
@@
@restart ~cron
@@
@@ The End.
Below is a list of 'to do' items.
1. Get and maintain plain vanilla default master list (i.e., set up a new PennMUSH "out of the box" and separate the code for setting up defaults in &DATA`<category>`<item>`DEFAULT attributes).
KNOWN BUG: the do-options code, as written, generates a category called 'parameters'.
Mike pages: If you just stick setdiff(<foo>,@config parameters,|) in (where <foo> is the textentries(help,@config %0*,|) I believe) that should fix that bit.
KNOWN BUG: the 'tiny' category doesn't get a description set.
KNOWN ISSUE: Haven't yet finished the /diff switch for two reasons:
1. time
2. have only tested this on M*U*S*H (haven't ever done a plain vanilla, per the 'to do' above).
Here's the code to generate all of the data (not yet separated per 'vanilla' above).
@@
&CMND.DO-OPTIONS [v(~)]=$do-options:@pemit %#=Doing options.[null(u(list-options))]
@@
&list-options [v(~)]=localize(setq(0,,1,,2,,3,0,4,0,5,0)[null(iter(sort(textentries(help, @config %0*,|),,|), if(isint(right(%i0, 1)), setq(5, 0), if(%q3, u(save-option, %q2, %q0))[switch(inum(0), 1, , u(save-category, %q0, %q1))][setq(3, 0, 2, , 0, rest(%i0), 5, 1)])[setq(4, 1)][iter(textfile(help, %i0), switch(setr(9, squish(%i0)), , if(%q3,u(save-option, %q2, %q0)[setq(3, 0, 2, )]), *=*:*, switch(1, %q3, u(save-option, %q2, %q0))[setq(2, %q9, 3, 1)], switch(1, %q4, if(%q5, setq(1, %q9))[setq(4,0)], %q3, setq(2, %q2 %q9))), %r, %b)], |, %b))])
@@
&save-option [v(~)]=set(me, DATA`%1`[first(%0, =)]`DEFAULT:[config(first(%0, =))])[set(me, DATA`%1`[first(%0, =)]`TYPE:[before(after(%0, <), >)])][set(me, DATA`%1`[first(%0, =)]:[squish(after(%0, :))])]
@@
&save-category [v(~)]=set(me,DATA`%0:%1)
@@
&credit-options [v(~)]=code for generating all of the attributes and contents originally written by Mike @ M*U*S*H with attribute name adaptations by Trispis @ c.p.o.
@@
And here's the display code, as it presently exists
@@
&cmnd`config [v(~)]=$~config:@pemit %#=u(UFUN`DISP)
@@
&cmnd`config.diff [v(~)]=$~config/diff:@pemit %#=u(UFUN`DISP`DIFF)
@@
&cmnd`config.list_x [v(~)]=$~config/list *:@pemit %#=ifelse(setr(e, u(UFUN`ERRCK`CATY, %0)), %qe, u(UFUN`DISP`HEADER)[u(UFUN`DISP`CATY, %0)][u(UFUN`DISP`FOOTER)])
@@
&cmnd`config.show_x [v(~)]=$~config/show *:@pemit %#=ifelse(setr(e, u(UFUN`ERRCK`ITEM, %0))