<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://wiki.lostsouls.org/w/skins/common/feed.css"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://wiki.lostsouls.org/w/index.php?action=history&amp;feed=atom&amp;title=Man_selection_core</id>
		<title>Man selection core - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.lostsouls.org/w/index.php?action=history&amp;feed=atom&amp;title=Man_selection_core"/>
		<link rel="alternate" type="text/html" href="http://wiki.lostsouls.org/w/index.php?title=Man_selection_core&amp;action=history"/>
		<updated>2026-05-06T11:43:22Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.8.2</generator>

	<entry>
		<id>http://wiki.lostsouls.org/w/index.php?title=Man_selection_core&amp;diff=4000&amp;oldid=prev</id>
		<title>Laine at 22:29, 11 June 2007</title>
		<link rel="alternate" type="text/html" href="http://wiki.lostsouls.org/w/index.php?title=Man_selection_core&amp;diff=4000&amp;oldid=prev"/>
				<updated>2007-06-11T22:29:33Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==Files==&lt;br /&gt;
&lt;br /&gt;
 /lib/rarity.h&lt;br /&gt;
 /lib/selection.h&lt;br /&gt;
 /mod/daemon/selection.c&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
/daemon/materials.c, /lib/materials.h&lt;br /&gt;
/daemon/races.c, /etc/races.h&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This document describes what you need to do in order to implement a&lt;br /&gt;
selection parser.  There are two reasons you might want to do this.&lt;br /&gt;
First, you may be a core systems developer looking to implement a new&lt;br /&gt;
core-level selection parser beyond those for materials, races, items,&lt;br /&gt;
characters, and rooms (described in 'man selection').  (Those of that&lt;br /&gt;
list that aren't implemented yet should be left to me, thank you&lt;br /&gt;
kindly, unless you don't hear from me for many, many moons.)  Second,&lt;br /&gt;
you may be a skilled content developer who feels that implementing a&lt;br /&gt;
selection parser in one of your projects would be particularly useful&lt;br /&gt;
for some purpose not covered adequately by any other mechanism.&lt;br /&gt;
&lt;br /&gt;
Either way, this document will tell you exactly what you need to do&lt;br /&gt;
in order to have your parser work sanely.  Referring to the examples&lt;br /&gt;
mentioned above is likely to be quite edifying, especially with this&lt;br /&gt;
document to explain why they're doing what they're doing.  I'll mention&lt;br /&gt;
points where you particularly may want to peruse examples.&lt;br /&gt;
&lt;br /&gt;
==Core Assumptions==&lt;br /&gt;
&lt;br /&gt;
There are several assumptions that this document makes:&lt;br /&gt;
&lt;br /&gt;
1) That you have some pool of things -- anything that can be represented&lt;br /&gt;
by an LPC variable of any kind -- that you want to select from.&lt;br /&gt;
&lt;br /&gt;
2) That you need to work with this pool in a number of different ways&lt;br /&gt;
and situations, such that a selection parser would be a more appropriate&lt;br /&gt;
application than using the rarity mechanics directly or simply employing&lt;br /&gt;
random_element().&lt;br /&gt;
&lt;br /&gt;
3) That you have, or can obtain, a concept of how rare you want each of&lt;br /&gt;
these things to be (as defined by /lib/rarity.h).&lt;br /&gt;
&lt;br /&gt;
4) That the selection language defined in selection.h is adequate for&lt;br /&gt;
the type of thing you want to do with your pool of things.&lt;br /&gt;
&lt;br /&gt;
If any of these assumptions is not the case, then a selection parser&lt;br /&gt;
is not the solution for your problem.  If #4 is not true because you would&lt;br /&gt;
need additional designators or other language elements added, you can&lt;br /&gt;
send me mudmail asking for what you need, but I don't recommend trying&lt;br /&gt;
to add it any other way; I'm very likely to splatter your changes, quite&lt;br /&gt;
by accident, when I install new versions of selection.h.  The Custom&lt;br /&gt;
designator provides a totally flexible workaround for this issue, of&lt;br /&gt;
course.&lt;br /&gt;
&lt;br /&gt;
==Basic Setup==&lt;br /&gt;
&lt;br /&gt;
Selection parsers are normally implemented as daemons, so it is assumed&lt;br /&gt;
you will be inheriting /std/daemon.  In addition, you need to inherit&lt;br /&gt;
/mod/daemon/selection and include selection.h.  /mod/daemon/selection does&lt;br /&gt;
not define any of the core functions like create(), reset(), and so on, so&lt;br /&gt;
you don't need to worry about calling ::create() and the like for it.&lt;br /&gt;
&lt;br /&gt;
It may possibly, for some reason, be reasonable to implement a selection&lt;br /&gt;
parser in some centralized location other than a daemon.  However, if you&lt;br /&gt;
were to implement a selection parser in a cloned object or do something&lt;br /&gt;
so that a new parser were created every time you wanted to request a&lt;br /&gt;
selection, I would probably eviscerate you upon discovering this.  I don't&lt;br /&gt;
want that.  You don't want that.&lt;br /&gt;
&lt;br /&gt;
You will want a header file that defines the standard selection-type&lt;br /&gt;
macros for your newly created selection class.  /etc/races.h is a lovely&lt;br /&gt;
example.  These macros should look like:&lt;br /&gt;
&lt;br /&gt;
 #define Random_Thing(x)                 \&lt;br /&gt;
 (Your_Daemon-&amp;gt;select_output(x, Select_Output_Single))&lt;br /&gt;
 #define Random_Things(x, y)             \&lt;br /&gt;
 (Your_Daemon-&amp;gt;select_output(x, Select_Output_Multiple, y))&lt;br /&gt;
 #define Random_Things_Unique(x, y)      \&lt;br /&gt;
 (Your_Daemon-&amp;gt;select_output(x, Select_Output_Unique, y))&lt;br /&gt;
 #define Selected_Things(x)              \&lt;br /&gt;
 (Your_Daemon-&amp;gt;select_output(x, Select_Output_All))&lt;br /&gt;
 #define Selected_Things_Distribution(x) \&lt;br /&gt;
 (Your_Daemon-&amp;gt;select_output(x, Select_Output_Distribution))&lt;br /&gt;
