This program, Attack, solves a superset of the "Eight Queens Problem".

In the Eight Queens Problem, you must place 8 queens on 8 separate squares of a chessboard in such a way that no queen is attacking any other.  I wanted to generalize the problem to allow pieces other than queens, as well as combinations of pieces, such as 4 queens and 6 bishops, or 3 kings, a rook and 17 knights.

Ultimately, the program needed to do several thing:

  1. Effectively perform an arbitrary number of loops, through the use of recursion; something I discussed a few days ago in this node.
  2. Incorporate the logic necessary to "short-circuit" recursion into positions which had already been tried.
  3. Find ways to optimize the speed of the search, thus minimizing the time needed to calculate large numbers of boards.
  4. Allow user-configuration of various interesting parameters, including how much information is displayed for each solution, the width and height of the board, and even the ability to create new, "hypothetical" pieces, with legal moves unlike any of those in traditional chess.

Two separate files are needed.  The first is the program itself, called attack (or attack.pl).  The second is a module called Legal.pm; it contains the legal moves for each piece on each square of the board, in a huge hash.

Here is the attack program:

#!/usr/bin/perl -w # # Solves the general case of which the "Eight Queens" problem is # a single example, whereby 2 or more major chess pieces are placed # on a standard chess board such that no piece attacks another. # # 060113 by liverpole # ############## ### Strict ### ############## use strict; use warnings; #################### ### User-defined ### #################### my $version = "1.0 (060113)"; # The current program version my $attack_symbol = "."; # Symbol for an attacked squar +e my $nticks = 1024; # How often is progress update +d? # Which pieces are allowed? The order is important; putting more powe +rful # pieces first in the string causes them to be used first, which will +tend # to speed up the program when more than 1 kind of piece is used. # my $allowed_pieces = "QRGCBNK"; ################# ### Libraries ### ################# use Data::Dumper; use Getopt::Long; use File::Basename; use Legal; #################### ### Declarations ### #################### sub elapsed_time; sub show_board; sub show_progress; sub try_each_piece_each_square; sub try_each_square; ############### ### Globals ### ############### $| = 1; my $iam = basename $0; my $verbosity = 0; # Level of verbosity my $b_progress = 0; # Display search progress? my $b_one_solution = 0; # Quit after first successful solutions my $show_attacks = 0; # Display attacked squares? my $nrows = 8; # Board has how many rows? (Default = 8) my $ncols = 8; # Board has how many cols? (Default = 8) my @rows = qw( 1 2 3 4 5 6 7 8 ); my @cols = qw( a b c d e f g h ); my $border = "+---+---+---+---+---+---+---+---+"; my $syntax = " syntax: $iam [switches] <chess piece(s)> Solves a generalized version of the 'eight queens' problem, whe +reby some number of major chess pieces (usually 8 queens) of the same c +olor have to be placed on a chess board in such a way that no piece att +acks any other. (For the purposes of this program, a 'major piece' is + any piece other than a pawn). The command-line arguments are each strings of characters represen +ting chess pieces, from the set {K, Q, R, B, N} (where 'N' stands for + the 'knight'). As a notational convenience, any piece may be followe +d by a count indicating the number of that piece to use. For example, + the original 'eight queens' problem can be solved using either 'QQQQQ +QQQ' or 'Q8'. Or, to solve the problem of 3 queens, 2 rooks and 2 knig +hts, the following are all legal: 'QQQ RR NN', 'Q3 R2 N2', and 'Q3R2 +N2'. Switches: -r <nrows> ... Specify alternate # of rows (from 2 to 8) -c <ncols> ... Specify alternate # of cols (from 2 to 8) -a ........... Label squares under attack (forces -vv) -1 ........... Quit after 1st solution found (forces -vv) -p ........... Display search progress every $nticks boards -v ........... Verbose; display solutions (1 per line) -vv .......... Very verbose; display board for each solution "; #################### ### Command-line ### #################### Getopt::Long::Configure("bundling"); GetOptions( "r=i" => \$nrows, "c=i" => \$ncols, "a" => \$show_attacks, "1" => \$b_one_solution, "p" => \$b_progress, "v+" => \$verbosity, ); my ($pieces, %pieces, @pieces); $pieces = uc join('', @ARGV) or die $syntax; while ($pieces =~ s/([$allowed_pieces])(\d*)//i) { $pieces{$1} += $2 | +| 1 } foreach my $piece (split(//, $allowed_pieces)) { push @pieces, (lc $piece) x ($pieces{$piece} || 0); } (@pieces > 1) or die "$iam: need at least 2 pieces from '$allowed_pie +ces'\n"; ($nrows < 2 || $nrows > 8) and die "$iam: # of rows must be in {2...8 +}\n"; ($ncols < 2 || $ncols > 8) and die "$iam: # of cols must be in {2...8 +}\n"; ($b_one_solution or $show_attacks) and $verbosity = 2; #################### ### Main program ### #################### my $plegal = new Legal(); @rows = splice(@rows, 0, $nrows); @cols = splice(@cols, 0, $ncols); my @all_legal_squares; $border = ' ' . ("+---" x $ncols) . '+'; foreach my $col (@cols) { foreach my $row (@rows) { push @all_legal_squares, "$col$row"; } } # The number of levels of recursion is equal to the number of pieces my $N = @pieces; my $start = time; try_each_piece_each_square($N, 0, \@pieces); ################### ### Subroutines ### ################### # # sub try_each_square # # Tries putting a given piece on every available square of the board. # The piece will only be placed if it doesn't attack any piece alread +y # on the board, nor itself comes under attack from any piece already +on # the board. # # Whenever a piece is successfully placed, a recursive call back into # try_each_piece_each_square() occurs to try placing another availabl +e # piece. # sub try_each_square { my ($N, $plevel, $ppieces, $pboard, $piece, $pp) = @_; # Save the current set of legal squares remaining for this piece my @saved_legal_moves = @{$pp->{'legal'}->{$piece}}; my $nattacks = $pp->{'nattacks'}; SQUARE: while (my $square = shift @{$pp->{'legal'}->{$piece}}) { # If the square is not empty, skip to the next square. defined($pboard->{$square}) and next; # Increment the total number of boards tried my $nboards = ++$pp->{'nboards'}; # If search progress was requested (-p) and enough new boards +have # been tried, issue a one-line progress report. # if ($b_progress && $nboards - $pp->{'lastboard'} >= $nticks) { show_progress($pp); } # If the square is under attack, skip to the next square. ($nattacks->{$square} > 0) and next; # If putting the given piece on the given square would attack # another piece already on the board, skip to the next square. # my $pthis = $plegal->attacks($piece, $square); map { defined($pboard->{$_}) and next SQUARE } @$pthis; # Place the piece on the board, ... $pboard->{$square} = $piece; # ... mark the squares it attacks ... map { ++$nattacks->{$_} } @$pthis; # ... and try more pieces on other squares ... try_each_piece_each_square($N, $plevel, $ppieces, $pboard, $pp +); # ... and finally, remove the piece from the square, and # demote the squares it attacks. # delete $pboard->{$square}; map { --$nattacks->{$_} } @$pthis; } # Reset the current legal moves $pp->{'legal'}->{$piece} = [ @saved_legal_moves ]; } # # sub try_each_piece_each_square # # Tries putting each piece on every square of the board. For every p +iece # left to try placing, a recursive call is made to try_each_square(), + which # will call this subroutine again with any position which placed the +piece # successfully. If all pieces are placed, that qualifies as a soluti +on. # sub try_each_piece_each_square { my ($N, $plevel, $ppieces, $pboard, $pp) = @_; # Check level my $level = (!$plevel)? 1: $$plevel + 1; # Initialization (Called once at the beginning of all loops) if (1 == $level) { # Called prior to the first loop only # The struct 'pp' is a pointer to 'persistent' data; variables # which we want to be able to modify at different recursion le +vels. # $pboard = { }; my $nattacks = { map { $_ => 0 } @all_legal_squares }; $pp = { 'nsolutions' => 0, # Total solutions found 'nboards' => 0, # Total boards tried 'lastboard' => 0, # Last board displayed 'legal' => { }, # All legal squares (for a giv +en piece) 'nattacks' => $nattacks, # Level of attack on each squa +re }; } # Call loop N times if ($level <= $N) { # If this piece is the first piece of any being placed, or # or first piece of this type -- allow all legal squares to # be considered for the piece. # my $piece = $ppieces->[$level - 1]; if ($level < 2 or $ppieces->[$level - 2] ne $piece) { $pp->{'legal'}->{$piece} = [ @all_legal_squares ]; } # Then see whether placing the piece onto the board would atta +ck # any other square. If NOT, place it, and invoke a new loop. # try_each_square($N, \$level, $ppieces, $pboard, $piece, $pp); } else { # If we get this far, we've got a board in which none of the p +ieces # attack any others! Increment the count, and (optionally) di +splay # the board. # ++$pp->{'nsolutions'}; # Increment solutions found $verbosity and show_board($pboard, $pp); $b_one_solution and die "Found solution -- quitting\n"; } # Finalization (Called once at the end of all loops) if (0 == --$level) { show_progress($pp, 1); } } # # sub elapsed_time # # Returns a string containing the current elapsed time nicely formatt +ed. # sub elapsed_time { my $nsecs = time - $start; my $hours = int($nsecs / 3600); $nsecs -= 3600 * $hours; my $mins = int($nsecs / 60); $nsecs -= 60 * $mins; return sprintf "%02d:%02d:%02d", $hours, $mins, $nsecs; } # # sub show_progress # # Shows the current elapsed time, the number of solutions found, # the total number of boards tried, and the solution rate as a # percentage. # sub show_progress { my ($pp, $b_final) = @_; my $pct = 100 * $pp->{'nsolutions'} / $pp->{'nboards'}; printf STDERR "%s ", elapsed_time(); $b_final and print STDERR "<Final> "; printf STDERR "Solutions: %-d ", $pp->{'nsolutions'}; printf STDERR "Boards: %-d ", $pp->{'nboards'}; printf STDERR "Rate: %.3f%% \r", $pct; $pp->{'lastboard'} = $pp->{'nboards'}; $b_final and print STDERR "\n\n"; $b_final or ++$b_progress; } # # sub show_board # # Displays the given board in shorthand notation. If the verbosity l +evel # is high enough (-vv), displays an ascii representation of the board + with # all the pieces on it. # sub show_board { my ($pboard, $pp) = @_; if ($b_progress > 1) { print STDERR "\n"; $b_progress = 1; } my $sol = join(' ', map { $_ . uc $pboard->{$_} } sort keys %$pboa +rd); my $nsolutions = $pp->{'nsolutions'}; my $nboards = $pp->{'nboards'}; printf STDERR "%s ", elapsed_time(); printf "Solution # %-d Board # %-d [%s]\n", $nsolutions, $nboard +s, $sol; if ($verbosity > 1) { print "$border\n"; foreach my $row (reverse @rows) { print " | "; foreach my $col (@cols) { my $square = "${col}${row}"; my $piece = uc $pboard->{$square} || " "; if ($show_attacks && $piece eq " ") { if ($plegal->is_attacked($pboard, $square)) { $piece = $attack_symbol; } } printf "$piece | "; } print "$row\n$border\n"; } printf " %s\n\n", join(' ', @cols); } }
and here is the Legal.pm module:
package Legal; ############## ### Strict ### ############## use strict; use warnings; ################# ### Libraries ### ################# use Data::Dumper; my $p_legal_moves = { # The King 'k' => { 'a1' => [ [ qw( a2 b1 b2 ) ] ], 'a2' => [ [ qw( a3 b3 b2 b1 a1 ) ] ], 'a3' => [ [ qw( a4 b4 b3 b2 a2 ) ] ], 'a4' => [ [ qw( a5 b5 b4 b3 a3 ) ] ], 'a5' => [ [ qw( a6 b6 b5 b4 a4 ) ] ], 'a6' => [ [ qw( a5 a7 b7 b6 b5 ) ] ], 'a7' => [ [ qw( a8 b8 b7 b6 a6 ) ] ], 'a8' => [ [ qw( b8 b7 a7 ) ] ], 'b1' => [ [ qw( a1 a2 b2 c2 c1 ) ] ], 'b2' => [ [ qw( a1 a2 a3 b3 c3 c2 c1 b1 ) ] ], 'b3' => [ [ qw( a2 a3 a4 b4 c4 c3 c2 b2 ) ] ], 'b4' => [ [ qw( a3 a4 a5 b5 c5 c4 c3 b3 ) ] ], 'b5' => [ [ qw( a4 a5 a6 b6 c6 c5 c4 b4 ) ] ], 'b6' => [ [ qw( a5 a6 a7 b7 c7 c6 c5 b5 ) ] ], 'b7' => [ [ qw( a6 a7 a8 b8 c8 c7 c6 b6 ) ] ], 'b8' => [ [ qw( a7 a8 c8 c7 b7 ) ] ], 'c1' => [ [ qw( b1 b2 c2 d2 d1 ) ] ], 'c2' => [ [ qw( b1 b2 b3 c3 d3 d2 d1 c1 ) ] ], 'c3' => [ [ qw( b2 b3 b4 c4 d4 d3 d2 c2 ) ] ], 'c4' => [ [ qw( b3 b4 b5 c5 d5 d4 d3 c3 ) ] ], 'c5' => [ [ qw( b4 b5 b6 c6 d6 d5 d4 c4 ) ] ], 'c6' => [ [ qw( b5 b6 b7 c7 d7 d6 d5 c5 ) ] ], 'c7' => [ [ qw( b6 b7 b8 c8 d8 d7 d6 c6 ) ] ], 'c8' => [ [ qw( b7 b8 d8 d7 c7 ) ] ], 'd1' => [ [ qw( c1 c2 d2 e2 e1 ) ] ], 'd2' => [ [ qw( c1 c2 c3 d3 e3 e2 e1 d1 ) ] ], 'd3' => [ [ qw( c2 c3 c4 d4 e4 e3 e2 d2 ) ] ], 'd4' => [ [ qw( c3 c4 c5 d5 e5 e4 e3 d3 ) ] ], 'd5' => [ [ qw( c4 c5 c6 d6 e6 e5 e4 d4 ) ] ], 'd6' => [ [ qw( c5 c6 c7 d7 e7 e6 e5 d5 ) ] ], 'd7' => [ [ qw( c6 c7 c8 d8 e8 e7 e6 d6 ) ] ], 'd8' => [ [ qw( c7 c8 e8 e7 d7 ) ] ], 'e1' => [ [ qw( d1 d2 e2 f2 f1 ) ] ], 'e2' => [ [ qw( d1 d2 d3 e3 f3 f2 f1 e1 ) ] ], 'e3' => [ [ qw( d2 d3 d4 e4 f4 f3 f2 e2 ) ] ], 'e4' => [ [ qw( d3 d4 d5 e5 f5 f4 f3 e3 ) ] ], 'e5' => [ [ qw( d4 d5 d6 e6 f6 f5 f4 e4 ) ] ], 'e6' => [ [ qw( d5 d6 d7 e7 f7 f6 f5 e5 ) ] ], 'e7' => [ [ qw( d6 d7 d8 e8 f8 f7 f6 e6 ) ] ], 'e8' => [ [ qw( d7 d8 f8 f7 e7 ) ] ], 'f1' => [ [ qw( e1 e2 f2 g2 g1 ) ] ], 'f2' => [ [ qw( e1 e2 e3 f3 g3 g2 g1 f1 ) ] ], 'f3' => [ [ qw( e2 e3 e4 f4 g4 g3 g2 f2 ) ] ], 'f4' => [ [ qw( e3 e4 e5 f5 g5 g4 g3 f3 ) ] ], 'f5' => [ [ qw( e4 e5 e6 f6 g6 g5 g4 f4 ) ] ], 'f6' => [ [ qw( e5 e6 e7 f7 g7 g6 g5 f5 ) ] ], 'f7' => [ [ qw( e6 e7 e8 f8 g8 g7 g6 f6 ) ] ], 'f8' => [ [ qw( e7 e8 g8 g7 f7 ) ] ], 'g1' => [ [ qw( f1 f2 g2 h2 h1 ) ] ], 'g2' => [ [ qw( f1 f2 f3 g3 h3 h2 h1 g1 ) ] ], 'g3' => [ [ qw( f2 f3 f4 g4 h4 h3 h2 g2 ) ] ], 'g4' => [ [ qw( f3 f4 f5 g5 h5 h4 h3 g3 ) ] ], 'g5' => [ [ qw( f4 f5 f6 g6 h6 h5 h4 g4 ) ] ], 'g6' => [ [ qw( f5 f6 f7 g7 h7 h6 h5 g5 ) ] ], 'g7' => [ [ qw( f6 f7 f8 g8 h8 h7 h6 g6 ) ] ], 'g8' => [ [ qw( f7 f8 h8 h7 g7 ) ] ], 'h1' => [ [ qw( g1 g2 h2 ) ] ], 'h2' => [ [ qw( g1 g2 g3 h3 h1 ) ] ], 'h3' => [ [ qw( g2 g3 g4 h4 h2 ) ] ], 'h4' => [ [ qw( g3 g4 g5 h5 h3 ) ] ], 'h5' => [ [ qw( g4 g5 g6 h6 h4 ) ] ], 'h6' => [ [ qw( g5 g6 g7 h7 h5 ) ] ], 'h7' => [ [ qw( g6 g7 g8 h8 h6 ) ] ], 'h8' => [ [ qw( g7 g8 h7 ) ] ], }, # The Queen 'q' => { 'a1' => [ [ qw( b2 c3 d4 e5 f6 g7 h8 ) ], [ qw( a2 a3 a4 a5 a6 a7 a8 ) ], [ qw( b1 c1 d1 e1 f1 g1 h1 ) ], ], 'a2' => [ [ qw( b3 c4 d5 e6 f7 g8 ) ], [ qw( b1 ) ], [ qw( a3 a4 a5 a6 a7 a8 ) ], [ qw( a1 ) ], [ qw( b2 c2 d2 e2 f2 g2 h2 ) ], ], 'a3' => [ [ qw( b4 c5 d6 e7 f8 ) ], [ qw( b2 c1 ) ], [ qw( a4 a5 a6 a7 a8 ) ], [ qw( b3 c3 d3 e3 f3 g3 h3 ) ], [ qw( a2 a1 ) ], ], 'a4' => [ [ qw( b5 c6 d7 e8 ) ], [ qw( b3 c2 d1 ) ], [ qw( a5 a6 a7 a8 ) ], [ qw( b4 c4 d4 e4 f4 g4 h4 ) ], [ qw( a3 a2 a1 ) ], ], 'a5' => [ [ qw( b6 c7 d8 ) ], [ qw( b4 c3 d2 e1 ) ], [ qw( a6 a7 a8 ) ], [ qw( b5 c5 d5 e5 f5 g5 h5 ) ], [ qw( a4 a3 a2 a1 ) ], ], 'a6' => [ [ qw( b7 c8 ) ], [ qw( b5 c4 d3 e2 f1 ) ], [ qw( a7 a8 ) ], [ qw( b6 c6 d6 e6 f6 g6 h6 ) ], [ qw( a5 a4 a3 a2 a1 ) ], ], 'a7' => [ [ qw( b8 ) ], [ qw( b6 c5 d4 e3 f2 g1 ) ], [ qw( a8 ) ], [ qw( b7 c7 d7 e7 f7 g7 h7 ) ], [ qw( a6 a5 a4 a3 a2 a1 ) ], ], 'a8' => [ [ qw( b7 c6 d5 e4 f3 g2 h1 ) ], [ qw( b8 c8 d8 e8 f8 g8 h8 ) ], [ qw( a7 a6 a5 a4 a3 a2 a1 ) ], ], 'b1' => [ [ qw( a2 ) ], [ qw( c2 d3 e4 f5 g6 h7 ) ], [ qw( a1 ) ], [ qw( b2 b3 b4 b5 b6 b7 b8 ) ], [ qw( c1 d1 e1 f1 g1 h1 ) ], ], 'b2' => [ [ qw( a3 ) ], [ qw( c3 d4 e5 f6 g7 h8 ) ], [ qw( c1 ) ], [ qw( a1 ) ], [ qw( a2 ) ], [ qw( b3 b4 b5 b6 b7 b8 ) ], [ qw( c2 d2 e2 f2 g2 h2 ) ], [ qw( b1 ) ], ], 'b3' => [ [ qw( a4 ) ], [ qw( c4 d5 e6 f7 g8 ) ], [ qw( c2 d1 ) ], [ qw( a2 ) ], [ qw( a3 ) ], [ qw( b4 b5 b6 b7 b8 ) ], [ qw( c3 d3 e3 f3 g3 h3 ) ], [ qw( b2 b1 ) ], ], 'b4' => [ [ qw( a5 ) ], [ qw( c5 d6 e7 f8 ) ], [ qw( c3 d2 e1 ) ], [ qw( a3 ) ], [ qw( a4 ) ], [ qw( b5 b6 b7 b8 ) ], [ qw( c4 d4 e4 f4 g4 h4 ) ], [ qw( b3 b2 b1 ) ], ], 'b5' => [ [ qw( a6 ) ], [ qw( c6 d7 e8 ) ], [ qw( c4 d3 e2 f1 ) ], [ qw( a4 ) ], [ qw( a5 ) ], [ qw( b6 b7 b8 ) ], [ qw( c5 d5 e5 f5 g5 h5 ) ], [ qw( b4 b3 b2 b1 ) ], ], 'b6' => [ [ qw( a7 ) ], [ qw( c7 d8 ) ], [ qw( c5 d4 e3 f2 g1 ) ], [ qw( a5 ) ], [ qw( a6 ) ], [ qw( b7 b8 ) ], [ qw( c6 d6 e6 f6 g6 h6 ) ], [ qw( b5 b4 b3 b2 b1 ) ], ], 'b7' => [ [ qw( a8 ) ], [ qw( c8 ) ], [ qw( c6 d5 e4 f3 h1 ) ], [ qw( a6 ) ], [ qw( a7 ) ], [ qw( b8 ) ], [ qw( c7 d7 e7 f7 g7 h7 ) ], [ qw( b6 b5 b4 b3 b2 b1 ) ], ], 'b8' => [ [ qw( c7 d6 e5 f4 g3 h2 ) ], [ qw( a7 ) ], [ qw( a8 ) ], [ qw( c8 d8 e8 f8 g8 h8 ) ], [ qw( b7 b6 b5 b4 b3 b2 b1 ) ], ], 'c1' => [ [ qw( b2 a3 ) ], [ qw( d2 e3 f4 g5 h6 ) ], [ qw( b1 a1 ) ], [ qw( c2 c3 c4 c5 c6 c7 c8 ) ], [ qw( d1 e1 f1 g1 h1 ) ], ], 'c2' => [ [ qw( b3 a4 ) ], [ qw( d3 e4 f5 g6 h7 ) ], [ qw( d1 ) ], [ qw( b1 ) ], [ qw( b2 a2 ) ], [ qw( c3 c4 c5 c6 c7 c8 ) ], [ qw( d2 e2 f2 g2 h2 ) ], [ qw( c1 ) ], ], 'c3' => [ [ qw( b4 a5 ) ], [ qw( d4 e5 f6 g7 h8 ) ], [ qw( d2 e1 ) ], [ qw( b2 a1 ) ], [ qw( b3 a3 ) ], [ qw( c4 c5 c6 c7 c8 ) ], [ qw( d3 e3 f3 g3 h3 ) ], [ qw( c2 c1 ) ], ], 'c4' => [ [ qw( b5 a6 ) ], [ qw( d5 e6 f7 g8 ) ], [ qw( d3 e2 f1 ) ], [ qw( b3 a2 ) ], [ qw( b4 a4 ) ], [ qw( c5 c6 c7 c8 ) ], [ qw( d4 e4 f4 g4 h4 ) ], [ qw( c3 c2 c1 ) ], ], 'c5' => [ [ qw( b6 a7 ) ], [ qw( d6 e7 f8 ) ], [ qw( d4 e3 f2 g1 ) ], [ qw( b4 a3 ) ], [ qw( b5 a5 ) ], [ qw( c6 c7 c8 ) ], [ qw( d5 e5 f5 g5 h5 ) ], [ qw( c4 c3 c2 c1 ) ], ], 'c6' => [ [ qw( b7 a8 ) ], [ qw( d7 e8 ) ], [ qw( d5 e4 f3 g2 h1 ) ], [ qw( b5 a4 ) ], [ qw( b6 a6 ) ], [ qw( c7 c8 ) ], [ qw( d6 e6 f6 g6 h6 ) ], [ qw( c5 c4 c3 c2 c1 ) ], ], 'c7' => [ [ qw( b8 ) ], [ qw( d8 ) ], [ qw( d6 e5 f4 g3 h2 ) ], [ qw( b6 a5 ) ], [ qw( b7 a7 ) ], [ qw( c8 ) ], [ qw( d7 e7 f7 g7 h7 ) ], [ qw( c6 c5 c4 c3 c2 c1 ) ], ], 'c8' => [ [ qw( d7 e6 f5 g4 h3 ) ], [ qw( b7 a6 ) ], [ qw( b8 a8 ) ], [ qw( d8 e8 f8 g8 h8 ) ], [ qw( c7 c6 c5 c4 c3 c2 c1 ) ], ], 'd1' => [ [ qw( c2 b3 a4 ) ], [ qw( e2 f3 g4 h5 ) ], [ qw( c1 b1 a1 ) ], [ qw( d2 d3 d4 d5 d6 d7 d8 ) ], [ qw( e1 f1 g1 h1 ) ], ], 'd2' => [ [ qw( c3 b4 a5 ) ], [ qw( e3 f4 g5 h6 ) ], [ qw( e1 ) ], [ qw( c1 ) ], [ qw( c2 b2 a2 ) ], [ qw( d3 d4 d5 d6 d7 d8 ) ], [ qw( e2 f2 g2 h2 ) ], [ qw( d1 ) ], ], 'd3' => [ [ qw( c4 b5 a6 ) ], [ qw( e4 f5 g6 h7 ) ], [ qw( e2 f1 ) ], [ qw( c2 b1 ) ], [ qw( c3 b3 a3 ) ], [ qw( d4 d5 d6 d7 d8 ) ], [ qw( e3 f3 g3 h3 ) ], [ qw( d2 d1 ) ], ], 'd4' => [ [ qw( c5 b6 a7 ) ], [ qw( e5 f6 g7 h8 ) ], [ qw( e3 f2 g1 ) ], [ qw( c3 b2 a1 ) ], [ qw( c4 b4 a4 ) ], [ qw( d5 d6 d7 d8 ) ], [ qw( e4 f4 g4 h4 ) ], [ qw( d3 d2 d1 ) ], ], 'd5' => [ [ qw( c6 b7 a8 ) ], [ qw( e6 f7 g8 ) ], [ qw( e4 f3 g2 h1 ) ], [ qw( c4 b3 a2 ) ], [ qw( c5 b5 a5 ) ], [ qw( d6 d7 d8 ) ], [ qw( e5 f5 g5 h5 ) ], [ qw( d4 d3 d2 d1 ) ], ], 'd6' => [ [ qw( c7 b8 ) ], [ qw( e7 f8 ) ], [ qw( e5 f4 g3 h2 ) ], [ qw( c5 b4 a3 ) ], [ qw( c6 b6 a6 ) ], [ qw( d7 d8 ) ], [ qw( e6 f6 g6 h6 ) ], [ qw( d5 d4 d3 d2 d1 ) ], ], 'd7' => [ [ qw( c8 ) ], [ qw( e8 ) ], [ qw( e6 f5 g4 h3 ) ], [ qw( c6 b5 a4 ) ], [ qw( c7 b7 a7 ) ], [ qw( d8 ) ], [ qw( e7 f7 g7 h7 ) ], [ qw( d6 d5 d4 d3 d2 d1 ) ], ], 'd8' => [ [ qw( e7 f6 g5 h4 ) ], [ qw( c7 b6 a5 ) ], [ qw( c8 b8 a8 ) ], [ qw( e8 f8 g8 h8 ) ], [ qw( d7 d6 d5 d4 d3 d2 d1 ) ], ], 'e1' => [ [ qw( d2 c3 b4 a5 ) ], [ qw( f2 g3 h4 ) ], [ qw( d1 c1 b1 a1 ) ], [ qw( e2 e3 e4 e5 e6 e7 e8 ) ], [ qw( f1 g1 h1 ) ], ], 'e2' => [ [ qw( d3 c4 b5 a6 ) ], [ qw( f3 g4 h5 ) ], [ qw( f1 ) ], [ qw( d1 ) ], [ qw( d2 c2 b2 a2 ) ], [ qw( e3 e4 e5 e6 e7 e8 ) ], [ qw( f2 g2 h2 ) ], [ qw( e1 ) ], ], 'e3' => [ [ qw( d4 c5 b6 a7 ) ], [ qw( f4 g5 h6 ) ], [ qw( f2 g1 ) ], [ qw( d2 c1 ) ], [ qw( d3 c3 b3 a3 ) ], [ qw( e4 e5 e6 e7 e8 ) ], [ qw( f3 g3 h3 ) ], [ qw( e2 e1 ) ], ], 'e4' => [ [ qw( d5 c6 b7 a8 ) ], [ qw( f5 g6 h7 ) ], [ qw( f3 g2 h1 ) ], [ qw( d3 c2 b1 ) ], [ qw( d4 c4 b4 a4 ) ], [ qw( e5 e6 e7 e8 ) ], [ qw( f4 g4 h4 ) ], [ qw( e3 e2 e1 ) ], ], 'e5' => [ [ qw( d6 c7 b8 ) ], [ qw( f6 g7 h8 ) ], [ qw( f4 g3 h2 ) ], [ qw( d4 c3 b2 a1 ) ], [ qw( d5 c5 b5 a5 ) ], [ qw( e6 e7 e8 ) ], [ qw( f5 g5 h5 ) ], [ qw( e4 e3 e2 e1 ) ], ], 'e6' => [ [ qw( d7 c8 ) ], [ qw( f7 g8 ) ], [ qw( f5 g4 h3 ) ], [ qw( d5 c4 b3 a2 ) ], [ qw( d6 c6 b6 a6 ) ], [ qw( e7 e8 ) ], [ qw( f6 g6 h6 ) ], [ qw( e5 e4 e3 e2 e1 ) ], ], 'e7' => [ [ qw( d8 ) ], [ qw( f8 ) ], [ qw( f6 g5 h4 ) ], [ qw( d6 c5 b4 a3 ) ], [ qw( d7 c7 b7 a7 ) ], [ qw( e8 ) ], [ qw( f7 g7 h7 ) ], [ qw( e6 e5 e4 e3 e2 e1 ) ], ], 'e8' => [ [ qw( f7 g6 h5 ) ], [ qw( d7 c6 b5 a4 ) ], [ qw( d8 c8 b8 a8 ) ], [ qw( f8 g8 h8 ) ], [ qw( e7 e6 e5 e4 e3 e2 e1 ) ], ], 'f1' => [ [ qw( e2 d3 c4 b5 a6 ) ], [ qw( g2 h3 ) ], [ qw( e1 d1 c1 b1 a1 ) ], [ qw( f2 f3 f4 f5 f6 f7 f8 ) ], [ qw( g1 h1 ) ], ], 'f2' => [ [ qw( e3 d4 c5 b6 a7 ) ], [ qw( g3 h4 ) ], [ qw( g1 ) ], [ qw( e1 ) ], [ qw( e2 d2 c2 b2 a2 ) ], [ qw( f3 f4 f5 f6 f7 f8 ) ], [ qw( g2 h2 ) ], [ qw( f1 ) ], ], 'f3' => [ [ qw( e4 d5 c6 b7 a8 ) ], [ qw( g4 h5 ) ], [ qw( g2 h1 ) ], [ qw( e2 d1 ) ], [ qw( e3 d3 c3 b3 a3 ) ], [ qw( f4 f5 f6 f7 f8 ) ], [ qw( g3 h3 ) ], [ qw( f2 f1 ) ], ], 'f4' => [ [ qw( e5 d6 c7 b8 ) ], [ qw( g5 h6 ) ], [ qw( g3 h2 ) ], [ qw( e3 d2 c1 ) ], [ qw( e4 d4 c4 b4 a4 ) ], [ qw( f5 f6 f7 f8 ) ], [ qw( g4 h4 ) ], [ qw( f3 f2 f1 ) ], ], 'f5' => [ [ qw( e6 d7 c8 ) ], [ qw( g6 h7 ) ], [ qw( g4 h3 ) ], [ qw( e4 d3 c2 b1 ) ], [ qw( e5 d5 c5 b5 a5 ) ], [ qw( f6 f7 f8 ) ], [ qw( g5 h5 ) ], [ qw( f4 f3 f2 f1 ) ], ], 'f6' => [ [ qw( e7 d8 ) ], [ qw( g7 h8 ) ], [ qw( g5 h4 ) ], [ qw( e5 d4 c3 b2 a1 ) ], [ qw( e6 d6 c6 b6 a6 ) ], [ qw( f7 f8 ) ], [ qw( g6 h6 ) ], [ qw( f5 f4 f3 f2 f1 ) ], ], 'f7' => [ [ qw( e8 ) ], [ qw( g8 ) ], [ qw( g6 h5 ) ], [ qw( e6 d5 c4 b3 a2 ) ], [ qw( e7 d7 c7 b7 a7 ) ], [ qw( f8 ) ], [ qw( g7 h7 ) ], [ qw( f6 f5 f4 f3 f2 f1 ) ], ], 'f8' => [ [ qw( g7 h6 ) ], [ qw( e7 d6 c5 b4 a3 ) ], [ qw( e8 d8 c8 b8 a8 ) ], [ qw( g8 h8 ) ], [ qw( f7 f6 f5 f4 f3 f2 f1 ) ], ], 'g1' => [ [ qw( f2 e3 d4 c5 b6 a7 ) ], [ qw( h2 ) ], [ qw( f1 e1 d1 c1 b1 a1 ) ], [ qw( g2 g3 g4 g5 g6 g7 g8 ) ], [ qw( h1 ) ], ], 'g2' => [ [ qw( f3 e4 d5 c6 b7 a8 ) ], [ qw( h3 ) ], [ qw( h1 ) ], [ qw( f1 ) ], [ qw( f2 e2 d2 c2 b2 a2 ) ], [ qw( g3 g4 g5 g6 g7 g8 ) ], [ qw( h2 ) ], [ qw( g1 ) ], ], 'g3' => [ [ qw( f4 e5 d6 c7 b8 ) ], [ qw( h4 ) ], [ qw( h2 ) ], [ qw( f2 e1 ) ], [ qw( f3 e3 d3 c3 b3 a3 ) ], [ qw( g4 g5 g6 g7 g8 ) ], [ qw( h3 ) ], [ qw( g2 g1 ) ], ], 'g4' => [ [ qw( f5 e6 d7 c8 ) ], [ qw( h5 ) ], [ qw( h3 ) ], [ qw( f3 e2 d1 ) ], [ qw( f4 e4 d4 c4 b4 a4 ) ], [ qw( g5 g6 g7 g8 ) ], [ qw( h4 ) ], [ qw( g3 g2 g1 ) ], ], 'g5' => [ [ qw( f6 e7 d8 ) ], [ qw( h6 ) ], [ qw( h4 ) ], [ qw( f4 e3 d2 c1 ) ], [ qw( f5 e5 d5 c5 b5 a5 ) ], [ qw( g6 g7 g8 ) ], [ qw( h5 ) ], [ qw( g4 g3 g2 g1 ) ], ], 'g6' => [ [ qw( f7 e8 ) ], [ qw( h7 ) ], [ qw( h5 ) ], [ qw( f5 e4 d3 c2 b1 ) ], [ qw( f6 e6 d6 c6 b6 a6 ) ], [ qw( g7 g8 ) ], [ qw( h6 ) ], [ qw( g5 g4 g3 g2 g1 ) ], ], 'g7' => [ [ qw( f8 ) ], [ qw( h8 ) ], [ qw( h6 ) ], [ qw( f6 e5 d4 c3 b2 a1 ) ], [ qw( f7 e7 d7 c7 b7 a7 ) ], [ qw( g8 ) ], [ qw( h7 ) ], [ qw( g6 g5 g4 g3 g2 g1 ) ], ], 'g8' => [ [ qw( h7 ) ], [ qw( f7 e6 d5 c4 b3 a2 ) ], [ qw( f8 e8 d8 c8 b8 a8 ) ], [ qw( h8 ) ], [ qw( g7 g6 g5 g4 g3 g2 g1 ) ], ], 'h1' => [ [ qw( g2 f3 e4 d5 c6 b7 a8 ) ], [ qw( g1 f1 e1 d1 c1 b1 a1 ) ], [ qw( h2 h3 h4 h5 h6 h7 h8 ) ], ], 'h2' => [ [ qw( g3 f4 e5 d6 c7 b8 ) ], [ qw( g1 ) ], [ qw( g2 f2 e2 d2 c2 b2 a2 ) ], [ qw( h3 h4 h5 h6 h7 h8 ) ], [ qw( h1 ) ], ], 'h3' => [ [ qw( g4 f5 e6 d7 c8 ) ], [ qw( g2 f1 ) ], [ qw( g3 f3 e3 d3 c3 b3 a3 ) ], [ qw( h4 h5 h6 h7 h8 ) ], [ qw( h2 h1 ) ], ], 'h4' => [ [ qw( g5 f6 e7 d8 ) ], [ qw( g3 f2 e1 ) ], [ qw( g4 f4 e4 d4 c4 b4 a4 ) ], [ qw( h5 h6 h7 h8 ) ], [ qw( h3 h2 h1 ) ], ], 'h5' => [ [ qw( g6 f7 e8 ) ], [ qw( g4 f3 e2 d1 ) ], [ qw( g5 f5 e5 d5 c5 b5 a5 ) ], [ qw( h6 h7 h8 ) ], [ qw( h4 h3 h2 h1 ) ], ], 'h6' => [ [ qw( g7 f8 ) ], [ qw( g5 f4 e3 d2 c1 ) ], [ qw( g6 f6 e6 d6 c6 b6 a6 ) ], [ qw( h7 h8 ) ], [ qw( h5 h4 h3 h2 h1 ) ], ], 'h7' => [ [ qw( g8 ) ], [ qw( g6 f5 e4 d3 c2 b1 ) ], [ qw( g7 f7 e7 d7 c7 b7 a7 ) ], [ qw( h8 ) ], [ qw( h6 h5 h4 h3 h2 h1 ) ], ], 'h8' => [ [ qw( g7 f6 e5 d4 c3 b2 a1 ) ], [ qw( g8 f8 e8 d8 c8 b8 a8 ) ], [ qw( h7 h6 h5 h4 h3 h2 h1 ) ], ], }, # The Rook 'r' => { 'a1' => [ [ qw( a2 a3 a4 a5 a6 a7 a8 ) ], [ qw( b1 c1 d1 e1 f1 g1 h1 ) ], ], 'a2' => [ [ qw( a3 a4 a5 a6 a7 a8 ) ], [ qw( a1 ) ], [ qw( b2 c2 d2 e2 f2 g2 h2 ) ], ], 'a3' => [ [ qw( a4 a5 a6 a7 a8 ) ], [ qw( b3 c3 d3 e3 f3 g3 h3 ) ], [ qw( a2 a1 ) ], ], 'a4' => [ [ qw( a5 a6 a7 a8 ) ], [ qw( b4 c4 d4 e4 f4 g4 h4 ) ], [ qw( a3 a2 a1 ) ], ], 'a5' => [ [ qw( a6 a7 a8 ) ], [ qw( b5 c5 d5 e5 f5 g5 h5 ) ], [ qw( a4 a3 a2 a1 ) ], ], 'a6' => [ [ qw( a7 a8 ) ], [ qw( b6 c6 d6 e6 f6 g6 h6 ) ], [ qw( a5 a4 a3 a2 a1 ) ], ], 'a7' => [ [ qw( a8 ) ], [ qw( b7 c7 d7 e7 f7 g7 h7 ) ], [ qw( a6 a5 a4 a3 a2 a1 ) ], ], 'a8' => [ [ qw( b8 c8 d8 e8 f8 g8 h8 ) ], [ qw( a7 a6 a5 a4 a3 a2 a1 ) ], ], 'b1' => [ [ qw( a1 ) ], [ qw( b2 b3 b4 b5 b6 b7 b8 ) ], [ qw( c1 d1 e1 f1 g1 h1 ) ], ], 'b2' => [ [ qw( a2 ) ], [ qw( b3 b4 b5 b6 b7 b8 ) ], [ qw( c2 d2 e2 f2 g2 h2 ) ], [ qw( b1 ) ], ], 'b3' => [ [ qw( a3 ) ], [ qw( b4 b5 b6 b7 b8 ) ], [ qw( c3 d3 e3 f3 g3 h3 ) ], [ qw( b2 b1 ) ], ], 'b4' => [ [ qw( a4 ) ], [ qw( b5 b6 b7 b8 ) ], [ qw( c4 d4 e4 f4 g4 h4 ) ], [ qw( b3 b2 b1 ) ], ], 'b5' => [ [ qw( a5 ) ], [ qw( b6 b7 b8 ) ], [ qw( c5 d5 e5 f5 g5 h5 ) ], [ qw( b4 b3 b2 b1 ) ], ], 'b6' => [ [ qw( a6 ) ], [ qw( b7 b8 ) ], [ qw( c6 d6 e6 f6 g6 h6 ) ], [ qw( b5 b4 b3 b2 b1 ) ], ], 'b7' => [ [ qw( a7 ) ], [ qw( b8 ) ], [ qw( c7 d7 e7 f7 g7 h7 ) ], [ qw( b6 b5 b4 b3 b2 b1 ) ], ], 'b8' => [ [ qw( a8 ) ], [ qw( c8 d8 e8 f8 g8 h8 ) ], [ qw( b7 b6 b5 b4 b3 b2 b1 ) ], ], 'c1' => [ [ qw( b1 a1 ) ], [ qw( c2 c3 c4 c5 c6 c7 c8 ) ], [ qw( d1 e1 f1 g1 h1 ) ], ], 'c2' => [ [ qw( b2 a2 ) ], [ qw( c3 c4 c5 c6 c7 c8 ) ], [ qw( d2 e2 f2 g2 h2 ) ], [ qw( c1 ) ], ], 'c3' => [ [ qw( b3 a3 ) ], [ qw( c4 c5 c6 c7 c8 ) ], [ qw( d3 e3 f3 g3 h3 ) ], [ qw( c2 c1 ) ], ], 'c4' => [ [ qw( b4 a4 ) ], [ qw( c5 c6 c7 c8 ) ], [ qw( d4 e4 f4 g4 h4 ) ], [ qw( c3 c2 c1 ) ], ], 'c5' => [ [ qw( b5 a5 ) ], [ qw( c6 c7 c8 ) ], [ qw( d5 e5 f5 g5 h5 ) ], [ qw( c4 c3 c2 c1 ) ], ], 'c6' => [ [ qw( b6 a6 ) ], [ qw( c7 c8 ) ], [ qw( d6 e6 f6 g6 h6 ) ], [ qw( c5 c4 c3 c2 c1 ) ], ], 'c7' => [ [ qw( b7 a7 ) ], [ qw( c8 ) ], [ qw( d7 e7 f7 g7 h7 ) ], [ qw( c6 c5 c4 c3 c2 c1 ) ], ], 'c8' => [ [ qw( b8 a8 ) ], [ qw( d8 e8 f8 g8 h8 ) ], [ qw( c7 c6 c5 c4 c3 c2 c1 ) ], ], 'd1' => [ [ qw( c1 b1 a1 ) ], [ qw( d2 d3 d4 d5 d6 d7 d8 ) ], [ qw( e1 f1 g1 h1 ) ], ], 'd2' => [ [ qw( c2 b2 a2 ) ], [ qw( d3 d4 d5 d6 d7 d8 ) ], [ qw( e2 f2 g2 h2 ) ], [ qw( d1 ) ], ], 'd3' => [ [ qw( c3 b3 a3 ) ], [ qw( d4 d5 d6 d7 d8 ) ], [ qw( e3 f3 g3 h3 ) ], [ qw( d2 d1 ) ], ], 'd4' => [ [ qw( c4 b4 a4 ) ], [ qw( d5 d6 d7 d8 ) ], [ qw( e4 f4 g4 h4 ) ], [ qw( d3 d2 d1 ) ], ], 'd5' => [ [ qw( c5 b5 a5 ) ], [ qw( d6 d7 d8 ) ], [ qw( e5 f5 g5 h5 ) ], [ qw( d4 d3 d2 d1 ) ], ], 'd6' => [ [ qw( c6 b6 a6 ) ], [ qw( d7 d8 ) ], [ qw( e6 f6 g6 h6 ) ], [ qw( d5 d4 d3 d2 d1 ) ], ], 'd7' => [ [ qw( c7 b7 a7 ) ], [ qw( d8 ) ], [ qw( e7 f7 g7 h7 ) ], [ qw( d6 d5 d4 d3 d2 d1 ) ], ], 'd8' => [ [ qw( c8 b8 a8 ) ], [ qw( e8 f8 g8 h8 ) ], [ qw( d7 d6 d5 d4 d3 d2 d1 ) ], ], 'e1' => [ [ qw( d1 c1 b1 a1 ) ], [ qw( e2 e3 e4 e5 e6 e7 e8 ) ], [ qw( f1 g1 h1 ) ], ], 'e2' => [ [ qw( d2 c2 b2 a2 ) ], [ qw( e3 e4 e5 e6 e7 e8 ) ], [ qw( f2 g2 h2 ) ], [ qw( e1 ) ], ], 'e3' => [ [ qw( d3 c3 b3 a3 ) ], [ qw( e4 e5 e6 e7 e8 ) ], [ qw( f3 g3 h3 ) ], [ qw( e2 e1 ) ], ], 'e4' => [ [ qw( d4 c4 b4 a4 ) ], [ qw( e5 e6 e7 e8 ) ], [ qw( f4 g4 h4 ) ], [ qw( e3 e2 e1 ) ], ], 'e5' => [ [ qw( d5 c5 b5 a5 ) ], [ qw( e6 e7 e8 ) ], [ qw( f5 g5 h5 ) ], [ qw( e4 e3 e2 e1 ) ], ], 'e6' => [ [ qw( d6 c6 b6 a6 ) ], [ qw( e7 e8 ) ], [ qw( f6 g6 h6 ) ], [ qw( e5 e4 e3 e2 e1 ) ], ], 'e7' => [ [ qw( d7 c7 b7 a7 ) ], [ qw( e8 ) ], [ qw( f7 g7 h7 ) ], [ qw( e6 e5 e4 e3 e2 e1 ) ], ], 'e8' => [ [ qw( d8 c8 b8 a8 ) ], [ qw( f8 g8 h8 ) ], [ qw( e7 e6 e5 e4 e3 e2 e1 ) ], ], 'f1' => [ [ qw( e1 d1 c1 b1 a1 ) ], [ qw( f2 f3 f4 f5 f6 f7 f8 ) ], [ qw( g1 h1 ) ], ], 'f2' => [ [ qw( e2 d2 c2 b2 a2 ) ], [ qw( f3 f4 f5 f6 f7 f8 ) ], [ qw( g2 h2 ) ], [ qw( f1 ) ], ], 'f3' => [ [ qw( e3 d3 c3 b3 a3 ) ], [ qw( f4 f5 f6 f7 f8 ) ], [ qw( g3 h3 ) ], [ qw( f2 f1 ) ], ], 'f4' => [ [ qw( e4 d4 c4 b4 a4 ) ], [ qw( f5 f6 f7 f8 ) ], [ qw( g4 h4 ) ], [ qw( f3 f2 f1 ) ], ], 'f5' => [ [ qw( e5 d5 c5 b5 a5 ) ], [ qw( f6 f7 f8 ) ], [ qw( g5 h5 ) ], [ qw( f4 f3 f2 f1 ) ], ], 'f6' => [ [ qw( e6 d6 c6 b6 a6 ) ], [ qw( f7 f8 ) ], [ qw( g6 h6 ) ], [ qw( f5 f4 f3 f2 f1 ) ], ], 'f7' => [ [ qw( e7 d7 c7 b7 a7 ) ], [ qw( f8 ) ], [ qw( g7 h7 ) ], [ qw( f6 f5 f4 f3 f2 f1 ) ], ], 'f8' => [ [ qw( e8 d8 c8 b8 a8 ) ], [ qw( g8 h8 ) ], [ qw( f7 f6 f5 f4 f3 f2 f1 ) ], ], 'g1' => [ [ qw( f1 e1 d1 c1 b1 a1 ) ], [ qw( g2 g3 g4 g5 g6 g7 g8 ) ], [ qw( h1 ) ], ], 'g2' => [ [ qw( f2 e2 d2 c2 b2 a2 ) ], [ qw( g3 g4 g5 g6 g7 g8 ) ], [ qw( h2 ) ], [ qw( g1 ) ], ], 'g3' => [ [ qw( f3 e3 d3 c3 b3 a3 ) ], [ qw( g4 g5 g6 g7 g8 ) ], [ qw( h3 ) ], [ qw( g2 g1 ) ], ], 'g4' => [ [ qw( f4 e4 d4 c4 b4 a4 ) ], [ qw( g5 g6 g7 g8 ) ], [ qw( h4 ) ], [ qw( g3 g2 g1 ) ], ], 'g5' => [ [ qw( f5 e5 d5 c5 b5 a5 ) ], [ qw( g6 g7 g8 ) ], [ qw( h5 ) ], [ qw( g4 g3 g2 g1 ) ], ], 'g6' => [ [ qw( f6 e6 d6 c6 b6 a6 ) ], [ qw( g7 g8 ) ], [ qw( h6 ) ], [ qw( g5 g4 g3 g2 g1 ) ], ], 'g7' => [ [ qw( f7 e7 d7 c7 b7 a7 ) ], [ qw( g8 ) ], [ qw( h7 ) ], [ qw( g6 g5 g4 g3 g2 g1 ) ], ], 'g8' => [ [ qw( f8 e8 d8 c8 b8 a8 ) ], [ qw( h8 ) ], [ qw( g7 g6 g5 g4 g3 g2 g1 ) ], ], 'h1' => [ [ qw( g1 f1 e1 d1 c1 b1 a1 ) ], [ qw( h2 h3 h4 h5 h6 h7 h8 ) ], ], 'h2' => [ [ qw( g2 f2 e2 d2 c2 b2 a2 ) ], [ qw( h3 h4 h5 h6 h7 h8 ) ], [ qw( h1 ) ], ], 'h3' => [ [ qw( g3 f3 e3 d3 c3 b3 a3 ) ], [ qw( h4 h5 h6 h7 h8 ) ], [ qw( h2 h1 ) ], ], 'h4' => [ [ qw( g4 f4 e4 d4 c4 b4 a4 ) ], [ qw( h5 h6 h7 h8 ) ], [ qw( h3 h2 h1 ) ], ], 'h5' => [ [ qw( g5 f5 e5 d5 c5 b5 a5 ) ], [ qw( h6 h7 h8 ) ], [ qw( h4 h3 h2 h1 ) ], ], 'h6' => [ [ qw( g6 f6 e6 d6 c6 b6 a6 ) ], [ qw( h7 h8 ) ], [ qw( h5 h4 h3 h2 h1 ) ], ], 'h7' => [ [ qw( g7 f7 e7 d7 c7 b7 a7 ) ], [ qw( h8 ) ], [ qw( h6 h5 h4 h3 h2 h1 ) ], ], 'h8' => [ [ qw( g8 f8 e8 d8 c8 b8 a8 ) ], [ qw( h7 h6 h5 h4 h3 h2 h1 ) ], ], }, # The Bishop 'b' => { 'a1' => [ [ qw( b2 c3 d4 e5 f6 g7 h8 ) ] ], 'a2' => [ [ qw( b3 c4 d5 e6 f7 g8 ) ], [ qw( b1 ) ], ], 'a3' => [ [ qw( b4 c5 d6 e7 f8 ) ], [ qw( b2 c1 ) ], ], 'a4' => [ [ qw( b5 c6 d7 e8 ) ], [ qw( b3 c2 d1 ) ], ], 'a5' => [ [ qw( b6 c7 d8 ) ], [ qw( b4 c3 d2 e1 ) ], ], 'a6' => [ [ qw( b7 c8 ) ], [ qw( b5 c4 d3 e2 f1 ) ], ], 'a7' => [ [ qw( b8 ) ], [ qw( b6 c5 d4 e3 f2 g1 ) ], ], 'a8' => [ [ qw( b7 c6 d5 e4 f3 g2 h1 ) ] ], 'b1' => [ [ qw( a2 ) ], [ qw( c2 d3 e4 f5 g6 h7 ) ], ], 'b2' => [ [ qw( a3 ) ], [ qw( c3 d4 e5 f6 g7 h8 ) ], [ qw( c1 ) ], [ qw( a1 ) ], ], 'b3' => [ [ qw( a4 ) ], [ qw( c4 d5 e6 f7 g8 ) ], [ qw( c2 d1 ) ], [ qw( a2 ) ], ], 'b4' => [ [ qw( a5 ) ], [ qw( c5 d6 e7 f8 ) ], [ qw( c3 d2 e1 ) ], [ qw( a3 ) ], ], 'b5' => [ [ qw( a6 ) ], [ qw( c6 d7 e8 ) ], [ qw( c4 d3 e2 f1 ) ], [ qw( a4 ) ], ], 'b6' => [ [ qw( a7 ) ], [ qw( c7 d8 ) ], [ qw( c5 d4 e3 f2 g1 ) ], [ qw( a5 ) ], ], 'b7' => [ [ qw( a8 ) ], [ qw( c8 ) ], [ qw( c6 d5 e4 f3 h1 ) ], [ qw( a6 ) ], ], 'b8' => [ [ qw( c7 d6 e5 f4 g3 h2 ) ], [ qw( a7 ) ], ], 'c1' => [ [ qw( b2 a3 ) ], [ qw( d2 e3 f4 g5 h6 ) ], ], 'c2' => [ [ qw( b3 a4 ) ], [ qw( d3 e4 f5 g6 h7 ) ], [ qw( d1 ) ], [ qw( b1 ) ], ], 'c3' => [ [ qw( b4 a5 ) ], [ qw( d4 e5 f6 g7 h8 ) ], [ qw( d2 e1 ) ], [ qw( b2 a1 ) ], ], 'c4' => [ [ qw( b5 a6 ) ], [ qw( d5 e6 f7 g8 ) ], [ qw( d3 e2 f1 ) ], [ qw( b3 a2 ) ], ], 'c5' => [ [ qw( b6 a7 ) ], [ qw( d6 e7 f8 ) ], [ qw( d4 e3 f2 g1 ) ], [ qw( b4 a3 ) ], ], 'c6' => [ [ qw( b7 a8 ) ], [ qw( d7 e8 ) ], [ qw( d5 e4 f3 g2 h1 ) ], [ qw( b5 a4 ) ], ], 'c7' => [ [ qw( b8 ) ], [ qw( d8 ) ], [ qw( d6 e5 f4 g3 h2 ) ], [ qw( b6 a5 ) ], ], 'c8' => [ [ qw( d7 e6 f5 g4 h3 ) ], [ qw( b7 a6 ) ], ], 'd1' => [ [ qw( c2 b3 a4 ) ], [ qw( e2 f3 g4 h5 ) ], ], 'd2' => [ [ qw( c3 b4 a5 ) ], [ qw( e3 f4 g5 h6 ) ], [ qw( e1 ) ], [ qw( c1 ) ], ], 'd3' => [ [ qw( c4 b5 a6 ) ], [ qw( e4 f5 g6 h7 ) ], [ qw( e2 f1 ) ], [ qw( c2 b1 ) ], ], 'd4' => [ [ qw( c5 b6 a7 ) ], [ qw( e5 f6 g7 h8 ) ], [ qw( e3 f2 g1 ) ], [ qw( c3 b2 a1 ) ], ], 'd5' => [ [ qw( c6 b7 a8 ) ], [ qw( e6 f7 g8 ) ], [ qw( e4 f3 g2 h1 ) ], [ qw( c4 b3 a2 ) ], ], 'd6' => [ [ qw( c7 b8 ) ], [ qw( e7 f8 ) ], [ qw( e5 f4 g3 h2 ) ], [ qw( c5 b4 a3 ) ], ], 'd7' => [ [ qw( c8 ) ], [ qw( e8 ) ], [ qw( e6 f5 g4 h3 ) ], [ qw( c6 b5 a4 ) ], ], 'd8' => [ [ qw( e7 f6 g5 h4 ) ], [ qw( c7 b6 a5 ) ], ], 'e1' => [ [ qw( d2 c3 b4 a5 ) ], [ qw( f2 g3 h4 ) ], ], 'e2' => [ [ qw( d3 c4 b5 a6 ) ], [ qw( f3 g4 h5 ) ], [ qw( f1 ) ], [ qw( d1 ) ], ], 'e3' => [ [ qw( d4 c5 b6 a7 ) ], [ qw( f4 g5 h6 ) ], [ qw( f2 g1 ) ], [ qw( d2 c1 ) ], ], 'e4' => [ [ qw( d5 c6 b7 a8 ) ], [ qw( f5 g6 h7 ) ], [ qw( f3 g2 h1 ) ], [ qw( d3 c2 b1 ) ], ], 'e5' => [ [ qw( d6 c7 b8 ) ], [ qw( f6 g7 h8 ) ], [ qw( f4 g3 h2 ) ], [ qw( d4 c3 b2 a1 ) ], ], 'e6' => [ [ qw( d7 c8 ) ], [ qw( f7 g8 ) ], [ qw( f5 g4 h3 ) ], [ qw( d5 c4 b3 a2 ) ], ], 'e7' => [ [ qw( d8 ) ], [ qw( f8 ) ], [ qw( f6 g5 h4 ) ], [ qw( d6 c5 b4 a3 ) ], ], 'e8' => [ [ qw( f7 g6 h5 ) ], [ qw( d7 c6 b5 a4 ) ], ], 'f1' => [ [ qw( e2 d3 c4 b5 a6 ) ], [ qw( g2 h3 ) ], ], 'f2' => [ [ qw( e3 d4 c5 b6 a7 ) ], [ qw( g3 h4 ) ], [ qw( g1 ) ], [ qw( e1 ) ], ], 'f3' => [ [ qw( e4 d5 c6 b7 a8 ) ], [ qw( g4 h5 ) ], [ qw( g2 h1 ) ], [ qw( e2 d1 ) ], ], 'f4' => [ [ qw( e5 d6 c7 b8 ) ], [ qw( g5 h6 ) ], [ qw( g3 h2 ) ], [ qw( e3 d2 c1 ) ], ], 'f5' => [ [ qw( e6 d7 c8 ) ], [ qw( g6 h7 ) ], [ qw( g4 h3 ) ], [ qw( e4 d3 c2 b1 ) ], ], 'f6' => [ [ qw( e7 d8 ) ], [ qw( g7 h8 ) ], [ qw( g5 h4 ) ], [ qw( e5 d4 c3 b2 a1 ) ], ], 'f7' => [ [ qw( e8 ) ], [ qw( g8 ) ], [ qw( g6 h5 ) ], [ qw( e6 d5 c4 b3 a2 ) ], ], 'f8' => [ [ qw( g7 h6 ) ], [ qw( e7 d6 c5 b4 a3 ) ], ], 'g1' => [ [ qw( f2 e3 d4 c5 b6 a7 ) ], [ qw( h2 ) ], ], 'g2' => [ [ qw( f3 e4 d5 c6 b7 a8 ) ], [ qw( h3 ) ], [ qw( h1 ) ], [ qw( f1 ) ], ], 'g3' => [ [ qw( f4 e5 d6 c7 b8 ) ], [ qw( h4 ) ], [ qw( h2 ) ], [ qw( f2 e1 ) ], ], 'g4' => [ [ qw( f5 e6 d7 c8 ) ], [ qw( h5 ) ], [ qw( h3 ) ], [ qw( f3 e2 d1 ) ], ], 'g5' => [ [ qw( f6 e7 d8 ) ], [ qw( h6 ) ], [ qw( h4 ) ], [ qw( f4 e3 d2 c1 ) ], ], 'g6' => [ [ qw( f7 e8 ) ], [ qw( h7 ) ], [ qw( h5 ) ], [ qw( f5 e4 d3 c2 b1 ) ], ], 'g7' => [ [ qw( f8 ) ], [ qw( h8 ) ], [ qw( h6 ) ], [ qw( f6 e5 d4 c3 b2 a1 ) ], ], 'g8' => [ [ qw( h7 ) ], [ qw( f7 e6 d5 c4 b3 a2 ) ], ], 'h1' => [ [ qw( g2 f3 e4 d5 c6 b7 a8 ) ] ], 'h2' => [ [ qw( g3 f4 e5 d6 c7 b8 ) ], [ qw( g1 ) ], ], 'h3' => [ [ qw( g4 f5 e6 d7 c8 ) ], [ qw( g2 f1 ) ], ], 'h4' => [ [ qw( g5 f6 e7 d8 ) ], [ qw( g3 f2 e1 ) ], ], 'h5' => [ [ qw( g6 f7 e8 ) ], [ qw( g4 f3 e2 d1 ) ], ], 'h6' => [ [ qw( g7 f8 ) ], [ qw( g5 f4 e3 d2 c1 ) ], ], 'h7' => [ [ qw( g8 ) ], [ qw( g6 f5 e4 d3 c2 b1 ) ], ], 'h8' => [ [ qw( g7 f6 e5 d4 c3 b2 a1 ) ] ], }, # The Knight 'n' => { 'a1' => [ [ qw( b3 c2 ) ] ], 'a2' => [ [ qw( b4 c3 c1 ) ] ], 'a3' => [ [ qw( b5 c4 c2 b1 ) ] ], 'a4' => [ [ qw( b6 c5 c3 b2 ) ] ], 'a5' => [ [ qw( b7 c6 c4 b3 ) ] ], 'a6' => [ [ qw( b8 c7 c5 b4 ) ] ], 'a7' => [ [ qw( c8 c6 b5 ) ] ], 'a8' => [ [ qw( c7 b6 ) ] ], 'b1' => [ [ qw( a3 c3 d2 ) ] ], 'b2' => [ [ qw( a4 c4 d3 d1 ) ] ], 'b3' => [ [ qw( a5 c5 d4 d2 c1 a1 ) ] ], 'b4' => [ [ qw( a6 c6 d5 d3 c2 a2 ) ] ], 'b5' => [ [ qw( a7 c7 d6 d4 c3 a3 ) ] ], 'b6' => [ [ qw( a8 c8 d7 d5 c4 a4 ) ] ], 'b7' => [ [ qw( d8 d6 c5 a5 ) ] ], 'b8' => [ [ qw( d7 c6 a6 ) ] ], 'c1' => [ [ qw( a2 b3 d3 e2 ) ] ], 'c2' => [ [ qw( a3 b4 d4 e3 e1 a1 ) ] ], 'c3' => [ [ qw( a4 b5 d5 e4 e2 d1 b1 a2 ) ] ], 'c4' => [ [ qw( a5 b6 d6 e5 e3 d2 b2 a3 ) ] ], 'c5' => [ [ qw( a6 b7 d7 e6 e4 d3 b3 a4 ) ] ], 'c6' => [ [ qw( a7 b8 d8 e7 e5 d4 b4 a5 ) ] ], 'c7' => [ [ qw( e8 e6 d5 b5 a6 a8 ) ] ], 'c8' => [ [ qw( e7 d6 b6 a7 ) ] ], 'd1' => [ [ qw( b2 c3 e3 f2 ) ] ], 'd2' => [ [ qw( b3 c4 e4 f3 f1 b1 ) ] ], 'd3' => [ [ qw( b4 c5 e5 f4 f2 e1 c1 b2 ) ] ], 'd4' => [ [ qw( b5 c6 e6 f5 f3 e2 c2 b3 ) ] ], 'd5' => [ [ qw( b6 c7 e7 f6 f4 e3 c3 b4 ) ] ], 'd6' => [ [ qw( b7 c8 e8 f7 f5 e4 c4 b5 ) ] ], 'd7' => [ [ qw( f8 f6 e5 c5 b6 b8 ) ] ], 'd8' => [ [ qw( f7 e6 c6 b7 ) ] ], 'e1' => [ [ qw( c2 d3 f3 g2 ) ] ], 'e2' => [ [ qw( c3 d4 f4 g3 g1 c1 ) ] ], 'e3' => [ [ qw( c4 d5 f5 g4 g2 f1 d1 c2 ) ] ], 'e4' => [ [ qw( c5 d6 f6 g5 g3 f2 d2 c3 ) ] ], 'e5' => [ [ qw( c6 d7 f7 g6 g4 f3 d3 c4 ) ] ], 'e6' => [ [ qw( c7 d8 f8 g7 g5 f4 d4 c5 ) ] ], 'e7' => [ [ qw( g8 g6 f5 d5 c6 c8 ) ] ], 'e8' => [ [ qw( g7 f6 d6 c7 ) ] ], 'f1' => [ [ qw( d2 e3 g3 h2 ) ] ], 'f2' => [ [ qw( d3 e4 g4 h3 h1 d1 ) ] ], 'f3' => [ [ qw( d4 e5 g5 h4 h2 g1 e1 d2 ) ] ], 'f4' => [ [ qw( d5 e6 g6 h5 h3 g2 e2 d3 ) ] ], 'f5' => [ [ qw( d6 e7 g7 h6 h4 g3 e3 d4 ) ] ], 'f6' => [ [ qw( d7 e8 g8 h7 h5 g4 e4 d5 ) ] ], 'f7' => [ [ qw( h8 h6 g5 e5 d6 d8 ) ] ], 'f8' => [ [ qw( h7 g6 e6 d7 ) ] ], 'g1' => [ [ qw( e2 f3 h3 ) ] ], 'g2' => [ [ qw( e3 f4 h4 e1 ) ] ], 'g3' => [ [ qw( e4 f5 h5 h1 f1 e2 ) ] ], 'g4' => [ [ qw( e5 f6 h6 h2 f2 e3 ) ] ], 'g5' => [ [ qw( e6 f7 h7 h3 f3 e4 ) ] ], 'g6' => [ [ qw( e7 f8 h8 h4 f4 e5 ) ] ], 'g7' => [ [ qw( h5 f5 e6 e8 ) ] ], 'g8' => [ [ qw( h6 f6 e7 ) ] ], 'h1' => [ [ qw( f2 g3 ) ] ], 'h2' => [ [ qw( f3 g4 f1 ) ] ], 'h3' => [ [ qw( f4 g5 g1 f2 ) ] ], 'h4' => [ [ qw( f5 g6 g2 f3 ) ] ], 'h5' => [ [ qw( f6 g7 g3 f4 ) ] ], 'h6' => [ [ qw( f7 g8 g4 f5 ) ] ], 'h7' => [ [ qw( g5 f6 f8 ) ] ], 'h8' => [ [ qw( g6 f7 ) ] ], }, 'g' => { # 'Grasshopper' -- a hypothetical piece created for use with t +he # 'attack' program. This piece moves/attacks sort of like a k +ing # and knight combined -- it attacks any square which is exactl +y 2 # squares either horizontally, vertically or diagonally. # 'a1' => [ [ qw( a3 b3 c3 c2 c1 ) ] ], 'a2' => [ [ qw( a4 b4 c4 c3 c2 c1 ) ] ], 'a3' => [ [ qw( a5 b5 c5 c4 c3 c2 c1 b1 a1 ) ] ], 'a4' => [ [ qw( a6 b6 c6 c5 c4 c3 c2 b2 a2 ) ] ], 'a5' => [ [ qw( a7 b7 c7 c6 c5 c4 c3 b3 a3 ) ] ], 'a6' => [ [ qw( a8 b8 c8 c7 c6 c5 c4 b4 a4 ) ] ], 'a7' => [ [ qw( c8 c7 c6 c5 b5 a5 ) ] ], 'a8' => [ [ qw( a6 b6 c6 c7 c8 ) ] ], 'b1' => [ [ qw( a3 b3 c3 d3 d2 d1 ) ] ], 'b2' => [ [ qw( a4 b4 c4 d4 d3 d2 d1 ) ] ], 'b3' => [ [ qw( a5 b5 c5 d5 d4 d3 d2 d1 c1 b1 a1 ) ] ], 'b4' => [ [ qw( a6 b6 c6 d6 d5 d4 d3 d2 c2 b2 a2 ) ] ], 'b5' => [ [ qw( a7 b7 c7 d7 d6 d5 d4 d3 c3 b3 a3 ) ] ], 'b6' => [ [ qw( a8 b8 c8 d8 d7 d6 d5 d4 c4 b4 a4 ) ] ], 'b7' => [ [ qw( d8 d7 d6 d5 c5 b5 a5 ) ] ], 'b8' => [ [ qw( a6 b6 c6 d6 d7 d8 ) ] ], 'c1' => [ [ qw( a1 a2 a3 b3 c3 d3 e3 e2 e1 ) ] ], 'c2' => [ [ qw( a2 a3 a4 b4 c4 d4 e4 e3 e2 a1 e1 ) ] ], 'c3' => [ [ qw( a5 b5 c5 d5 e5 e4 e3 e2 e1 d1 c1 b1 a1 a2 a3 a +4 ) ] ], 'c4' => [ [ qw( a6 b6 c6 d6 e6 e5 e4 e3 e2 d2 c2 b2 a2 a3 a4 a +5 ) ] ], 'c5' => [ [ qw( a7 b7 c7 d7 e7 e6 e5 e4 e3 d3 c3 b3 a3 a4 a5 a +6 ) ] ], 'c6' => [ [ qw( a8 b8 c8 d8 e8 e7 e6 e5 e4 d4 c4 b4 a4 a5 a6 a +7 ) ] ], 'c7' => [ [ qw( e8 e7 e6 e5 d5 c5 b5 a5 a6 a7 a8 ) ] ], 'c8' => [ [ qw( a8 a7 a6 b6 c6 d6 e6 e7 e8 ) ] ], 'd1' => [ [ qw( b1 b2 b3 c3 d3 e3 f3 f2 f1 ) ] ], 'd2' => [ [ qw( b2 b3 b4 c4 d4 e4 f4 f3 f2 b1 f1 ) ] ], 'd3' => [ [ qw( b5 c5 d5 e5 f5 f4 f3 f2 f1 e1 d1 c1 b1 b2 b3 b +4 ) ] ], 'd4' => [ [ qw( b6 c6 d6 e6 f6 f5 f4 f3 f2 e2 d2 c2 b2 b3 b4 b +5 ) ] ], 'd5' => [ [ qw( b7 c7 d7 e7 f7 f6 f5 f4 f3 e3 d3 c3 b3 b4 b5 b +6 ) ] ], 'd6' => [ [ qw( b8 c8 d8 e8 f8 f7 f6 f5 f4 e4 d4 c4 b4 b5 b6 b +7 ) ] ], 'd7' => [ [ qw( f8 f7 f6 f5 e5 d5 c5 b5 b6 b7 b8 ) ] ], 'd8' => [ [ qw( b8 b7 b6 c6 d6 e6 f6 f7 f8 ) ] ], 'e1' => [ [ qw( c1 c2 c3 d3 e3 f3 g3 g2 g1 ) ] ], 'e2' => [ [ qw( c2 c3 c4 d4 e4 f4 g4 g3 g2 c1 g1 ) ] ], 'e3' => [ [ qw( c5 d5 e5 f5 g5 g4 g3 g2 g1 f1 e1 d1 c1 c2 c3 c +4 ) ] ], 'e4' => [ [ qw( c6 d6 e6 f6 g6 g5 g4 g3 g2 f2 e2 d2 c2 c3 c4 c +5 ) ] ], 'e5' => [ [ qw( c7 d7 e7 f7 g7 g6 g5 g4 g3 f3 e3 d3 c3 c4 c5 c +6 ) ] ], 'e6' => [ [ qw( c8 d8 e8 f8 g8 g7 g6 g5 g4 f4 e4 d4 c4 c5 c6 c +7 ) ] ], 'e7' => [ [ qw( g8 g7 g6 g5 f5 e5 d5 c5 c6 c7 c8 ) ] ], 'e8' => [ [ qw( c8 c7 c6 d6 e6 f6 g6 g7 g8 ) ] ], 'f1' => [ [ qw( d1 d2 d3 e3 f3 g3 h3 h2 h1 ) ] ], 'f2' => [ [ qw( d2 d3 d4 e4 f4 g4 h4 h3 h2 d1 h1 ) ] ], 'f3' => [ [ qw( d5 e5 f5 g5 h5 h4 h3 h2 h1 g1 f1 e1 d1 d2 d3 d +4 ) ] ], 'f4' => [ [ qw( d6 e6 f6 g6 h6 h5 h4 h3 h2 g2 f2 e2 d2 d3 d4 d +5 ) ] ], 'f5' => [ [ qw( d7 e7 f7 g7 h7 h6 h5 h4 h3 g3 f3 e3 d3 d4 d5 d +6 ) ] ], 'f6' => [ [ qw( d8 e8 f8 g8 h8 h7 h6 h5 h4 g4 f4 e4 d4 d5 d6 d +7 ) ] ], 'f7' => [ [ qw( h8 h7 h6 h5 g5 f5 e5 d5 d6 d7 d8 ) ] ], 'f8' => [ [ qw( d8 d7 d6 e6 f6 g6 h6 h7 h8 ) ] ], 'g1' => [ [ qw( e1 e2 e3 f3 g3 h3 ) ] ], 'g2' => [ [ qw( e2 e3 e4 f4 g4 h4 e1 ) ] ], 'g3' => [ [ qw( e5 f5 g5 h5 h1 g1 f1 e1 e2 e3 e4 ) ] ], 'g4' => [ [ qw( e6 f6 g6 h6 h2 g2 f2 e2 e3 e4 e5 ) ] ], 'g5' => [ [ qw( e7 f7 g7 h7 h3 g3 f3 e3 e4 e5 e6 ) ] ], 'g6' => [ [ qw( e8 f8 g8 h8 h4 g4 f4 e4 e5 e6 e7 ) ] ], 'g7' => [ [ qw( h5 g5 f5 e5 e6 e7 e8 ) ] ], 'g8' => [ [ qw( e8 e7 e6 f6 g6 h6 ) ] ], 'h1' => [ [ qw( f1 f2 f3 g3 h3 ) ] ], 'h2' => [ [ qw( f2 f3 f4 g4 h4 f1 ) ] ], 'h3' => [ [ qw( f5 g5 h5 h1 g1 f1 f2 f3 f4 ) ] ], 'h4' => [ [ qw( f6 g6 h6 h2 g2 f2 f3 f4 f5 ) ] ], 'h5' => [ [ qw( f7 g7 h7 h3 g3 f3 f4 f5 f6 ) ] ], 'h6' => [ [ qw( f8 g8 h8 h4 g4 f4 f5 f6 f7 ) ] ], 'h7' => [ [ qw( h5 g5 f5 f6 f7 f8 ) ] ], 'h8' => [ [ qw( f8 f7 f6 g6 h6 ) ] ], }, 'c' => { # 'Cardinal' -- a hypothetical piece created for use with the # 'attack' program. This piece moves/attacks in a diamond # shape; moving exactly 1-diagonal square in a diagonal direct +ion, # or exactly 2 squares in a horizontal or vertical direction. # 'a1' => [ [ qw( a3 b2 c1 ) ] ], 'a2' => [ [ qw( a4 b3 c2 b1 ) ] ], 'a3' => [ [ qw( a5 b4 c3 b2 a1 ) ] ], 'a4' => [ [ qw( a6 b5 c4 b3 a2 ) ] ], 'a5' => [ [ qw( a7 b6 c5 b4 a3 ) ] ], 'a6' => [ [ qw( a8 b7 c6 b5 a4 ) ] ], 'a7' => [ [ qw( b8 c7 b6 a5 ) ] ], 'a8' => [ [ qw( b7 a6 c8 ) ] ], 'b1' => [ [ qw( a2 b3 c2 d1 ) ] ], 'b2' => [ [ qw( a3 b4 c3 d2 c1 a1 ) ] ], 'b3' => [ [ qw( a4 b5 c4 d3 c2 b1 a2 ) ] ], 'b4' => [ [ qw( a5 b6 c5 d4 c3 b2 a3 ) ] ], 'b5' => [ [ qw( a6 b7 c6 d5 c4 b3 a4 ) ] ], 'b6' => [ [ qw( a7 b8 c7 d6 c5 b4 a5 ) ] ], 'b7' => [ [ qw( c8 d7 c6 b5 a6 a8 ) ] ], 'b8' => [ [ qw( a7 b6 c7 d8 ) ] ], 'c1' => [ [ qw( a1 b2 c3 d2 e1 ) ] ], 'c2' => [ [ qw( a2 b3 c4 d3 e2 d1 b1 ) ] ], 'c3' => [ [ qw( a3 b4 c5 d4 e3 d2 c1 b2 ) ] ], 'c4' => [ [ qw( a4 b5 c6 d5 e4 d3 c2 b3 ) ] ], 'c5' => [ [ qw( a5 b6 c7 d6 e5 d4 c3 b4 ) ] ], 'c6' => [ [ qw( a6 b7 c8 d7 e6 d5 c4 b5 ) ] ], 'c7' => [ [ qw( d8 e7 d6 c5 b6 a7 b8 ) ] ], 'c8' => [ [ qw( a8 b7 c6 d7 e8 ) ] ], 'd1' => [ [ qw( b1 c2 d3 e2 f1 ) ] ], 'd2' => [ [ qw( b2 c3 d4 e3 f2 e1 c1 ) ] ], 'd3' => [ [ qw( b3 c4 d5 e4 f3 e2 d1 c2 ) ] ], 'd4' => [ [ qw( b4 c5 d6 e5 f4 e3 d2 c3 ) ] ], 'd5' => [ [ qw( b5 c6 d7 e6 f5 e4 d3 c4 ) ] ], 'd6' => [ [ qw( b6 c7 d8 e7 f6 e5 d4 c5 ) ] ], 'd7' => [ [ qw( e8 f7 e6 d5 c6 b7 c8 ) ] ], 'd8' => [ [ qw( b8 c7 e7 f8 d6 ) ] ], 'e1' => [ [ qw( c1 d2 e3 f2 g1 ) ] ], 'e2' => [ [ qw( c2 d3 e4 f3 g2 f1 d1 ) ] ], 'e3' => [ [ qw( c3 d4 e5 f4 g3 f2 e1 d2 ) ] ], 'e4' => [ [ qw( c4 d5 e6 f5 g4 f3 e2 d3 ) ] ], 'e5' => [ [ qw( c5 d6 e7 f6 g5 f4 e3 d4 ) ] ], 'e6' => [ [ qw( c6 d7 e8 f7 g6 f5 e4 d5 ) ] ], 'e7' => [ [ qw( f8 g7 f6 e5 d6 c7 d8 ) ] ], 'e8' => [ [ qw( c8 d7 e6 f7 g8 ) ] ], 'f1' => [ [ qw( d1 e2 f3 g2 h1 ) ] ], 'f2' => [ [ qw( d2 e3 f4 g3 h2 g1 e1 ) ] ], 'f3' => [ [ qw( d3 e4 f5 g4 h3 g2 f1 e2 ) ] ], 'f4' => [ [ qw( d4 e5 f6 g5 h4 g3 f2 e3 ) ] ], 'f5' => [ [ qw( d5 e6 f7 g6 h5 g4 f3 e4 ) ] ], 'f6' => [ [ qw( d6 e7 f8 g7 h6 g5 f4 e5 ) ] ], 'f7' => [ [ qw( g8 h7 g6 f5 e6 d7 e8 ) ] ], 'f8' => [ [ qw( d8 e7 f6 g7 h8 ) ] ], 'g1' => [ [ qw( e1 f2 g3 h2 ) ] ], 'g2' => [ [ qw( e2 f3 g4 h3 h1 f1 ) ] ], 'g3' => [ [ qw( e3 f4 g5 h4 h2 g1 f2 ) ] ], 'g4' => [ [ qw( e4 f5 g6 h5 h3 g2 f3 ) ] ], 'g5' => [ [ qw( e5 f6 g7 h6 h4 g3 f4 ) ] ], 'g6' => [ [ qw( e6 f7 g8 h7 h5 g4 f5 ) ] ], 'g7' => [ [ qw( h8 h6 g5 f6 e7 f8 ) ] ], 'g8' => [ [ qw( e8 f7 g6 h7 ) ] ], 'h1' => [ [ qw( f1 g2 h3 ) ] ], 'h2' => [ [ qw( f2 g3 h4 g1 ) ] ], 'h3' => [ [ qw( f3 g4 h5 h1 g2 ) ] ], 'h4' => [ [ qw( f4 g5 h6 h2 g3 ) ] ], 'h5' => [ [ qw( f5 g6 h7 h3 g4 ) ] ], 'h6' => [ [ qw( f6 g7 h8 h4 g5 ) ] ], 'h7' => [ [ qw( g6 f7 g8 h5 ) ] ], 'h8' => [ [ qw( f8 g7 h6 ) ] ], }, }; sub legal_moves { my ($this) = @_; return $p_legal_moves; } sub attacks { my ($this, $piece, $square) = @_; my @squares; my $plegal = $p_legal_moves->{$piece}->{$square}; foreach my $plist (@$plegal) { push @squares, @$plist; } return \@squares; } sub is_attacked { my ($this, $pboard, $square) = @_; foreach my $occupied (keys %$pboard) { my $occupier = $pboard->{$occupied}; my $pattack = $this->attacks($occupier, $occupied); map { ($_ eq $square) and return 1 } @$pattack; } return 0; } sub attackers { my ($this, $pboard, $square) = @_; my @list = ( ); foreach my $occupied (keys %$pboard) { my $occupier = $pboard->{$occupied}; my $pattack = $this->attacks($occupier, $occupied); map { ($_ eq $square) and push @list, $occupied } @$pattack; } return \@list; } sub new { my ($class) = @_; my $this = { 'all' => $p_legal_moves, }; # Bless the object and return it bless $this, $class; return $this; } 1;
The attack program has 2 main logic subroutines which call each other recursively.

