Here comes version 4.0 [edit: 4.1]
Now we have associative rules with "ambient" thoughts, sequentially ordered thoughts, and a chatlog.
Here is the source code. As usually, you can run it with
SL4A on your cellphone.
rew.pl
use Android;
my $droid = Android->new();
my $homedir = '/sdcard/sl4a/scripts';
my $rewversion = 'v4.1';
sub hist {
return $chatlog[$logcount-$_[0]-1];
}
sub new { $rule{$_[0]} = $_[1]; }
sub del { delete $rule{$_[0]}; }
sub load {
my $fp = "$homedir/$_[0].rew";
if (-e $fp) {
open F, "<$fp";
local $/; eval <F>;
close F;
}
}
sub decamb {
for (keys %ambient) {
if ($ambient{$_}-- eq 0) {
delete $ambient{$_};
}
}
}
sub associate {
for (keys %ambient) {
my $asso = "< $_[0] & $_ >";
for (keys %rule) {
if ($asso =~ qr/$_/) {
eval $rule{$_};
}
}
}
}
sub thk {
associate $_[0];
for (keys %rule) {
if ($_[0] =~ qr/$_/) {
eval $rule{$_};
}
}
}
sub say {
push @chatlog, $_[0]; $logcount++;
print"O $_[0]\n";
}
sub save {
unlink "$homedir/$_[0].rew";
open F, ">>$homedir/$_[0].rew";
for (keys %rule) {
print F '$rule{q('
. "$_" . ')} = q('
. "$rule{$_});\n\n";
}
close F;
say 'done';
}
sub aft { push @thoughtlist, $_[0]; }
sub amb { $ambient{$_[0]}= 5; }
sub unamb { delete $ambient{$_[0]}; }
load 'current';
$rule{'^user said s$'}=
q(save 'current';);
$rule{'^user said t (.+) x (.+)'}=
q(new $1, $2;);
$rule{'^user said x (.+)'}=
q(eval $1;);
print "\n Rew $rewversion [ Perl "
. $^V . " / SL4A ]\n\n\n "
. scalar(keys %rule) . " rules\n";
amb 'startup';
while (1) {
print "\nI ";
chomp(my $message = <STDIN>);
push @chatlog, $message; $logcount++;
@thoughtlist=();
aft "user said $message";
for $tht (@thoughtlist) { thk $tht; }
decamb;
}
So. You start with 3 rules, which are hard coded. One for saving your work, one for adding new rules, and one for evaluating Perl commands. You need to know Perl programming basics if you gonna use Rew.
Let's create a new rule to see our current ruleset:
Rew v4.0 [ Perl v5.11.0 / SL4A ]
3 rules
I t ^show rules$ x for (keys %rule) { say "$_ => $rule{$_}"; }
I show rules
O ^t (.+) x (.+) => new $1, $2;
O ^show rules$ => for (keys %rule) { say "$_ => $rule{$_}"; }
O ^s$ => save 'current';
O ^x (.+) => eval $1;
I
In Rew, rules are merely Perl pattern associated with Perl code.
Here we associate the pattern
^show rules$
with the code
for (keys %rule) { say "$_ => $rule{$_}"; }
It's all Perl, nothing more.
Now you can see our 4 rules.
First rule is "t something x something", which means that when the first "something" is thought, then the second "something" is executed.
Second rule is, YOU DO NOT TALK ABOUT no wait...
The t / x syntax is just sugar for the sub named "new". At some point, you'll want to create rules that create rules. When you get there, don't use the t / x syntax twice in the same statement: the interpreter wouldn't get it correctly. Instead, use t / x and then new, like this:
I t ^nf x new '^foo (.+)', 'say "bar $1";'
I foo test
I nf
I foo test
O bar test
The sub named "say" obviously makes the bot speak.
The sub named "thk" makes it think something immediately. Any thought is matched against every rule in the current ruleset.
The sub named "aft" makes it think something, but only after the current thought has been matched against every rule, like this:
I t bar x say 'ok';
I t test x aft 'bar'; say 'foo';
I test
O foo
O ok
Finally, the sub named "amb" will create a temporary "ambient" thought. Ambient thoughts are automatically associated with every produced thought, during 5 rounds. Associated thoughts are surrounded by '< ' and ' >', and separated by ' & '. See this example:
I t (.+) x say "thinking [ $1 ]";
I ju
O thinking [ ju ]
I x amb 'test'
0 thinking [ x amb 'test' ]
I uy
O thinking [ < uy & test > ]
O thinking [ uy ]
And there's also the "hist" sub, to access things previously said.
I foo
I bar
I x say hist 2
O foo
That's it. Have fun!
edit:
This is version 4.1, with a new function "unamb" that deletes an ambient thought, and an ambient thought "startup" automatically launched at startup. Also, every user input is automatically prefixed with "user said ". My first 10 rules:
current.rew
$rule{q(^user said t (.+) x (.+))} = q(new $1, $2;);
$rule{q(^user said show rule (.+))} = q(my $trig= qr/$1/; for (keys %rule) { if ($_ =~ $trig) { say "$_ => $rule{$_}"; } });
$rule{q(^user said x (.+))} = q(eval $1;);
$rule{q(< user said (hi|hi there|hello) & startup >)} = q(say 'hello user';);
$rule{q(^user said show thoughts$)} = q(amb 'log';);
$rule{q(^user said show ruleset$)} = q(for (keys %rule) { say "$_ => $rule{$_}"; });
$rule{q(^user said s$)} = q(save 'current';);
$rule{q(< (.+) & log >)} = q(say "[ $1 ]";);
$rule{q(^user said show ambient$)} = q(for (keys %ambient) { say "$_"; });
$rule{q(^user said count rules$)} = q(say scalar(keys %rule) . ' rules';);