Add markov chain generator
A simple markov chain bot
## Installation
-Requires `JSON`, `POE`, and `POE::Component::IRC`.
+Requires `JSON`, `POE`, and `POE::Component::IRC`, all of which are of course
+available from [CPAN](http://cpan.org).
## Configuration
Copy config.pm.example to config.pm and edit to match your setup.
+WonderlandAlice does not support passwords, nickservs, SSL, or other advanced
+authentication mechanisms. PRs welcome.
+
+## Creating your own markov chain
+`markov.pl` transforms an input file into a JSON structure defining the
+relationships between the words. Use it like so:
+
+ $ perl markov.pl text > chain.json
+
+The bot loads the markov chain from chain.json when it starts up, so you will
+have to restart the bot to load new data. `markov.pl` also accepts a `--js`
+flag that makes it output a JS snippet that loads the data into a `chain`
+variable. It's intended for use when embedding the chain into a JS program.
+#!/usr/bin/perl
+use JSON;
+use Getopt::Long;
+use strict;
+
+my (%wordlist, @wordlist, %db, $js);
+
+GetOptions(
+ "js" => \$js,
+);
+
+my $lastword;
+my $c = 0;
+
+sub w_index {
+ my $word = shift;
+ if (!exists $wordlist{$word}) {
+ $wordlist{$word} = $c++;
+ push @wordlist, $word;
+ }
+ return $wordlist{$word};
+}
+
+while (<>) {
+ chomp;
+ s/^\s+//;
+ s/\s+$//;
+ s/--/ /g;
+ s/['"()\][<>*&^@~]//g;
+ my @words = split(/\s+/, $_);
+ # Make punctuation its own "word"
+ @words = map {
+ /^([\w-]+)([,.!?;:])$/ ?
+ ($1, $2) :
+ $_;
+ } @words;
+
+ for my $w (@words) {
+ my $wi = w_index(lc $w);
+ if (not defined $lastword) {
+ $lastword = $wi;
+ next;
+ }
+
+ $db{$lastword} = []
+ unless exists $db{$lastword};
+
+ push @{$db{$lastword}}, $wi;
+
+ $lastword = $wi;
+ }
+}
+
+if ($js) {
+ print "var chain = ";
+}
+
+print JSON->new->utf8->encode({wordlist => \@wordlist, relations => \%db});
+
+if ($js) {
+ print ";";
+}
+
+print "\n";