The first, try_each_piece_each_square gets called once from the main program with the total number of pieces, and the list containing the piece names.  It perfroms some initialization, and then calls the subroutine try_each_square, to check the effects of putting the first piece on each square, and then the second piece, etc.  try_each_square itself makes a call back into try_each_piece_each_square which keeps track of the recursion level it's at at any time.  When it gets to the bottom level, if the board was successfully filled with all the pieces, that position is a valid solution.

Type attack without arguments to get a syntax message.  The original "Eight Queens Problem" can be solved with:  "attack -p q8".

In addition to the classical chess pieces, I included the 2 hypothetical pieces I used to test the program; 'G' (grasshopper) and 'C' cardinal.  Look at the comments in Legal.pm to see more about how these 2 unusual pieces move.


@ARGV=split//,"/:L"; map{print substr crypt($_,ord pop),2,3}qw"PerlyouC READPIPE provides"

Replies are listed 'Best First'.
Re: "Attack" -- Find Solutions for N Non-Attacking Chess Pieces
by hossman (Prior) on Jan 14, 2006 at 08:34 UTC

    I have not tried running this, or even looked at your code very carefully, but i wanted to make a suggestion regarding the format of your Legal.pm...

    It seems like it might be a lot more readable (and probably reusable when defining hypothetical pieces) if you created named hash refrences for the two major classifications of move types: diagonally and horizontally. Then defined the legal attacks for the individual pieces based on those where appropriate (ie: bishop is an alias for the diagonal hash, rook is an alias for the horisontal hash, queen is a merge of both).

    Alternatly (and the more i think about it, even better) you could impliment the set of legal attacks for a peice as a function ref instead of a hash ref -- where the function takes in a current location, and returns the list of legal atacks -- for simple pieces like the rook, pawn and king these functions are trivial. for things like bishop, and knight the math is a little more complicated, but still much shorter then your giant hashes. Once again the queen can be implimented by calling both the rook and bishop functions and unioning the results.

      Well, let me explain why I didn't choose any of those methods for implementing the data structure.

      I implemented the data structure before anything else, including the original Eight Queens Problem, and one of my foremost priorities for it was speed.  That would rule out function references; if you're trying to make things as fast as possible, you can't make each legal move a function call.

      As far as why I didn't define things in terms of diagonals versus horizontal/vertical moves:  the data structure needed to contain AoA for each square for each piece rather than simply an array, and the reason for that was, when calculating the directions for a piece such as a bishop, rook or queen, you have to stop as soon as you hit another piece (if the piece is of the opposite color, it can be captured, of course).  Besides which, pawns, knights and kings wouldn't follow those same rules, so what would be the point?

      When I created the data structure, I *did* actually calculate the rook moves and bishop moves first, and then just "added" them together to get the queen.

      So I hope you understand my reasoning.  Maybe if you try running the program, you'll see why optimizing for speed was my primary goal.


      @ARGV=split//,"/:L"; map{print substr crypt($_,ord pop),2,3}qw"PerlyouC READPIPE provides"