&lt;br /&gt;
This example is appropriate to a lib-level parser.  If you are doing&lt;br /&gt;
this for a project, the appropriate header file is your project header file,&lt;br /&gt;
and these macros are NOT exempt from normal namespace considerations, and&lt;br /&gt;
so will probably look much like:&lt;br /&gt;
&lt;br /&gt;
 #define Project_Random_Thing(x)                 \&lt;br /&gt;
 (Project_Daemon(&amp;quot;thing&amp;quot;)-&amp;gt;select_output(x, Select_Output_Single))&lt;br /&gt;
 #define Project_Random_Things(x, y)             \&lt;br /&gt;
 (Project_Daemon(&amp;quot;thing&amp;quot;)-&amp;gt;select_output(x, Select_Output_Multiple, y))&lt;br /&gt;
 #define Project_Random_Things_Unique(x, y)      \&lt;br /&gt;
 (Project_Daemon(&amp;quot;thing&amp;quot;)-&amp;gt;select_output(x, Select_Output_Unique, y))&lt;br /&gt;
 #define Project_Selected_Things(x)              \&lt;br /&gt;
 (Project_Daemon(&amp;quot;thing&amp;quot;)-&amp;gt;select_output(x, Select_Output_All))&lt;br /&gt;
 #define Project_Selected_Things_Distribution(x) \&lt;br /&gt;
 (Project_Daemon(&amp;quot;thing&amp;quot;)-&amp;gt;select_output(x, Select_Output_Distribution)) &lt;br /&gt;
