So, I have this program for generating random things. It works essentially like a left recursive descent parser, and it's reasonable sophisticated an easily extensible, but I don't really have a good use for it at the moment.
It can do some really cool stuff, so I'd like to give it a purpose. For instance, instead of just filling in a bunch of blanks, it can create outputs of variable length, outputs with optional components, outputs with randomly added components, and, importantly, its recursive as fuck.
Example code that generates a person. Problematically, it's all compressed to one line, but it is semi-colon delimited.
[people] ` [unit] [person] [male] ` [humanoid] ` [C] ` [setvar heshe he] [setvar hisher his] [setvar himher him] [buildvar fname malefname] [buildvar lname surname] [buildvar race race] [loadvar fname] [loadvar lname] is a male [loadvar race]. His skin is [build skincolor], his [build hair], and his eyes [build eyes]. He looks [build agedescriptor] [optional 25] [split 50] but is truly [build agedescriptor] [else] but is quite [build extremeagedescriptor] at heart [join][end]. [optional 50] For a [loadvar race] he's quite [build unitdescriptor].[end] [build distinguishingFeature]. [has crest][optional 50] The crest of the [loadvar lname] family is a [build crest] [optional 50] [split 50], but he [build symbolshame][else], and he [build symbolpride][join][end].[end][end] [pb][nl] [loadvar fname] has an inborn affinity for [build affinity][optional 50][split 75] and [build affinity][else], [build affinity], and [build affinity][join][end]. In the past [split 33] [build darkpast] [else] [split 50] [build lightpast] [else] [build mundanepast][join][join]. Now [split 33] [build darkpresent] [else] [split 50] [build lightpresent] [else] [build mundanepresent][join][join]. [optional 75] [build destiny] [end] [pb][nl] At heart [loadvar fname] is a [build personalitytrait] man. [optional 50] Most of those who meet him consider him [build personalitytrait] and [build personalitytrait].[end] [Optional 50] He has a habit of [build habit] when he's [build emotion][end] [optional 50] [build personalityquirk][end];
Huh. This might take some time to explain. I colored things to make it look like less of a mess. The reason it looks like a pile of vomit is that the syntax grew steadily more expressive the longer I worked on it. When the first ones were written, there was nothing more than optionals, and certainly no nested control statements. Their addition makes this run a whole lot more like you're actually writing code, and thus makes this A LOT easier to interpret using multi-line formats instead of the single line version it was originally designed to parse.
So, starting from the top, the sequence of [SOMETHING] before the first hanja is the library that this item is associated with. The sequence of [SOMETHING] between the first and second hanjas indicates the item's identities which determine by what names it can be called, between the second and third hanjas are tags which influence the probability generating an object with matching tags, between the third and fourth hanjas is the item's rarity which influences its base probability of being picked. Now, everything after that...
Grey text is read directly. Whatever is in grey WILL be printed to the screen.
Cyan text denotes set and load commands. SetVar commands associate a variable name to a given, non-random string. BuildVar commands associate a variable name to a variable as determined by the build command, but DOES NOT PRINT IT IMMEDIATELY. All variables are available at lower levels of recursion than they were initially defined, so by defining heshe (a variable that contains either a he or a she pronoun) one can maintain things like gender consistency and plurality easily through all sub-items.
Green text is the meat and potatoes. The Build command searches all the loaded libraries for all items fitting the given identity. From the list, it performs a random selection based on known tags and predefines rarities. Once it selects an item, it reads that item through, filling in all of that item's build commands, and when that item reaches EOF it prints the result of its grey text into the space. Loadvar is similar, except that instead of building an item from the respective libraries, it merely inserts the predefined string.
Blue text is associated with the [OPTIONAL x][End] control structure, which basically says that anything between the [OPTIONAL] and its associated [END] has an x percent chance of being written.
Red text is associated with the [Split x] [Else] [Join] control structure, which basically says there is an x chance for the data between the [split] and [else] to be parsed, and, if it isn't, the text between the [else] and [end] will be parsed. It's basically an if-else structure. Yes, that does mean it basically does everything optional does, but its a bit more cumbersome to write and I wrote it later.
Orange text is associated with the [has identity][End] command, which evaluates text iff there is at least one item in the loaded libraries that matches the provided identities. Really quite useful.
Pink text contains formatting codes, [pb] is page break, [nl] is new line.
Sooo... overlong description aside. Anyone have ideas for a game that can/should use this?