Re: "Attack" -- Find Solutions for N Non-Attacking Chess Pieces
by strat (Canon) on Jan 15, 2006 at 10:54 UTC

    One idea of optimizing for speed sprang into my mind: maybe using a one-dimensional-array for the board instead of a two-dimensional one might be faster.

    e.g if the board looks like:

    133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 097 | 098 | 099 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 085 | 086 | 087 | 088 | 089 | 090 | 091 | 092 | 093 | 094 | 095 | 096 073 | 074 | 075 | 076 | 077 | 078 | 079 | 080 | 081 | 082 | 083 | 084 061 | 062 | 063 | 064 | 065 | 066 | 067 | 068 | 069 | 070 | 071 | 072 049 | 050 | 051 | 052 | 053 | 054 | 055 | 056 | 057 | 058 | 059 | 060 037 | 038 | 039 | 040 | 041 | 042 | 043 | 044 | 045 | 046 | 047 | 048 025 | 026 | 027 | 028 | 029 | 030 | 031 | 032 | 033 | 034 | 035 | 036 013 | 014 | 015 | 016 | 017 | 018 | 019 | 020 | 021 | 022 | 023 | 024 001 | 002 | 003 | 004 | 005 | 006 | 007 | 008 | 009 | 010 | 011 | 012
    • the inner 8x8 are the playfield (e.g. 027 is a1, 118 is h8)
    • if you just use an array of 8x8= 1..64 (or maybe 0..63), it may become difficult for pieces to find out if they went out of the board at the right hand side and entered it with the left hand side (especially the knight). So the frame fields are forbidden (and you can use 0,1, 12, 133,144 for other purpose, e.g. whose move is next, is castling allowed, ...)
    • with a one-dimensional array a move is just a calculation of one dimension and not of two.

    but for just the 8-queens-problem this may be an overkill, I don't know

    Best regards,
    perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"