&lt;br /&gt;
==Implementing Your Hooks==&lt;br /&gt;
&lt;br /&gt;
There are three &amp;quot;hooks&amp;quot; the parser requires, and one which is optional.&lt;br /&gt;
(&amp;quot;Hook&amp;quot; is used here in a slightly different sense than with the general&lt;br /&gt;
hook mechanism in the lib, since the people messing with things at this level&lt;br /&gt;
can be expected not to be confused by this.)  Your parser must implement&lt;br /&gt;
the following functions.  The static flag is not strictly necessary, but&lt;br /&gt;
recommended.  You must NOT use the private flag for these or any other&lt;br /&gt;
functions required by the parser, because then the parser cannot access them.&lt;br /&gt;
&lt;br /&gt;
static int select_hook_rarity(mixed array parse, mixed what)&lt;br /&gt;
&lt;br /&gt;
A required hook.  'parse' is the parse environment, as defined in&lt;br /&gt;
selection.h, and 'what' is the thing that the parser is requesting a&lt;br /&gt;
rarity for.  This function must return the rarity you want associated&lt;br /&gt;
with the thing given.&lt;br /&gt;
&lt;br /&gt;
static mixed array select_hook_entire_pool(mixed array parse)&lt;br /&gt;
&lt;br /&gt;
A required hook.  'parse', again, is the parse environment.  This&lt;br /&gt;
function must return an array containing your entire pool of things.&lt;br /&gt;
Order is insignificant.&lt;br /&gt;
&lt;br /&gt;
static mixed array select_hook_closure_args(mixed array parse, mixed what)&lt;br /&gt;
&lt;br /&gt;
A required hook.  The arguments are the same as in the rarity hook.&lt;br /&gt;
This function must return an array of the arguments you want passed to&lt;br /&gt;
user-defined closures encountered by the parser.  Customarily, the options&lt;br /&gt;
mapping from the parse environment is made the last argument.  If you don't&lt;br /&gt;
know what to do with this hook, you can't go far wrong with this:&lt;br /&gt;
&lt;br /&gt;
    return ({ what, parse[Select_Parse_Env_Options] });&lt;br /&gt;
