#!/usr/bin/perl use constant DELAY => 15; use strict; use warnings; use Storable; use Win32::GuiTest 'SendKeys'; my $list = retrieve('word_list.db'); my $word = $ARGV[0] or die "Usage: $0 "; my $file = "${word}_highest_score.txt"; open(my $fh, '<', $file) or die "Unable to open '$file' for reading: $!"; my $last_line; while (<$fh>) { chomp; $last_line = $_; } my @guess = grep length($_) == 4, split ' ', $last_line; my ($curr, @chain) = ($list->{$word}, ()); GUESS: for my $want (@guess) { for my $have (@$curr) { if ($have->{word} eq $want) { push @chain, $have; $curr = $list->{$have->{word}}; next GUESS; } } } my $score = calculate_score(\@chain); print "Ready to get $score points (excludes time bonus)\n"; ; sleep 5; my ($last_pos, $last_word) = (0, $word); for (@chain) { my ($word, $pos, $let) = @{$_}{qw/word position letter/}; move_position($last_pos, $pos) if $last_pos != $pos; $last_pos = $pos; print "Changing '$last_word' into '$word' by using $let at $pos\n"; $last_word = $word; SendKeys($let, DELAY); } sub calculate_score { my ($chain) = @_; my ($total, $multiplier, %bonus) = (0, 1, ()); for (@$chain) { my ($pos, $score) = @{$_}{qw/position score/}; if ($bonus{$pos}) { %bonus = ($pos => 1); } else { $bonus{$pos} = 1; } if (keys %bonus == 4) { $multiplier++; %bonus = (); } $total += ($score * $multiplier); } return $total; } sub move_position { my ($src, $tgt) = @_; if ($src > $tgt) { SendKeys("{LEFT}", DELAY) for 1 .. $src - $tgt; } else { SendKeys("{RIGHT}", DELAY) for 1 .. $tgt - $src; } } sub get_next_word { my ($list, $used, $chain, $bonus, $rule) = @_; my $curr = @$chain ? $chain->[-1]{word} : $ARGV[0]; die "Usage: $0 " if ! $curr; my ($best, $max) = ('', 0); { my %avail = map {$_ => 1} 0 .. 3; delete $avail{$_} for keys %$bonus; for my $neighbor (@{$list->{$curr}}) { my ($word, $pos, $let) = @{$neighbor}{qw/word position letter/}; next if $used->{$word} || ! $avail{$pos} || fails_rule($chain, $rule, $pos, $let); my $count = @{$list->{$word}}; ($best, $max) = ($neighbor, $count) if $count > $max; } if (! $best) { return if ! %$bonus; %$bonus = (); redo; } } return $best; } sub fails_rule { my ($chain, $rule, $let, $pos) = @_; return if ! @$rule; my $ord = @$chain % 10; if ($rule->[$ord]) { for ( @{$rule->[$ord]{letter}} ) { return 1 if $let eq $chain->[$_]{letter}; }; for ( @{$rule->[$ord]{position}} ) { return 1 if $let eq $chain->[$_]{position}; }; } else { for ( @{$rule->[-1]{letter}} ) { return 1 if $let eq $chain->[$_]{letter}; }; for ( @{$rule->[-1]{position}} ) { return 1 if $let eq $chain->[$_]{position}; }; } return; }