Re: "Attack" -- Find Solutions for N Non-Attacking Chess Pieces
by zentara (Cardinal) on Jan 14, 2006 at 12:48 UTC
    What? No Tk visualization? ;-)

    I'm not really a human, but I play one on earth. flash japh
      I was originally going to post the program makelegal which is a Tk GUI for creating the Legal.pm module.  But it would have taken too much space, which I was out of already after posting the two files above.  The makelegal program consists of several modules, Icons.pm, Legal.pm (the same one above) and Gui.pm, all of which are necessary for constructing the chessboard as a Tk app.  You can imagine that Icons.pm itself takes up a huge amount of space, as it contains the images for each piece!

      I have to admit, I'm a little disappointed by both of these comments.  I thought more people would be interested in the program itself (I've been having fun trying it on different combinations of pieces, myself), but the feedback is more along the lines of "I'm not going to waste time trying your program, but let me point out how you should have done it instead!"

      So if you or anyone wants the code for the Tk part of it, just message me, and I'll email it, or send a link or something.  You'll understand, I trust, why I don't post it for more people to criticize.


      @ARGV=split//,"/:L"; map{print substr crypt($_,ord pop),2,3}qw"PerlyouC READPIPE provides"

        Hi liverpole,

        I'm just yersterday joined to PerlMonks. I like chess, Perl and Tk, so I will glad if you send me an attach or a link (I don't know the better way) of your program makelegal , because I have appreciated your work.

        Best regards

        Tchai