The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Build.PL 37
Changes 213
MANIFEST 33
META.json 0119
META.yml 4347
Makefile.PL 230
README 11
examples/jumping_cards.pl 33
inc/Test/Run/Builder.pm 11
lib/Games/LMSolve/Alice.pm 1616
lib/Games/LMSolve/Base.pm 4242
lib/Games/LMSolve/Input.pm 2424
lib/Games/LMSolve/Minotaur.pm 1515
lib/Games/LMSolve/Numbers.pm 1212
lib/Games/LMSolve/Plank/Base.pm 2929
lib/Games/LMSolve/Registry.pm 11
lib/Games/LMSolve/Tilt/Multi.pm 99
lib/Games/LMSolve/Tilt/RedBlue.pm 1414
lib/Games/LMSolve/Tilt/Single.pm 1010
lib/Games/LMSolve.pm 68
lm-solve 2121
lm-solve.spec 540
lm-solve.spec.in 540
scripts/gen_use_test.pl 1215
t/00use.t 11
t/cpan-changes.t 012
t/regression/regress.sh 22
t/style-trailing-space.t 029
28 files changed (This is a version diff) 401454
@@ -11,16 +11,21 @@ use Test::Run::Builder;
 
 my $build = Test::Run::Builder->new(
     module_name => "Games::LMSolve",
+    configure_requires =>
+    {
+        'Module::Build' => '0.36',
+    },
     build_requires =>
     {
         "Test::More" => 0,
     },
-    requires => 
+    requires =>
     {
         'English' => 0,
         'Exporter' => 0,
         'Getopt::Long' => 0,
         'Pod::Usage' => 0,
+        'perl' => '5.008',
         'strict' => 0,
         'vars' => 0,
         'warnings' => 0,
@@ -28,13 +33,12 @@ my $build = Test::Run::Builder->new(
     dist_author => 'Shlomi Fish <shlomif@iglu.org.il>',
     dist_version_from => "lib/Games/LMSolve/Base.pm",
     license => "mit",
-    create_makefile_pl => 'traditional',
     script_files => ["lm-solve"],
     meta_merge =>
     {
         resources =>
         {
-            repository => "http://svn.berlios.de/svnroot/repos/quad-pres/lm-solve/",
+            repository => "http://bitbucket.org/shlomif/lm-solve-source",
             homepage => "http://www.shlomifish.org/lm-solve/",
         },
         keywords =>
@@ -1,4 +1,15 @@
-0.8.4    Sun Jun 28 12:26:18 IDT 2009
+0.8.6   2014-01-30
+    - Minimum perl version set to 5.8.x (CPANTS KWalitee).
+
+0.8.5   2013-05-22
+    - Remove lm-solve.spec.in and lm-solve.spec .
+    - Remove Makefile.PL.
+    - Add t/style-trailing-space.t .
+        - Remove trailing space.
+    - Update URLs and E-mail addresses.
+    - Add t/cpan-changes.t and convert this file to CPAN::Changes format.
+
+0.8.4   2009-06-28
     - Changed COPYING to read MIT/X11 instead of Public Domain.
     - Changed the license in Build.PL to "mit".
     - Updated Test::Run::Builder to include ACTION_tags.
@@ -6,7 +17,7 @@
     - Added some "requires" (built-in, but still.).
     - Added resources and keywords to the META.yml / Build.PL .
 
-0.8.3
+0.8.3   2007-08-27
     - Added the Changes file.
     - Added the jumping_cards.pl example under examples.
     - Added the MIT X11 license as the LICENSE file.
@@ -20,16 +20,16 @@ lib/Games/LMSolve/Tilt/RedBlue.pm
 lib/Games/LMSolve/Tilt/Single.pm
 LICENSE
 lm-solve
-lm-solve.spec
-lm-solve.spec.in
-Makefile.PL
 MANIFEST
 META.yml                                Module meta-data (added by MakeMaker)
 prepare_package.sh
 README
 scripts/gen_use_test.pl
 t/00use.t
+t/cpan-changes.t
 TODO
 t/pod-coverage.t
 t/pod.t
+t/style-trailing-space.t
 t/regression/regress.sh
+META.json
@@ -0,0 +1,119 @@
+{
+   "abstract" : "base class for puzzle solvers.",
+   "author" : [
+      "Shlomi Fish <shlomif@iglu.org.il>"
+   ],
+   "dynamic_config" : 1,
+   "generated_by" : "Module::Build version 0.4007, CPAN::Meta::Converter version 2.132830",
+   "keywords" : [
+      "alice",
+      "brfs",
+      "dfs",
+      "game",
+      "games",
+      "inheritance",
+      "logic",
+      "logic mazes",
+      "mazes",
+      "minotaur",
+      "plank",
+      "pure-perl",
+      "puzzle",
+      "puzzles",
+      "riddle",
+      "riddles",
+      "scan",
+      "search",
+      "swamp",
+      "theseus",
+      "tilt"
+   ],
+   "license" : [
+      "mit"
+   ],
+   "meta-spec" : {
+      "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
+      "version" : "2"
+   },
+   "name" : "Games-LMSolve",
+   "prereqs" : {
+      "build" : {
+         "requires" : {
+            "Test::More" : "0"
+         }
+      },
+      "configure" : {
+         "requires" : {
+            "Module::Build" : "0.36"
+         }
+      },
+      "runtime" : {
+         "requires" : {
+            "English" : "0",
+            "Exporter" : "0",
+            "Getopt::Long" : "0",
+            "Pod::Usage" : "0",
+            "perl" : "5.008",
+            "strict" : "0",
+            "vars" : "0",
+            "warnings" : "0"
+         }
+      }
+   },
+   "provides" : {
+      "Games::LMSolve" : {
+         "file" : "lib/Games/LMSolve.pm"
+      },
+      "Games::LMSolve::Alice" : {
+         "file" : "lib/Games/LMSolve/Alice.pm"
+      },
+      "Games::LMSolve::Base" : {
+         "file" : "lib/Games/LMSolve/Base.pm",
+         "version" : "v0.8.6"
+      },
+      "Games::LMSolve::Input" : {
+         "file" : "lib/Games/LMSolve/Input.pm"
+      },
+      "Games::LMSolve::Input::Scalar::FH" : {
+         "file" : "lib/Games/LMSolve/Input.pm"
+      },
+      "Games::LMSolve::Minotaur" : {
+         "file" : "lib/Games/LMSolve/Minotaur.pm"
+      },
+      "Games::LMSolve::Numbers" : {
+         "file" : "lib/Games/LMSolve/Numbers.pm"
+      },
+      "Games::LMSolve::Plank::Base" : {
+         "file" : "lib/Games/LMSolve/Plank/Base.pm"
+      },
+      "Games::LMSolve::Plank::Hex" : {
+         "file" : "lib/Games/LMSolve/Plank/Hex.pm"
+      },
+      "Games::LMSolve::Registry" : {
+         "file" : "lib/Games/LMSolve/Registry.pm"
+      },
+      "Games::LMSolve::Tilt::Base" : {
+         "file" : "lib/Games/LMSolve/Tilt/Base.pm"
+      },
+      "Games::LMSolve::Tilt::Multi" : {
+         "file" : "lib/Games/LMSolve/Tilt/Multi.pm"
+      },
+      "Games::LMSolve::Tilt::RedBlue" : {
+         "file" : "lib/Games/LMSolve/Tilt/RedBlue.pm"
+      },
+      "Games::LMSolve::Tilt::Single" : {
+         "file" : "lib/Games/LMSolve/Tilt/Single.pm"
+      }
+   },
+   "release_status" : "stable",
+   "resources" : {
+      "homepage" : "http://www.shlomifish.org/lm-solve/",
+      "license" : [
+         "http://www.opensource.org/licenses/mit-license.php"
+      ],
+      "repository" : {
+         "url" : "http://bitbucket.org/shlomif/lm-solve-source"
+      }
+   },
+   "version" : "v0.8.6"
+}
@@ -1,24 +1,40 @@
 ---
-name: Games-LMSolve
-version: 0.8.4
+abstract: 'base class for puzzle solvers.'
 author:
   - 'Shlomi Fish <shlomif@iglu.org.il>'
-abstract: base class for puzzle solvers.
-license: mit
-resources:
-  homepage: http://www.shlomifish.org/lm-solve/
-  license: http://www.opensource.org/licenses/mit-license.php
-  repository: http://svn.berlios.de/svnroot/repos/quad-pres/lm-solve/
-requires:
-  English: 0
-  Exporter: 0
-  Getopt::Long: 0
-  Pod::Usage: 0
-  strict: 0
-  vars: 0
-  warnings: 0
 build_requires:
   Test::More: 0
+configure_requires:
+  Module::Build: 0.36
+dynamic_config: 1
+generated_by: 'Module::Build version 0.4007, CPAN::Meta::Converter version 2.132830'
+keywords:
+  - alice
+  - brfs
+  - dfs
+  - game
+  - games
+  - inheritance
+  - logic
+  - 'logic mazes'
+  - mazes
+  - minotaur
+  - plank
+  - pure-perl
+  - puzzle
+  - puzzles
+  - riddle
+  - riddles
+  - scan
+  - search
+  - swamp
+  - theseus
+  - tilt
+license: mit
+meta-spec:
+  url: http://module-build.sourceforge.net/META-spec-v1.4.html
+  version: 1.4
+name: Games-LMSolve
 provides:
   Games::LMSolve:
     file: lib/Games/LMSolve.pm
@@ -26,7 +42,7 @@ provides:
     file: lib/Games/LMSolve/Alice.pm
   Games::LMSolve::Base:
     file: lib/Games/LMSolve/Base.pm
-    version: 0.8.4
+    version: v0.8.6
   Games::LMSolve::Input:
     file: lib/Games/LMSolve/Input.pm
   Games::LMSolve::Input::Scalar::FH:
@@ -49,29 +65,17 @@ provides:
     file: lib/Games/LMSolve/Tilt/RedBlue.pm
   Games::LMSolve::Tilt::Single:
     file: lib/Games/LMSolve/Tilt/Single.pm
-generated_by: Module::Build version 0.33
-meta-spec:
-  url: http://module-build.sourceforge.net/META-spec-v1.4.html
-  version: 1.4
-keywords:
-  - alice
-  - brfs
-  - dfs
-  - game
-  - games
-  - inheritance
-  - logic
-  - logic mazes
-  - mazes
-  - minotaur
-  - plank
-  - pure-perl
-  - puzzle
-  - puzzles
-  - riddle
-  - riddles
-  - scan
-  - search
-  - swamp
-  - theseus
-  - tilt
+requires:
+  English: 0
+  Exporter: 0
+  Getopt::Long: 0
+  Pod::Usage: 0
+  perl: 5.008
+  strict: 0
+  vars: 0
+  warnings: 0
+resources:
+  homepage: http://www.shlomifish.org/lm-solve/
+  license: http://www.opensource.org/licenses/mit-license.php
+  repository: http://bitbucket.org/shlomif/lm-solve-source
+version: v0.8.6
@@ -1,23 +0,0 @@
-# Note: this file was auto-generated by Module::Build::Compat version 0.33
-use ExtUtils::MakeMaker;
-WriteMakefile
-(
-          'NAME' => 'Games::LMSolve',
-          'VERSION_FROM' => 'lib/Games/LMSolve/Base.pm',
-          'PREREQ_PM' => {
-                           'English' => 0,
-                           'Exporter' => 0,
-                           'Getopt::Long' => 0,
-                           'Pod::Usage' => 0,
-                           'Test::More' => 0,
-                           'strict' => 0,
-                           'vars' => 0,
-                           'warnings' => 0
-                         },
-          'INSTALLDIRS' => 'site',
-          'EXE_FILES' => [
-                           'lm-solve'
-                         ],
-          'PL_FILES' => {}
-        )
-;
@@ -14,7 +14,7 @@ Its version control repository is:
 
 http://svn.berlios.de/svnroot/repos/quad-pres/lm-solve/
 
-LM-Solve was written by Shlomi Fish (shlomif@vipe.technion.ac.il).
+LM-Solve was written by Shlomi Fish ( http://www.shlomifish.org/ ).
 
 Have fun!
 
@@ -31,7 +31,7 @@ sub pack_state
     return join(",", @$state_vector);
 }
 
-# A function that accepts an atom that represents a state 
+# A function that accepts an atom that represents a state
 # and returns an array ref that represents it.
 sub unpack_state
 {
@@ -40,7 +40,7 @@ sub unpack_state
     return [ split(/,/, $state) ];
 }
 
-# Accept an atom that represents a state and output a 
+# Accept an atom that represents a state and output a
 # user-readable string that describes it.
 sub display_state
 {
@@ -58,7 +58,7 @@ sub check_if_final_state
 }
 
 # This function enumerates the moves accessible to the state.
-# If it returns a move, it still does not mean that it is a valid 
+# If it returns a move, it still does not mean that it is a valid
 # one. I.e: it is possible that it is illegal to perform it.
 sub enumerate_moves
 {
@@ -54,7 +54,7 @@ sub do_test_run_tests
         Test::Run::CmdLine::Iface->new(
             {
                 'test_files' => [glob("t/*.t")],
-            }   
+            }
             # 'backend_params' => $self->_get_backend_params(),
         );
 
@@ -25,7 +25,7 @@ sub input_board
 
     my $filename = shift;
 
-    my $spec = 
+    my $spec =
     {
         'dims' => {'type' => "xy(integer)", 'required' => 1},
         'layout' => {'type' => "layout", 'required' => 1},
@@ -37,7 +37,7 @@ sub input_board
     my ($width, $height) = @{$input_fields->{'dims'}->{'value'}}{'x','y'};
 
     my (@board);
-    
+
     my $line;
     my $line_number=0;
     my $lines_ref = $input_fields->{'layout'}->{'value'};
@@ -54,8 +54,8 @@ sub input_board
 
     my $gen_exception = sub {
         my $text = shift;
-        die "$text on $filename at line " . 
-            ($input_fields->{'layout'}->{'line_num'} + $line_number + 1) . 
+        die "$text on $filename at line " .
+            ($input_fields->{'layout'}->{'line_num'} + $line_number + 1) .
             "!\n";
     };
 
@@ -72,17 +72,17 @@ sub input_board
         {
             $line =~ s/^\s+//;
             if ($line =~ /\S/)
-            {                
+            {
                 if ($line =~ /^\[([^\]]*)\]/)
                 {
                     my $flags_string = uc($1);
                     my @flags = (split(/,/, $flags_string));
                     my @dirs = (grep { exists($cell_dirs{$_}) } @flags);
                     my @flag_flags = (grep { exists($cell_flags{$_}) } @flags);
-                    my @unknown_flags = 
-                        (grep 
-                            { 
-                                (!exists($cell_dirs{$_})) && 
+                    my @unknown_flags =
+                        (grep
+                            {
+                                (!exists($cell_dirs{$_})) &&
                                 (!exists($cell_flags{$_}))
                             }
                             @flags
@@ -106,7 +106,7 @@ sub input_board
                         $start_x = $x;
                         $start_y = $y;
                     }
-                    $x++;                    
+                    $x++;
                     if ($x == $width)
                     {
                         $x = 0;
@@ -157,7 +157,7 @@ sub pack_state
     return pack("ccc", @{$state_vector});
 }
 
-# A function that accepts an atom that represents a state 
+# A function that accepts an atom that represents a state
 # and returns an array ref that represents it.
 sub unpack_state
 {
@@ -166,7 +166,7 @@ sub unpack_state
     return [ unpack("ccc", $state) ];
 }
 
-# Accept an atom that represents a state and output a 
+# Accept an atom that represents a state and output a
 # user-readable string that describes it.
 sub display_state
 {
@@ -182,7 +182,7 @@ sub check_if_unsolvable
 {
     my $self = shift;
     my $coords = shift;
-    return ($coords->[2] == 0);    
+    return ($coords->[2] == 0);
 }
 
 sub check_if_final_state
@@ -194,7 +194,7 @@ sub check_if_final_state
 }
 
 # This function enumerates the moves accessible to the state.
-# If it returns a move, it still does not mean that it is a valid 
+# If it returns a move, it still does not mean that it is a valid
 # one. I.e: it is possible that it is illegal to perform it.
 sub enumerate_moves
 {
@@ -221,7 +221,7 @@ sub perform_move
     $new_coords[1] += $offsets->[1];
 
     my $new_cell = $self->{'board'}->[$new_coords[1]][$new_coords[0]]->{'flags'};
-    
+
     # Check if we are out of the bounds of the board.
     if (($new_coords[0] < 0) || ($new_coords[0] >= $self->{'width'}) ||
         ($new_coords[1] < 0) || ($new_coords[1] >= $self->{'height'}) ||
@@ -230,7 +230,7 @@ sub perform_move
     {
         return undef;
     }
-    
+
     if (exists($new_cell->{'ADD'}))
     {
         $new_coords[2]++;
@@ -7,7 +7,7 @@ use Getopt::Long;
 
 use vars qw($VERSION);
 
-$VERSION = '0.8.4';
+$VERSION = '0.8.6';
 
 use Exporter;
 
@@ -19,7 +19,7 @@ use vars qw(@ISA @EXPORT_OK);
 
 use vars qw(%cell_dirs);
 
-%cell_dirs = 
+%cell_dirs =
     (
         'N' => [0,-1],
         'NW' => [-1,-1],
@@ -40,7 +40,7 @@ Games::LMSolve::Base - base class for puzzle solvers.
     package MyPuzzle::Solver;
 
     use Games::LMSolve::Base;
-    
+
     @ISA = qw(Games::LMSolve::Base);
 
     # Override these methods:
@@ -53,7 +53,7 @@ Games::LMSolve::Base - base class for puzzle solvers.
     sub enumerate_moves { ... }
     sub perform_move { ... }
 
-    # Optionally: 
+    # Optionally:
     sub render_move { ... }
     sub check_if_unsolvable { ... }
 
@@ -64,7 +64,7 @@ Games::LMSolve::Base - base class for puzzle solvers.
     $self->solve_board($filename);
 
 =head1 DESCRIPTION
-    
+
 This class implements a generic solver for single player games. In order
 to use it, one must inherit from it and implement some abstract methods.
 Afterwards, its interface functions can be invoked to actually solve
@@ -92,7 +92,7 @@ sub new
 
     $self->initialize(@_);
 
-    return $self;    
+    return $self;
 }
 
 sub initialize
@@ -139,7 +139,7 @@ sub main
     my $run_time_states_display = 0;
 
     #my $p = Getopt::Long::Parser->new();
-    if (! GetOptions('rle!' => \$to_rle, 
+    if (! GetOptions('rle!' => \$to_rle,
         'output-states!' => \$output_states,
         'method=s' => \$scan,
         'rtd!' => \$run_time_states_display,
@@ -169,7 +169,7 @@ sub main
 =head1 METHODS TO OVERRIDE
 
 =cut
-    
+
 
 
 
@@ -177,13 +177,13 @@ sub _die_on_abstract_function
 {
     my ($package, $filename, $line, $subroutine, $hasargs,
         $wantarray, $evaltext, $is_require, $hints, $bitmask) = caller(1);
-    die ("The abstract function $subroutine() was " . 
+    die ("The abstract function $subroutine() was " .
         "called, while it needs to be overrided by the derived class.\n");
 }
 
 =head2 input_board($self, $file_spec)
 
-This method is responsible to read the "board" (the permanent parameters) of 
+This method is responsible to read the "board" (the permanent parameters) of
 the puzzle and its initial state. It should place the board in the object's
 keys, and return the initial state. (in unpacked format).
 
@@ -204,7 +204,7 @@ sub input_board
 =head2 pack_state($self, $state_vector)
 
 This function accepts a state in unpacked form and should return it in packed
-format. A state in unpacked form can be any perl scalar (as complex as you 
+format. A state in unpacked form can be any perl scalar (as complex as you
 like). A state in packed form must be a string.
 
 =cut
@@ -223,7 +223,7 @@ expanded form.
 
 =cut
 
-# A function that accepts an atom that represents a state 
+# A function that accepts an atom that represents a state
 # and returns an array ref that represents it.
 sub unpack_state
 {
@@ -232,12 +232,12 @@ sub unpack_state
 
 =head2 display_state($self, $packed_state)
 
-Accepts a packed state and should return the user-readable string 
+Accepts a packed state and should return the user-readable string
 representation of the state.
 
 =cut
 
-# Accept an atom that represents a state and output a 
+# Accept an atom that represents a state and output a
 # user-readable string that describes it.
 sub display_state
 {
@@ -246,7 +246,7 @@ sub display_state
 
 =head2 check_if_final_state($self, $state_vector)
 
-This function should return 1 if the expanded state $state_vector is 
+This function should return 1 if the expanded state $state_vector is
 a final state, and the game is over.
 
 =cut
@@ -264,7 +264,7 @@ that can be performed on this state.
 =cut
 
 # This function enumerates the moves accessible to the state.
-# If it returns a move, it still does not mean that this move is a valid 
+# If it returns a move, it still does not mean that this move is a valid
 # one. I.e: it is possible that it is illegal to perform it.
 sub enumerate_moves
 {
@@ -331,12 +331,12 @@ sub _solve_brfs_or_dfs
     my $state_collection = $self->{'state_collection'};
     my $is_dfs = shift;
     my %args = @_;
-    
+
     my $run_time_display = $self->{'cmd_line'}->{'rt_states_display'};
     my $rtd_callback = $self->{'run_time_display_callback'};
     my $max_iters = $args{'max_iters'} || (-1);
     my $check_iters = ($max_iters >= 0);
-    
+
     my (@queue, $state, $coords, $depth, @moves, $new_state);
 
     if (exists($args{'initial_state'}))
@@ -380,7 +380,7 @@ sub _solve_brfs_or_dfs
             );
             # print ((" " x $depth) . join(",", @$coords) . " M=" . $self->render_move($state_collection->{$state}->{'m'}) ."\n");
         }
-        
+
         if ($self->check_if_unsolvable($coords))
         {
             next;
@@ -391,7 +391,7 @@ sub _solve_brfs_or_dfs
             @ret = ("solved", $state);
             goto Return;
         }
-        
+
         @moves = $self->enumerate_moves($coords);
 
         foreach my $m (@moves)
@@ -402,21 +402,21 @@ sub _solve_brfs_or_dfs
             {
                 next;
             }
-            
+
             $new_state = $self->pack_state($new_coords);
             if (! exists($state_collection->{$new_state}))
             {
-                $state_collection->{$new_state} = 
+                $state_collection->{$new_state} =
                     {
-                        'p' => $state, 
-                        'm' => $m, 
+                        'p' => $state,
+                        'm' => $m,
                         'd' => ($depth+1)
                     };
                 push @queue, $new_state;
             }
         }
-    }    
-    
+    }
+
     Return:
 
     return @ret;
@@ -434,7 +434,7 @@ sub _run_length_encoding
     {
         if ($m eq $prev_m)
         {
-            $count++;            
+            $count++;
         }
         else
         {
@@ -445,20 +445,20 @@ sub _run_length_encoding
     }
     push @ret, [$prev_m, $count];
 
-    return @ret;    
+    return @ret;
 }
 
 
 sub _solve_state
 {
     my $self = shift;
-    
+
     my $initial_coords = shift;
-    
+
     my $state = $self->pack_state($initial_coords);
     $self->{'state_collection'}->{$state} = {'p' => undef, 'd' => 0};
 
-    return 
+    return
         $self->run_scan(
             'initial_state' => $state,
             @_
@@ -467,8 +467,8 @@ sub _solve_state
 
 =head2 $self->solve_board($file_spec, %args)
 
-Solves the board specification specified in $file_spec. %args specifies 
-optional arguments. Currently there is one: 'max_iters' that specifies the 
+Solves the board specification specified in $file_spec. %args specifies
+optional arguments. Currently there is one: 'max_iters' that specifies the
 maximal iterations to run.
 
 Returns whatever run_scan returns.
@@ -477,7 +477,7 @@ Returns whatever run_scan returns.
 sub solve_board
 {
     my $self = shift;
-    
+
     my $filename = shift;
 
     my $initial_coords = $self->input_board($filename);
@@ -490,10 +490,10 @@ sub solve_board
 Continues the current scan. %args may contain the 'max_iters' parameter
 to specify a maximal iterations limit.
 
-Returns two values. The first is a progress indicator. "solved" means the 
+Returns two values. The first is a progress indicator. "solved" means the
 puzzle was solved. "unsolved" means that all the states were covered and
 the puzzle was proven to be unsolvable. "interrupted" means that the
-scan was interrupted in the middle, and could be proved to be either 
+scan was interrupted in the middle, and could be proved to be either
 solvable or unsolvable.
 
 The second argument is the final state and is valid only if the progress
@@ -507,7 +507,7 @@ sub run_scan
 
     my %args = @_;
 
-    return 
+    return
         $scan_functions{$self->{'cmd_line'}->{'scan'}}->(
             $self,
             %args
@@ -545,13 +545,13 @@ sub display_solution
     my $output_states = $self->{'cmd_line'}->{'output_states'};
     my $to_rle = $self->{'cmd_line'}->{'to_rle'};
 
-    my $echo_state = 
+    my $echo_state =
         sub {
             my $state = shift;
-            return $output_states ? 
+            return $output_states ?
                 ($self->display_state($state) . ": Move = ") :
                 "";
-        };    
+        };
 
     print $ret[0], "\n";
 
@@ -589,7 +589,7 @@ sub display_solution
             for($num_state=0;$num_state<scalar(@moves);$num_state++)
             {
                 print $echo_state->($states[$num_state]) . $self->render_move($moves[$num_state]) . "\n";
-            }            
+            }
         }
         if ($output_states)
         {
@@ -645,7 +645,7 @@ L<Games::LMSolve::Input>
 
 Shlomi Fish, L<http://www.shlomifish.org/>
 
-=cut 
+=cut
 
 1;
 
@@ -47,10 +47,10 @@ Games::LMSolve::Input - input class for LM-Solve
     my $spec =
     {
         'dims' => { 'type' => "xy(integer)", 'required' => 1, },
-        'planks' => { 'type' => "array(start_end(xy(integer)))", 
+        'planks' => { 'type' => "array(start_end(xy(integer)))",
                       'required' => 1,
                     },
-        'layout' => { 'type' => "layout", 'required' => 1,},        
+        'layout' => { 'type' => "layout", 'required' => 1,},
     };
 
     my $input_fields = $input_obj->input_board($filename, $spec);
@@ -90,15 +90,15 @@ sub _initialize
 
 =head2 $self->input_board($file_spec, $spec);
 
-This method accepts two arguments. C<$file_spec> which is the filename, 
-reference to a filehandle, or reference to the text containing the board 
+This method accepts two arguments. C<$file_spec> which is the filename,
+reference to a filehandle, or reference to the text containing the board
 specification.
 
-$spec is a specification of the board given as a reference to a hash. 
+$spec is a specification of the board given as a reference to a hash.
 The keys are the keys inside the file. The values are references
 to hashes containing parameters. The 'required' parameter is given to
 specify that an exception should be thrown if this key was not specified. The
-other parameter (a mandatory one) is type which specified the type of the 
+other parameter (a mandatory one) is type which specified the type of the
 value. Available types are:
 
 =over 8
@@ -118,10 +118,10 @@ reference to an array of (X,Y) pairs.
 
 =item array(start_end(xy(integer)))
 
-An array of [((SX1,SX2)->(EX1,EX2)), ((SX1,SX2)->(EX1,EX2))...] pairs of 
-(X,Y) pairs. Will be returned as a reference to an array of 
+An array of [((SX1,SX2)->(EX1,EX2)), ((SX1,SX2)->(EX1,EX2))...] pairs of
+(X,Y) pairs. Will be returned as a reference to an array of
 
-    { 
+    {
         'start' => { 'x' => $start_x, 'y' => $start_y },
         'end' => { 'x' => $end_x, 'y' => $end_y },
     }
@@ -158,8 +158,8 @@ sub input_board
             die "Failed to read \"$filename\" : $OS_ERROR";
 
         $file_ref = \*I;
-        $filename_str = ($filename eq "-") ? 
-            "standard input" : 
+        $filename_str = ($filename eq "-") ?
+            "standard input" :
             "\"$filename\"";
     }
     elsif (ref($file_spec) eq "GLOB")
@@ -177,7 +177,7 @@ sub input_board
     {
         die "Unknown file specification passed to input_board!";
     }
-    
+
     # Now we have the filehandle *$file_ref opened.
 
     my $line;
@@ -216,8 +216,8 @@ sub input_board
             # Save the line number for safekeeping because a layout or
             # other multi-line value can increase it.
             my $key_line_num = $line_num;
-            
-            
+
+
 
             if (! exists ($spec->{$key}))
             {
@@ -255,9 +255,9 @@ sub input_board
             }
             elsif ($type eq "array(xy(integer))")
             {
-                
+
                 if ($line =~ /^\[\s*$xy_pair(\s*\,\s*$xy_pair)*\s*\]\s*$/)
-                {                    
+                {
                     my @elements = ($line =~ m/$xy_pair/g);
                     my @pairs;
                     while (scalar(@elements))
@@ -284,9 +284,9 @@ sub input_board
                     {
                         my ($sx,$sy,$ex,$ey) = @elements[0 .. 3];
                         @elements = @elements[4 .. $#elements];
-                        push @pairs, 
-                            { 
-                                'start' => { 'x'=>$sx , 'y'=>$sy }, 
+                        push @pairs,
+                            {
+                                'start' => { 'x'=>$sx , 'y'=>$sy },
                                 'end' => { 'x' => $ex, 'y' => $ey }
                             };
                     }
@@ -294,7 +294,7 @@ sub input_board
                 }
                 else
                 {
-                    $gen_exception->("Key \"$key\" expects an array of integral (sx,sy) -> (ex,ey) start/end x,y pairs as a value");                    
+                    $gen_exception->("Key \"$key\" expects an array of integral (sx,sy) -> (ex,ey) start/end x,y pairs as a value");
                 }
             }
             elsif ($type eq "layout")
@@ -345,7 +345,7 @@ sub input_board
             }
         }
     }
-    
+
     return $ret;
 }
 
@@ -364,7 +364,7 @@ sub input_horiz_vert_walls_layout
     my $lines_ptr = shift;
 
     my (@vert_walls, @horiz_walls);
-    
+
     my $line;
     my $line_num = 0;
     my $y;
@@ -380,7 +380,7 @@ sub input_horiz_vert_walls_layout
         my $msg = shift;
         die ($msg . " at line " . ($line_num+$lines_ptr->{'line_num'}+1));
     };
-    
+
 
     my $input_horiz_wall = sub {
         $line = $get_next_line->();
@@ -407,7 +407,7 @@ sub input_horiz_vert_walls_layout
         }
         push @vert_walls, [ (map { $_ eq "|" } split(//, $line)) ];
     };
-    
+
 
 
     for($y=0;$y<$height;$y++)
@@ -16,7 +16,7 @@ sub input_board
     my $self = shift;
     my $filename = shift;
 
-    my $spec = 
+    my $spec =
     {
         (map { $_ => { 'type' => "xy(integer)", 'required' => 1} } (qw(dims thes mino exit))),
         'layout' => { 'type' => "layout", 'required' => 1},
@@ -24,8 +24,8 @@ sub input_board
 
     my $input_obj = Games::LMSolve::Input->new();
     my $input_fields = $input_obj->input_board($filename, $spec);
-    
-    my ($width, $height) = @{$input_fields->{'dims'}->{'value'}}{'x','y'};    
+
+    my ($width, $height) = @{$input_fields->{'dims'}->{'value'}}{'x','y'};
     my ($thes_x, $thes_y) = @{$input_fields->{'thes'}->{'value'}}{'x','y'};
     my ($mino_x, $mino_y) = @{$input_fields->{'mino'}->{'value'}}{'x','y'};
     my ($exit_x, $exit_y) = @{$input_fields->{'exit'}->{'value'}}{'x','y'};
@@ -39,13 +39,13 @@ sub input_board
     {
         die "The minotaur is out of bounds of the board in file \"$filename\"!\n";
     }
-    
+
     if (($exit_x >= $width) || ($exit_y >= $height))
     {
         die "The exit is out of bounds of the board in file \"$filename\"!\n";
     }
 
-    my ($horiz_walls, $vert_walls) = 
+    my ($horiz_walls, $vert_walls) =
         $input_obj->input_horiz_vert_walls_layout($width, $height, $input_fields->{'layout'});
 
     $self->{'width'} = $width;
@@ -64,7 +64,7 @@ sub _mino_move
     my $horiz_walls = $self->{'horiz_walls'};
     my $vert_walls = $self->{'vert_walls'};
 
-    my ($thes_x, $thes_y, $mino_x, $mino_y) = @_; 
+    my ($thes_x, $thes_y, $mino_x, $mino_y) = @_;
     for(my $t=0;$t<2;$t++)
     {
         if (($thes_x < $mino_x) && (! $vert_walls->[$mino_y][$mino_x]))
@@ -97,7 +97,7 @@ sub pack_state
     return pack("cccc", @{$state_vector});
 }
 
-# A function that accepts an atom that represents a state 
+# A function that accepts an atom that represents a state
 # and returns an array ref that represents it.
 sub unpack_state
 {
@@ -106,7 +106,7 @@ sub unpack_state
     return [ unpack("cccc", $state) ];
 }
 
-# Accept an atom that represents a state and output a 
+# Accept an atom that represents a state and output a
 # user-readable string that describes it.
 sub display_state
 {
@@ -137,7 +137,7 @@ sub check_if_final_state
 
 
 # This function enumerates the moves accessible to the state.
-# If it returns a move, it still does not mean that it is a valid 
+# If it returns a move, it still does not mean that it is a valid
 # one. I.e: it is possible that it is illegal to perform it.
 sub enumerate_moves
 {
@@ -145,11 +145,11 @@ sub enumerate_moves
 
     my $horiz_walls = $self->{'horiz_walls'};
     my $vert_walls = $self->{'vert_walls'};
-    
+
     my $coords = shift;
 
     my ($thes_x, $thes_y) = @$coords[0..1];
-    
+
     my @moves;
 
     if (! $vert_walls->[$thes_y][$thes_x])
@@ -173,11 +173,11 @@ sub enumerate_moves
     return @moves;
 }
 
-my %translate_moves = 
+my %translate_moves =
     (
-        "u" => [0, -1], 
-        "d" => [0, 1], 
-        "l" => [-1,0], 
+        "u" => [0, -1],
+        "d" => [0, 1],
+        "l" => [-1,0],
         "r" => [1,0],
         "w" => [0,0],
     );
@@ -9,7 +9,7 @@ use vars qw(@ISA);
 
 @ISA=qw(Games::LMSolve::Base);
 
-my %cell_dirs = 
+my %cell_dirs =
     (
         'N' => [0,-1],
         'S' => [0,1],
@@ -23,7 +23,7 @@ sub input_board
 
     my $filename = shift;
 
-    my $spec = 
+    my $spec =
     {
         'dims' => {'type' => "xy(integer)", 'required' => 1},
         'start' => {'type' => "xy(integer)", 'required' => 1},
@@ -31,11 +31,11 @@ sub input_board
     };
 
     my $input_obj = Games::LMSolve::Input->new();
-    my $input_fields = $input_obj->input_board($filename, $spec); 
+    my $input_fields = $input_obj->input_board($filename, $spec);
     my ($width, $height) = @{$input_fields->{'dims'}->{'value'}}{'x','y'};
     my ($start_x, $start_y) = @{$input_fields->{'start'}->{'value'}}{'x','y'};
     my (@board);
-    
+
     my $line;
     my $line_number=0;
     my $lines_ref = $input_fields->{'layout'}->{'value'};
@@ -52,8 +52,8 @@ sub input_board
 
     my $gen_exception = sub {
         my $text = shift;
-        die "$text on $filename at line " . 
-            ($input_fields->{'layout'}->{'line_num'} + $line_number + 1) . 
+        die "$text on $filename at line " .
+            ($input_fields->{'layout'}->{'line_num'} + $line_number + 1) .
             "!\n";
     };
 
@@ -103,7 +103,7 @@ sub pack_state
     return pack("cc", @{$state_vector});
 }
 
-# A function that accepts an atom that represents a state 
+# A function that accepts an atom that represents a state
 # and returns an array ref that represents it.
 sub unpack_state
 {
@@ -112,7 +112,7 @@ sub unpack_state
     return [ unpack("cc", $state) ];
 }
 
-# Accept an atom that represents a state and output a 
+# Accept an atom that represents a state and output a
 # user-readable string that describes it.
 sub display_state
 {
@@ -131,7 +131,7 @@ sub check_if_final_state
 }
 
 # This function enumerates the moves accessible to the state.
-# If it returns a move, it still does not mean that it is a valid 
+# If it returns a move, it still does not mean that it is a valid
 # one. I.e: it is possible that it is illegal to perform it.
 sub enumerate_moves
 {
@@ -145,7 +145,7 @@ sub enumerate_moves
     my $step = $self->{'board'}->[$y][$x];
 
     my @moves;
-    
+
     if ($x + $step < $self->{'width'})
     {
         push @moves, "E";
@@ -166,8 +166,8 @@ sub enumerate_moves
     {
         push @moves, "N";
     }
-    
-    return @moves;   
+
+    return @moves;
 }
 
 # This function accepts a state and a move. It tries to perform the
@@ -29,10 +29,10 @@ sub input_board
     my $spec =
     {
         'dims' => { 'type' => "xy(integer)", 'required' => 1, },
-        'planks' => { 'type' => "array(start_end(xy(integer)))", 
+        'planks' => { 'type' => "array(start_end(xy(integer)))",
                       'required' => 1,
                     },
-        'layout' => { 'type' => "layout", 'required' => 1,},        
+        'layout' => { 'type' => "layout", 'required' => 1,},
     };
 
     my $input_obj = Games::LMSolve::Input->new();
@@ -68,13 +68,13 @@ sub input_board
             }
             $x++;
         }
-        push @board, $l;        
+        push @board, $l;
     }
     if (!defined($goal_x))
     {
         die "The Goal was not defined in the layout";
     }
-    
+
     my $planks_in = $input_fields->{'planks'}->{'value'};
 
     my @planks;
@@ -94,11 +94,11 @@ sub input_board
             {
                 die "Plank cannot be placed at point ($end_x,$end_y)!";
             }
-        };        
+        };
 
         my $plank_str = "Plank ($start_x,$start_y) ==> ($end_x,$end_y)";
 
-        if (($start_x >= $width) || ($end_x >= $width) || 
+        if (($start_x >= $width) || ($end_x >= $width) ||
             ($start_y >= $height) || ($end_y >= $height))
         {
             die "$plank_str is out of the boundaries of the board";
@@ -159,11 +159,11 @@ sub input_board
             {
                 die "$plank_str is not aligned horizontally or vertically.";
             }
-            return 
-                { 
-                    'len' => ($end_x - $start_x), 
-                    'start' => 
-                        { 
+            return
+                {
+                    'len' => ($end_x - $start_x),
+                    'start' =>
+                        {
                             'x' => $start_x,
                             'y' => $start_y,
                         },
@@ -175,7 +175,7 @@ sub input_board
             die "$plank_str is not aligned horizontally or vertically.";
         }
     };
-    
+
     foreach my $p (@$planks_in)
     {
         push @planks, $get_plank->($p);
@@ -187,7 +187,7 @@ sub input_board
     $self->{'goal_y'} = $goal_y;
     $self->{'board'} = \@board;
     $self->{'plank_lens'} = [ map { $_->{'len'} } @planks ];
-    
+
     my $state = [ 0,  (map { ($_->{'start'}->{'x'}, $_->{'start'}->{'y'}, (($_->{'dir'} eq "E") ? 0 : ($_->{'dir'} eq "SE") ? 2 : 1)) } @planks) ];
     $self->_process_plank_data($state);
 
@@ -209,27 +209,27 @@ sub _process_plank_data
 
     my $active = $state->[0];
 
-    my @planks = 
-        (map 
-            { 
-                { 
-                    'len' => $self->{'plank_lens'}->[$_], 
-                    'x' => $state->[$_*3+1], 
-                    'y' => $state->[$_*3+1+1], 
+    my @planks =
+        (map
+            {
+                {
+                    'len' => $self->{'plank_lens'}->[$_],
+                    'x' => $state->[$_*3+1],
+                    'y' => $state->[$_*3+1+1],
                     'dir' => $state->[$_*3+2+1],
                     'active' => 0,
-                } 
-            } 
+                }
+            }
             (0 .. (scalar(@{$self->{'plank_lens'}}) - 1))
         );
 
-   
+
     foreach my $p (@planks)
     {
         my $p_dir = $p->{'dir'};
         my $dir = ($p_dir == 0) ? "E" : ($p_dir == 1) ? "S" : "SE";
         $p->{'dir'} = $dir;
-    
+
         $p->{'end_x'} = $p->{'x'} + $cell_dirs{$dir}->[0] * $p->{'len'};
         $p->{'end_y'} = $p->{'y'} + $cell_dirs{$dir}->[1] * $p->{'len'};
     }
@@ -315,8 +315,8 @@ sub check_if_final_state
     my $goal_x = $self->{'goal_x'};
     my $goal_y = $self->{'goal_y'};
 
-    return (scalar(grep { (($_->{'x'} == $goal_x) && ($_->{'y'} == $goal_y)) || 
-                  (($_->{'end_x'} == $goal_x) && ($_->{'end_y'} == $goal_y)) 
+    return (scalar(grep { (($_->{'x'} == $goal_x) && ($_->{'y'} == $goal_y)) ||
+                  (($_->{'end_x'} == $goal_x) && ($_->{'end_y'} == $goal_y))
                 }
                 @$plank_data) > 0);
 }
@@ -381,7 +381,7 @@ sub enumerate_moves
                     {
                         my $ix = $x + $cell_dirs{$dir}->[0] * $offset;
                         my $iy = $y + $cell_dirs{$dir}->[1] * $offset;
-                        
+
                         if ($board->[$iy]->[$ix])
                         {
                             next DIR_LOOP;
@@ -461,7 +461,7 @@ sub perform_move
     {
         $dir_idx = 2;
         $y -= $self->{'plank_lens'}->[$p];
-        $x -= $self->{'plank_lens'}->[$p];        
+        $x -= $self->{'plank_lens'}->[$p];
     }
     elsif ($dir eq "SE")
     {
@@ -474,7 +474,7 @@ sub perform_move
     @$new_state[(1+$p*3) .. (1+$p*3+2)] = ($x,$y,$dir_idx);
 
     $self->_process_plank_data($new_state);
-    
+
     return $new_state;
 }
 
@@ -11,7 +11,7 @@ Games::LMSolve::Registry - the registry of all LM-Solve drivers.
 
 This is a registry of all LM-Solve drivers.
 
-=head1 METHODS 
+=head1 METHODS
 =cut
 
 use Games::LMSolve;
@@ -15,8 +15,8 @@ sub input_board
 {
     my $self = shift;
     my $filename = shift;
-    
-    my $spec = 
+
+    my $spec =
     {
         'dims' => { 'type' => "xy(integer)", 'required' => 1 },
         'start' => { 'type' => "xy(integer)", 'required' => 1 },
@@ -31,10 +31,10 @@ sub input_board
     my ($width, $height) = @{$input_fields->{'dims'}->{'value'}}{'x','y'};
     my ($start_x, $start_y) = @{$input_fields->{'start'}->{'value'}}{'x','y'};
 
-    
+
     if (($start_x >= $width) || ($start_y >= $height))
     {
-        die "The Starting position is out of bounds of the board in file \"$filename\"!\n";        
+        die "The Starting position is out of bounds of the board in file \"$filename\"!\n";
     }
 
     my @goals_map = map { [ (0) x $width ] } (1 .. $height);
@@ -52,7 +52,7 @@ sub input_board
         $goal_id++;
     }
 
-    my ($horiz_walls, $vert_walls) = 
+    my ($horiz_walls, $vert_walls) =
         $input_obj->input_horiz_vert_walls_layout($width, $height, $input_fields->{'layout'});
 
     $self->{'width'} = $width;
@@ -69,9 +69,9 @@ sub input_board
     {
         $dest_goals_bitmap |= (1 << $i);
     }
-    
+
     $self->{'dest_goals_bitmap'} = $dest_goals_bitmap;
-    
+
     return [ $start_x, $start_y, $reached_goals_bitmap ];
 }
 
@@ -122,7 +122,7 @@ sub perform_move
     my $coords = shift;
     my $move = shift;
 
-    my ($new_coords, $intermediate_states) = 
+    my ($new_coords, $intermediate_states) =
         $self->move_ball_to_end($coords, $move);
 
     my $goal_bitmap = $coords->[2];
@@ -138,7 +138,7 @@ sub perform_move
             $goal_bitmap |= (1<<$goal);
         }
     }
-    
+
     return [ @$new_coords, $goal_bitmap];
 }
 
@@ -15,14 +15,14 @@ sub input_board
 {
     my $self = shift;
     my $filename = shift;
-    
-    my $spec = 
+
+    my $spec =
     {
         'dims' => { 'type' => "xy(integer)", 'required' => 1 },
         'red_start' => { 'type' => "xy(integer)", 'required' => 1 },
         'red_goal' => {'type' => "xy(integer)", 'required' => 1 },
         'blue_start' => { 'type' => "xy(integer)", 'required' => 1 },
-        'blue_goal' => {'type' => "xy(integer)", 'required' => 1 },        
+        'blue_goal' => {'type' => "xy(integer)", 'required' => 1 },
         'layout' => { 'type' => "layout", 'required' => 1},
     };
 
@@ -36,29 +36,29 @@ sub input_board
     my ($blue_start_x, $blue_start_y) = @{$input_fields->{'blue_start'}->{'value'}}{'x','y'};
     my ($blue_goal_x, $blue_goal_y) = @{$input_fields->{'blue_goal'}->{'value'}}{'x','y'};
 
-    
+
     if (($red_start_x >= $width) || ($red_start_y >= $height))
     {
-        die "The starting position of the red block is out of bounds of the board in file \"$filename\"!\n";        
+        die "The starting position of the red block is out of bounds of the board in file \"$filename\"!\n";
     }
 
     if (($red_goal_x >= $width) || ($red_goal_y >= $height))
     {
-        die "The goal position of the red block is out of bounds of the board in file \"$filename\"!\n";        
+        die "The goal position of the red block is out of bounds of the board in file \"$filename\"!\n";
     }
 
     if (($blue_start_x >= $width) || ($blue_start_y >= $height))
     {
-        die "The starting position of the blue block is out of bounds of the board in file \"$filename\"!\n";        
+        die "The starting position of the blue block is out of bounds of the board in file \"$filename\"!\n";
     }
 
     if (($blue_goal_x >= $width) || ($blue_goal_y >= $height))
     {
-        die "The goal position of the blue block is out of bounds of the board in file \"$filename\"!\n";        
+        die "The goal position of the blue block is out of bounds of the board in file \"$filename\"!\n";
     }
-    
 
-    my ($horiz_walls, $vert_walls) = 
+
+    my ($horiz_walls, $vert_walls) =
         $input_obj->input_horiz_vert_walls_layout($width, $height, $input_fields->{'layout'});
 
     $self->{'width'} = $width;
@@ -67,7 +67,7 @@ sub input_board
 
     $self->{'horiz_walls'} = $horiz_walls;
     $self->{'vert_walls'} = $vert_walls;
-    
+
     return [ $red_start_x, $red_start_y, $blue_start_x, $blue_start_y];
 }
 
@@ -128,12 +128,12 @@ sub perform_move
 
     my ($rx, $ry, $bx, $by) = @$coords;
 
-    my ($red_new_coords, $red_intermediate_states) = 
+    my ($red_new_coords, $red_intermediate_states) =
         $self->move_ball_to_end([ $rx, $ry], $move);
 
-    my ($blue_new_coords, $blue_intermediate_states) = 
+    my ($blue_new_coords, $blue_intermediate_states) =
         $self->move_ball_to_end([ $bx, $by], $move);
-    
+
     return [ @$red_new_coords, @$blue_new_coords ];
 }
 
@@ -15,8 +15,8 @@ sub input_board
 {
     my $self = shift;
     my $filename = shift;
-    
-    my $spec = 
+
+    my $spec =
     {
         'dims' => { 'type' => "xy(integer)", 'required' => 1 },
         'start' => { 'type' => "xy(integer)", 'required' => 1 },
@@ -31,18 +31,18 @@ sub input_board
     my ($width, $height) = @{$input_fields->{'dims'}->{'value'}}{'x','y'};
     my ($start_x, $start_y) = @{$input_fields->{'start'}->{'value'}}{'x','y'};
     my ($goal_x, $goal_y) = @{$input_fields->{'goal'}->{'value'}}{'x','y'};
-    
+
     if (($start_x >= $width) || ($start_y >= $height))
     {
-        die "The starting position is out of bounds of the board in file \"$filename\"!\n";        
+        die "The starting position is out of bounds of the board in file \"$filename\"!\n";
     }
 
     if (($goal_x >= $width) || ($goal_y >= $height))
     {
-        die "The goal position is out of bounds of the board in file \"$filename\"!\n";        
+        die "The goal position is out of bounds of the board in file \"$filename\"!\n";
     }
 
-    my ($horiz_walls, $vert_walls) = 
+    my ($horiz_walls, $vert_walls) =
         $input_obj->input_horiz_vert_walls_layout($width, $height, $input_fields->{'layout'});
 
     $self->{'width'} = $width;
@@ -51,8 +51,8 @@ sub input_board
     $self->{'goal_y'} = $goal_y;
     $self->{'horiz_walls'} = $horiz_walls;
     $self->{'vert_walls'} = $vert_walls;
-    
-    return [ $start_x, $start_y ];    
+
+    return [ $start_x, $start_y ];
 }
 
 sub pack_state
@@ -102,9 +102,9 @@ sub perform_move
     my $coords = shift;
     my $move = shift;
 
-    my ($new_coords, $intermediate_states) = 
+    my ($new_coords, $intermediate_states) =
         $self->move_ball_to_end($coords, $move);
-    
+
     return $new_coords;
 }
 
@@ -3,6 +3,8 @@ package Games::LMSolve;
 use strict;
 use warnings;
 
+use 5.008;
+
 use Getopt::Long;
 use Pod::Usage;
 
@@ -26,7 +28,7 @@ Games::LMSolve - base class for LM-Solve solvers factories
     package MyReg;
 
     use Games::LMSolve;
-    
+
     @ISA = qw(Games::LMSolve);
 
     use MyPuzzle::Solver;
@@ -86,7 +88,7 @@ sub new
 
     $self->_initialize(@_);
 
-    return $self;    
+    return $self;
 }
 
 sub _initialize
@@ -94,7 +96,7 @@ sub _initialize
     my $self = shift;
 
     my %args = @_;
-    
+
     $self->{'games_solvers'} = {};
 
     $self->register_all_solvers();
@@ -103,7 +105,7 @@ sub _initialize
     {
         $self->set_default_variant($args{'default_variant'});
     }
-    
+
     return 0;
 }
 
@@ -172,8 +174,8 @@ sub main
 
     Getopt::Long::Configure('pass_through');
     GetOptions(
-        "g|game=s" => \$variant, 
-        'help|h|?' => \$help, 
+        "g|game=s" => \$variant,
+        'help|h|?' => \$help,
         'man' => \$man
         ) or pod2usage(2);
 
@@ -20,8 +20,8 @@ B<lm-solve> [options] I<Input File>
 
 =head1 DESCRIPTION
 
-This program is a front end for the LM-Solve Perl modules that 
-can be used to solve any of the number of Logic Mazes present on the 
+This program is a front end for the LM-Solve Perl modules that
+can be used to solve any of the number of Logic Mazes present on the
 Logic Mazes site (http://www.logicmazes.com/) and similar sites.
 
 To use this program you should create a text file describing the layout
@@ -57,7 +57,7 @@ B<minotaur> - Theseus and the Minotaur Mazes
 
 B<numbers> - Number Mazes
 
-B<plank> - Planks in the Swamp Puzzles 
+B<plank> - Planks in the Swamp Puzzles
 
 B<tilt_single> - Tilt Mazes with one goal
 
@@ -89,7 +89,7 @@ B<dfs> - Depth-First Search.
 
 =item B<--rtd> B<--nortd>
 
-B<--rtd> stands for "Run-Time Display". This option will print the states 
+B<--rtd> stands for "Run-Time Display". This option will print the states
 of the scan that were arrived to, as the scan encounters them. The default is
 B<--nortd>.
 
@@ -102,11 +102,11 @@ line, in the format "key=value". A value can be an integer (e.g: "x=6"),
 an (x,y) integral pair (e.g: "dims=(3,6)"), an array of pairs (e.g:
 "goals="[(5,6), (3,8), (0, 3)]"), an array of start and end pairs
 (e.g: "Planks = [ ((0,2) -> (3,2)) , ((6,5) -> (7,5)) ]")
-or a layout specification. The latter begins with "<<EOF" where EOF is a 
-terminator and extends from the next line down to the first line 
+or a layout specification. The latter begins with "<<EOF" where EOF is a
+terminator and extends from the next line down to the first line
 containing the terminator.
 
-Whitespace and newlines are generally ignored and the keys are 
+Whitespace and newlines are generally ignored and the keys are
 case-insensitive.
 
 =head1 Alice Mazes Board Format
@@ -116,7 +116,7 @@ is the layout of the board. The cells are specified row by row, from top to
 bottom and from left to right. Newlines and whitespace between each cell
 are ignored as well as lines beginning with a sharp-sign ("#").
 
-Each cell is surrounded by square brackets and contains several flags 
+Each cell is surrounded by square brackets and contains several flags
 separated by commas. The flags are:
 
 =over 8
@@ -194,12 +194,12 @@ Examples can be found in the layouts archive.
 =head1 Number Mazes Board Format
 
 Dims is an (x,y) key that specifies the dimensions of the board. Start
-is an (x,y) key that specifies the starting position (starting from (0,0) 
-at the top-left corner). The key layout is a layout key that contains 
+is an (x,y) key that specifies the starting position (starting from (0,0)
+at the top-left corner). The key layout is a layout key that contains
 the layout of the board.
 
 The layout contains a line for every row, and every cell is represented as
-a character. It contains a digit for its number or an asterisk ("*") if it 
+a character. It contains a digit for its number or an asterisk ("*") if it
 is the goal cell.
 
 Examples can be found in the layouts archive.
@@ -225,15 +225,15 @@ Minotaur's mazes.
 =head1 Red-Blue Tilt Puzzles
 
 Dims is an (x,y) key that specifies the dimensions of the board. Blue_Start
-and Red_Start are two (x,y) keys which specify the starting positiones of 
+and Red_Start are two (x,y) keys which specify the starting positiones of
 the red and blue markers. Red_Goal and Blue_Goal are their respective goals.
 
-layout contains a scheme of horizontal and vertical walls similar to the 
+layout contains a scheme of horizontal and vertical walls similar to the
 Minotaur's mazes.
 
 =head1 Planks in the Swamp Puzzles
 
-Dims is an (x,y) key that specifies the dimensions of the board. Planks is 
+Dims is an (x,y) key that specifies the dimensions of the board. Planks is
 an array of start and end pairs specifying the start and end coordinates
 of the planks. layout is a layout that matches the size specified by Dims
 that has an X where a stump is present, G where the goal is
@@ -244,21 +244,21 @@ The first plank in "Planks" is the active plank.
 
 =head1 SEE ALSO
 
-B<LM-Solve's Homepage>: 
+B<LM-Solve's Homepage>:
 
-http://vipe.technion.ac.il/~shlomif/lm-solve/
+L<http://www.shlomifish.org/lm-solve/>
 
-B<The Logic Mazes Homepage>: 
+B<The Logic Mazes Homepage>:
 
-http://www.logicmazes.com/
+L<http://www.logicmazes.com/>
 
-B<Click Mazes>: 
+B<Click Mazes>:
 
-http://www.gjnem.demon.co.uk/
+L<http://www.gjnem.demon.co.uk/>
 
 =head1 AUTHOR
 
-Shlomi Fish <shlomif@vipe.technion.ac.il>
+Shlomi Fish, L<http://www.shlomifish.org/> .
 
 =cut
 
@@ -1,54 +0,0 @@
-Name: lm-solve
-Version: 0.8.2
-Release: 1
-Group: Amusement/Games
-Source: http://vipe.technion.ac.il/~shlomif/lm-solve/Games-LMSolve-%{version}.tar.gz
-Buildroot: %{_tmppath}/%{name}-buildroot
-Requires: perl
-URL: http://vipe.technion.ac.il/~shlomif/lm-solve/
-Prefix: %{_prefix}
-License: Public Domain
-BuildArch: noarch
-Summary: Perl-based solver for various types of logic mazes
-
-%description
-LM-Solve is a solver for various types of Logic Mazes as features on the 
-Logic Mazes site (http://www.logicmazes.com/). Currently it supports Alice 
-Mazes, Number Mazes, Plank Puzzles, Theseus and the Minotaur Mazes and
-three type of Tilt Mazes (single goal, multiple goals and red-blue tilt 
-puzzles)
-
-%prep
-%setup -q -n Games-LMSolve-%{version}
-
-
-%build
-# %{__perl} Makefile.PL PREFIX=%{prefix} INST_MAN1DIR=%{_mandir}/man1 INST_MAN3DIR=%{_mandir}/man3 < /dev/null
-%{__perl} Makefile.PL PREFIX=%{prefix} < /dev/null
-make OPTIMIZE="$RPM_OPT_FLAGS" PREFIX=%{prefix}
-make test
-
-%install
-rm -rf $RPM_BUILD_ROOT
-%makeinstall PREFIX=$RPM_BUILD_ROOT%{prefix} INSTALLMAN1DIR=$RPM_BUILD_ROOT%{_mandir}/man1 INSTALLSITEMAN1DIR=$RPM_BUILD_ROOT%{_mandir}/man1 INSTALLVENDORMAN1DIR=$RPM_BUILD_ROOT%{_mandir}/man1
-rm -f `find $RPM_BUILD_ROOT -name perllocal.pod`
-
-%clean
-rm -fr $RPM_BUILD_ROOT
-
-%files
-%defattr (-,root,root)
-%doc README TODO MANIFEST COPYING INSTALL
-%{_bindir}/*
-%{_mandir}/*/*
-%{_libdir}/perl5/site_perl/*/Games
-
-%changelog
-* Mon Jul 21 2003 Shlomi Fish <shlomif@vipe.technion.ac.il> 0.7.4-1
-- Adapted to the new namespace.
-- Added some MAN1DIR's to the make install to get it to install the man
-  page properly
-
-* Sat Jul 27 2002 Shlomi Fish <shlomif@vipe.technion.ac.il> 0.5.3-1
-- First working version of the SPEC.
-
@@ -1,54 +0,0 @@
-Name: lm-solve
-Version: [[VERSION]]
-Release: 1
-Group: Amusement/Games
-Source: http://vipe.technion.ac.il/~shlomif/lm-solve/Games-LMSolve-%{version}.tar.gz
-Buildroot: %{_tmppath}/%{name}-buildroot
-Requires: perl
-URL: http://vipe.technion.ac.il/~shlomif/lm-solve/
-Prefix: %{_prefix}
-License: Public Domain
-BuildArch: noarch
-Summary: Perl-based solver for various types of logic mazes
-
-%description
-LM-Solve is a solver for various types of Logic Mazes as features on the 
-Logic Mazes site (http://www.logicmazes.com/). Currently it supports Alice 
-Mazes, Number Mazes, Plank Puzzles, Theseus and the Minotaur Mazes and
-three type of Tilt Mazes (single goal, multiple goals and red-blue tilt 
-puzzles)
-
-%prep
-%setup -q -n Games-LMSolve-%{version}
-
-
-%build
-# %{__perl} Makefile.PL PREFIX=%{prefix} INST_MAN1DIR=%{_mandir}/man1 INST_MAN3DIR=%{_mandir}/man3 < /dev/null
-%{__perl} Makefile.PL PREFIX=%{prefix} < /dev/null
-make OPTIMIZE="$RPM_OPT_FLAGS" PREFIX=%{prefix}
-make test
-
-%install
-rm -rf $RPM_BUILD_ROOT
-%makeinstall PREFIX=$RPM_BUILD_ROOT%{prefix} INSTALLMAN1DIR=$RPM_BUILD_ROOT%{_mandir}/man1 INSTALLSITEMAN1DIR=$RPM_BUILD_ROOT%{_mandir}/man1 INSTALLVENDORMAN1DIR=$RPM_BUILD_ROOT%{_mandir}/man1
-rm -f `find $RPM_BUILD_ROOT -name perllocal.pod`
-
-%clean
-rm -fr $RPM_BUILD_ROOT
-
-%files
-%defattr (-,root,root)
-%doc README TODO MANIFEST COPYING INSTALL
-%{_bindir}/*
-%{_mandir}/*/*
-%{_libdir}/perl5/site_perl/*/Games
-
-%changelog
-* Mon Jul 21 2003 Shlomi Fish <shlomif@vipe.technion.ac.il> 0.7.4-1
-- Adapted to the new namespace.
-- Added some MAN1DIR's to the make install to get it to install the man
-  page properly
-
-* Sat Jul 27 2002 Shlomi Fish <shlomif@vipe.technion.ac.il> 0.5.3-1
-- First working version of the SPEC.
-
@@ -1,13 +1,16 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl
 
 use strict;
+use warnings;
+
+use autodie;
 
-my @modules = 
+my @modules =
     (
-        (map 
-            { 
-                "Games::LMSolve::$_" 
-            } 
+        (map
+            {
+                "Games::LMSolve::$_"
+            }
             qw(Numbers Base Plank::Base Plank::Hex Alice),
             qw(Tilt::Base Tilt::Single Tilt::Multi Tilt::RedBlue),
             qw(Input Registry)
@@ -17,23 +20,23 @@ my @modules =
 
 my $num_modules = scalar(@modules);
 
-open O, ">t/00use.t";
-print O <<"EOF" ;
+open my $out_fh, ">t/00use.t";
+print {$out_fh} <<"EOF" ;
 #!/usr/bin/perl -w
 
 use strict;
 
 use Test::More tests => $num_modules;
 
-BEGIN 
+BEGIN
 {
 EOF
 
 foreach (@modules)
 {
-    print O "use_ok(\"$_\");\n";
+    print {$out_fh} "use_ok(\"$_\");\n";
 }
 
-print O "}\n";
+print {$out_fh} "}\n";
 
-close(O);
+close ($out_fh);
@@ -4,7 +4,7 @@ use strict;
 
 use Test::More tests => 12;
 
-BEGIN 
+BEGIN
 {
 use_ok("Games::LMSolve::Numbers");
 use_ok("Games::LMSolve::Base");
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More;
+
+eval 'use Test::CPAN::Changes';
+plan skip_all => 'Test::CPAN::Changes required for this test' if $@;
+
+changes_ok();
+
@@ -20,8 +20,8 @@ for TYPE in "alice alice" "minotaur minotaur" "plank plank" \
         echo "$dir does not exist"
     fi
     mkdir -p checksums/$dir
-    (cd ./layouts/$dir/; ls) | 
-        (while read T ; do 
+    (cd ./layouts/$dir/; ls) |
+        (while read T ; do
             if [ -f ./layouts/$dir/$T ] ; then
                 run_lm_solve brfs
                 run_lm_solve dfs
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More;
+
+eval "use Test::TrailingSpace";
+if ($@)
+{
+    plan skip_all => "Test::TrailingSpace required for trailing space test.";
+}
+else
+{
+    plan tests => 1;
+}
+
+my $finder = Test::TrailingSpace->new(
+    {
+        root => '.',
+        filename_regex => qr/(?:(?:\.(?:t|pm|pl|PL|yml|json|arc|vim))|README|Changes|LICENSE|MANIFEST)\z/,
+    },
+);
+
+# TEST
+$finder->no_trailing_space(
+    "No trailing space was found."
+);
+