&lt;br /&gt;
static mixed select_hook_convert_output(mixed array parse, mixed what)&lt;br /&gt;
&lt;br /&gt;
An optional hook.  The arguments are the same as in the rarity hook.&lt;br /&gt;
This hooks allows you to postprocess the output which is produced by the&lt;br /&gt;
selection system.  The return value of this hook will replace the item&lt;br /&gt;
as it would normally be returned.  Note that this function must be able&lt;br /&gt;
to handle the case when nothing could be selected and 'what' is zero.&lt;br /&gt;
&lt;br /&gt;
==Implementing Your Designators==&lt;br /&gt;
&lt;br /&gt;
I assume that you are familiar with the concept of designators from 'man&lt;br /&gt;
selection'.  There are three designators that the parser provides on its&lt;br /&gt;
own using the hooks you give: All, Custom, and Rarity.  You do not need&lt;br /&gt;
to, and in fact cannot, provide support for these.  Any designators beyond&lt;br /&gt;
these that you wish your parser to implement, you need to provide support&lt;br /&gt;
functions for.  Feel free at all times to refer to the examples to see how&lt;br /&gt;
it's done.&lt;br /&gt;
&lt;br /&gt;
A designator support function is defined by its name being the string&lt;br /&gt;
&amp;quot;select_designator_&amp;quot; + lower_case(replace(&amp;quot; &amp;quot;, &amp;quot;_&amp;quot;, Designator_Name)).&lt;br /&gt;
So, the name of the support function for the Anatomy Component designator&lt;br /&gt;
is select_designator_anatomy_component().&lt;br /&gt;
&lt;br /&gt;
Say you have a pool of things in which some are sentient and some are not,&lt;br /&gt;
so you want to support the Sentience designator in your parser.  You also&lt;br /&gt;
happen to have a global array, called 'sentient', that has a list of the&lt;br /&gt;
items in your pool that are sentient.  Your support function might then&lt;br /&gt;
look like this:&lt;br /&gt;
&lt;br /&gt;
static void select_designator_sentience(mixed array parse) {&lt;br /&gt;
    mixed arg = select_pop_stack(parse);&lt;br /&gt;
    unless(statusp(arg))&lt;br /&gt;
        select_error(&amp;quot;Non-boolean argument for sentience&amp;quot;, arg);&lt;br /&gt;
    foreach(mixed thing : sentient)&lt;br /&gt;
        select_hit(parse, thing);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
You will see here that we have introduced a few new concepts: the&lt;br /&gt;
functions select_pop_stack(), select_error(), and select_hit().  These&lt;br /&gt;
are utility functions provided by /mod/daemon/selection for your use in&lt;br /&gt;
implementing your parser.  Their care and feeding is described in the&lt;br /&gt;
next section.&lt;br /&gt;
&lt;br /&gt;
==Parser Utility Functions==&lt;br /&gt;
&lt;br /&gt;
mixed select_pop_stack(mixed array parse)&lt;br /&gt;
&lt;br /&gt;
This function is how you obtain the data that the user has passed as an&lt;br /&gt;
argument to your designator.  You must pop off no more and no less than&lt;br /&gt;
the number of values your designator takes as arguments; one for Sentience,&lt;br /&gt;
Property, Material, two for Value, and so on.  Doing otherwise will screw&lt;br /&gt;
up the parsing process and cause errors.  You pass as an argument the parse&lt;br /&gt;
environment your support function is passed.&lt;br /&gt;
&lt;br /&gt;
void select_hit(mixed array parse, mixed what)&lt;br /&gt;
&lt;br /&gt;
This function is how you tell the parser that your designator has found a&lt;br /&gt;
thing that it applies to.  The first argument is the parse environment your&lt;br /&gt;
support function is passed, and the second is the thing your designator&lt;br /&gt;
wants to designate.&lt;br /&gt;
&lt;br /&gt;
varargs void select_error(string message, mixed value)&lt;br /&gt;
&lt;br /&gt;
This function aborts execution with an error from the selection parsing&lt;br /&gt;
process.  The first argument is the string message you want displayed.&lt;br /&gt;
the second, optional, argument is any value particularly relevant to the&lt;br /&gt;
error, which select_error() will present in as useful a fashion as it can&lt;br /&gt;
determine as part of the error message.&lt;br /&gt;
&lt;br /&gt;
==Implementing Your Options==&lt;br /&gt;
&lt;br /&gt;
If you would like to support any parser-level options, you need to define&lt;br /&gt;
support functions for these as well.  The name of the necessary support&lt;br /&gt;
function for a given option is &amp;quot;select_option_&amp;quot; + option_name.  (Note that&lt;br /&gt;
this means option names cannot have any character that is not valid in a&lt;br /&gt;
function name.)  An option support function is like a designator with one&lt;br /&gt;
argument, so you need to pop one value off the stack.  A support function&lt;br /&gt;
for an option called &amp;quot;allow_unique&amp;quot; might look like this:&lt;br /&gt;
&lt;br /&gt;
static void select_option_allow_unique(mixed array parse) {&lt;br /&gt;
    mixed val = select_pop_stack(parse);&lt;br /&gt;
    unless(statusp(val))&lt;br /&gt;
        select_error(&amp;quot;Non-boolean argument for allow_unique&amp;quot;, val);&lt;br /&gt;
    parse[Select_Parse_Env_Options][&amp;quot;allow_unique&amp;quot;] = val;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
There is no specific need to use the options mapping, or to access only&lt;br /&gt;
the name of your option; you can manipulate global variables or whatever&lt;br /&gt;
else in your option support function.  The options mapping is there for&lt;br /&gt;
your convenience if it's useful to you.&lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
&lt;br /&gt;
Implemented your hooks?  Implemented the designators you want to support?&lt;br /&gt;
Implemented any options you want?  Then you have a (hopefully) working parser.&lt;br /&gt;
Test, debug, wash, rinse, repeat.&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
&lt;br /&gt;
[[man selection|selection(mechanisms)]], [[man rarity|rarity(mechanisms)]]&lt;/div&gt;</summary>
		<author><name>Laine</name></author>	</entry>

	</feed>