This describes what the Production Czar should do to set things up so that the instructions about manual use of generated random numbers works. You should have read that material already before reading this.
Contents:
Let's say you want to implement the sample encoding mechanics given in numbers-use for item numbers:
In LaTeX/Numbers/ make a file itemnum-spec as
digits: 4 flag ingame $a =~ /0/ flag magic $b =~ /1|3|5|7|9/ value recharge &magic and $b flag psi ($b + $c) % 3 == 0 value age ($d > $a) and ($d - $a)and run
gmX numbers itemnumwhich will ask if you want to generate new random itemnum's; answer yes. (If there aren't any generated itemnum files already, yes will be the default; if there are, no is the default, and if you try it'll make sure it doesn't overwrite anything valuable.)
What does this do? Since you said "digits: 4," the script goes through all numbers for 0000 to 9999, assigning the first digit to the variable $a, the second to $b, etc. Then it sees which flags the number satisfies. For the 'ingame' flag, we said "$a =~ /0/", which means "the first digit ($a) is a '0'." The 'magic' flag uses the 'or' symbol `|' to see if the second digit ($b) is 1 or 3 or 5 or 7 or 9, i.e. is an odd number. The 'psi' flag adds the second and third digits ($b and $c), takes them modulo three (% 3), and sees if the result is 0.
Further, it calculates the value of each 'value' entry in itemnum-spec. 'recharge' is "&magic and $b" --- meaning "look at what the 'magic' flag is for this number (whether or not we've listed it yet); if it's True, then be the second digit, and if not just be false (zero)." So if the item is magic, its recharge is just the second digit, and if it's not magic, the recharge is always zero. 'value' entries must always come out to non-negative integer values, not words or whatever.
The 'age' value involves both numerical values and Boolean (true/false) values. When these both come up, the rules are, as usual:
($d > $a) and ($d - $a)
Entries must be separated by blank lines.
The generated numbers are saved in files whose names tell you what flags they satisfy. Those that don't satisfy any of your special flags go in itemnum.plain. Psi ones go in itemnum.psi, magic in itemnum.magic, etc; psi magic items go in itemnum.magic.psi, ingame magic psionic items go in itemnum.ingame.magic.psi, etc.
Within each file, the items are sorted by the 'recharge' value (since that came first in the file) and those of the same recharge are sorted by age. In each chunk of identical flags and values the numbers are randomized. Now you can see why we made 'recharge' "&magic and $b" instead of just $b; $b itself would cause the non-magic items to have different recharge values, so it would sort them, but we want them randomized. Since "&magic and $b" is zero for all non-magic items, we avoid a spurious sort.
To limit the space the output files take up, you can put a "memory: 300" line before your "digits: " line. The '300' (for instance) is approximately how many kilobytes the files will be limited to total. If you have more than four digits, you must specify this. (Not that four digits isn't a lot of room to encode information.) This does not speed execution; see the KEEP flag below.
Most things you might want to encode you can probably do just from the examples above. What are the general rules? As some of you have figured out, the syntax for flag and value specifications is Perl syntax. Don't be scared by this; you're not writing programs, just simple expressions. Below is a list of some useful bits of syntax; if you really need to do something beyond them, just ask anyone who knows Perl for the appropriate expression.
As indicated above with 'recharge,' you can use one property in the expression for another, (no matter which order they're defined in). That is, in addition to the variables $a, $b, $c etc, if you define the flag 'magic' somewhere, you can use '&magic' to access its value; you should only use this as a Boolean, not as a number, since it could be True by being 1 or True by being -1 or... etc. 'value' properties hopefully have numeric values.
Note that you access the base variables with a $ ($a, $b, etc, or $_ for the current number as a whole) and the spec-defined properties with an & (&magic, &recharge, &psi, &age, etc).
Make sure you don't create circular definitions unless you know what you're doing.
Sometimes there's a large section of numbers you don't care about --- Reign of Terror used one digit of badge numbers as social status, and it ranged only from 1 to 5, so generating other numbers would waste time and space. To avoid them, define the special flag KEEP:
flag KEEP $d >= 1 and $d <= 5says to only keep numbers whose fourth digit is 1 to 5, and to not even look at the flags and values for other numbers, nor save them anywhere. Since this eliminates half the numbers, it cuts the runtime by half and the output takes up half as much space. KEEP is used only for this.
Here's some of those useful bits of syntax. No need to read them until you need to do something you can't see just from the examples, unless you want to.
Don't take the quotient if $b might be zero! You could avoid this with something like
value age ($b != 0) and ($a / $b)Since an 'and' is only true if both sides of it are true, it doesn't bother to look at the second one if the first is false. So if $b is zero, the first part is false (0), so the whole thing is just 0 without looking at the second part and doing that dangerous division. If $b isn't zero, the first part is true, so it looks at the second part ($a / $b); the value of the second part is then the final value.
Similarly, since an 'or' is only false if both sides are false, (foo or bar) will be equal to whatever foo is if it's nonzero (true) since there's no reason to look at bar then; if foo is false/zero then (foo or bar) will be bar.
When you say
(flag or value) foo blah blah blah blah blah blah blah blahall that happens is that
sub foo { blah blah blah blah blah blah blah blah }gets defined (in a seperate package, to preserve namespace).
You see why &foo gets you that property's value.
You should also see that having a single line with no semicolon and no 'return,' as in the sample, is a special case, even though it's almost always enough; if you write a bigger subroutine you'll need semicolons except on the last line as usual, and you might want explicit 'return's instead on relying on return-the-last-thing-evaluated.
If you write bigger subroutines, DON'T PUT IN BLANK LINES! A blank lines means you're starting a new flag/value entry!
All of the above holds for both flags and values --- the difference is that flags are used to build up a string which is the name of the file to save in, and values to build up a string that heads a chunk of the file and which is used to sort inside the file.
The flag/value subroutines are evaluated inside a nested loop with $a, $b, etc each running from '0' to '9', and their concatenation ("$a$b$c...") put into $_ for convenience.
DON'T MODIFY THE CONTENTS OF $a, $b, ETC, NOR OF $_ IN YOUR FLAGS/VALUES! Treat those as read-only or you will regret it!