File Coverage

blib/lib/Chess/Rep.pm
Criterion Covered Total %
statement 289 430 67.2
branch 129 238 54.2
condition 63 143 44.0
subroutine 27 37 72.9
pod 21 21 100.0
total 529 869 60.8


line stmt bran cond sub pod time code
1             package Chess::Rep;
2              
3 2     2   43799 use strict;
  2         6  
  2         75  
4              
5 2     2   1802 use POSIX;
  2         15457  
  2         16  
6              
7             our $VERSION = '0.8';
8              
9             use constant ({
10 2         270 CASTLE_W_OO => 1,
11             CASTLE_W_OOO => 2,
12             CASTLE_B_OO => 4,
13             CASTLE_B_OOO => 8,
14             PIECE_TO_ID => {
15             p => 0x01, # black pawn
16             n => 0x02, # black knight
17             k => 0x04, # black king
18             b => 0x08, # black bishop
19             r => 0x10, # black rook
20             q => 0x20, # black queen
21             P => 0x81, # white pawn
22             N => 0x82, # white knight
23             K => 0x84, # white king
24             B => 0x88, # white bishop
25             R => 0x90, # white rook
26             Q => 0xA0, # white queen
27             },
28             ID_TO_PIECE => [
29             undef, # 0
30             'p', # 1
31             'n', # 2
32             undef, # 3
33             'k', # 4
34             undef, # 5
35             undef, # 6
36             undef, # 7
37             'b', # 8
38             undef, # 9
39             undef, # 10
40             undef, # 11
41             undef, # 12
42             undef, # 13
43             undef, # 14
44             undef, # 15
45             'r', # 16
46             undef, # 17
47             undef, # 18
48             undef, # 19
49             undef, # 20
50             undef, # 21
51             undef, # 22
52             undef, # 23
53             undef, # 24
54             undef, # 25
55             undef, # 26
56             undef, # 27
57             undef, # 28
58             undef, # 29
59             undef, # 30
60             undef, # 31
61             'q', # 32
62             ],
63             FEN_STANDARD => 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
64 2     2   13018 });
  2         9  
65              
66 2     2   10 use Exporter 'import';
  2         5  
  2         12371  
67              
68             our %EXPORT_TAGS = (
69             castle => [
70             qw( CASTLE_W_OO
71             CASTLE_W_OOO
72             CASTLE_B_OO
73             CASTLE_B_OOO
74             )],
75             other => [
76             qw( PIECE_TO_ID
77             ID_TO_PIECE
78             FEN_STANDARD
79             )],
80             );
81              
82             {
83             my %seen;
84              
85             push @{$EXPORT_TAGS{all}},
86             grep {!$seen{$_}++} @{$EXPORT_TAGS{$_}} foreach keys %EXPORT_TAGS;
87             }
88              
89             Exporter::export_ok_tags('castle');
90             Exporter::export_ok_tags('all');
91              
92             my @MOVES_N = (31, 33, 14, 18, -18, -14, -33, -31);
93             my @MOVES_B = (15, 17, -15, -17);
94             my @MOVES_R = (1, 16, -16, -1);
95             my @MOVES_K = (@MOVES_B, @MOVES_R);
96              
97             =head1 NAME
98              
99             Chess::Rep - represent chess positions, generate list of legal moves, parse moves in various formats.
100              
101             The name stands for "Chess Representation", basically meaning that
102             this module won't actually play chess -- it just helps you represent
103             the board and validate the moves according to the laws of chess. It
104             also generates a set of all valid moves for the color to play.
105              
106             =head1 SYNOPSIS
107              
108             my $pos = Chess::Rep->new;
109             print $pos->get_fen;
110              
111             # use any decent notation to describe moves
112             # the parser will read pretty much anything which isn't ambiguous
113              
114             $pos->go_move('e4');
115             $pos->go_move('e7e5');
116             $pos->go_move('Bc4');
117             $pos->go_move('Nc8-C6');
118             $pos->go_move('Qf3');
119             $pos->go_move('d6');
120             $pos->go_move('F3-F7');
121              
122             if ($pos->status->{check}) {
123             print("CHECK\n");
124             }
125              
126             if ($pos->status->{mate}) {
127             print("MATE\n");
128             }
129              
130             if ($pos->status->{stalemate}) {
131             print("STALEMATE\n");
132             }
133              
134             # reset position from FEN
135              
136             $pos->set_from_fen('r1b1k1nr/pp1ppppp/8/2pP4/3b4/8/PPP1PqPP/RNBQKBNR w KQkq - 0 1');
137             my $status = $pos->status;
138              
139             my $moves = $status->{moves}; # there's only one move, E1-D2
140             print Chess::Rep::get_field_id($moves->[0]{from}) . '-' .
141             Chess::Rep::get_field_id($moves->[0]{to});
142              
143             print $status->{check}; # 1
144             print $status->{mate};
145             print $status->{stalemate};
146              
147             =head1 REPRESENTATION
148              
149             =head2 Pieces and colors
150              
151             As of version B<0.4>, a piece is represented as a byte, as follows:
152              
153             p => 0x01 # black pawn
154             n => 0x02 # black knight
155             k => 0x04 # black king
156             b => 0x08 # black bishop
157             r => 0x10 # black rook
158             q => 0x20 # black queen
159             P => 0x81 # white pawn
160             N => 0x82 # white knight
161             K => 0x84 # white king
162             B => 0x88 # white bishop
163             R => 0x90 # white rook
164             Q => 0xA0 # white queen
165              
166             This representation is incompatible with older versions, which were
167             representing a piece as a char. Performance is the main reason for
168             this change. For example, in order to test if a piece is king
169             (regardless the color) we now do:
170              
171             $p & 0x04
172              
173             while in versions prior to 0.4 we needed to do:
174              
175             lc $p eq 'k'
176              
177             Similarly, if we wanted to check if a piece is a queen or a bishop, in
178             previous version we had:
179              
180             lc $p eq 'q' || lc $p eq 'b'
181              
182             while in the new version we do:
183              
184             $p & 0x28
185              
186             which is considerably faster. (if you wonder why the difference
187             between 0.03 milliseconds and 0.01 milliseconds matters all that much,
188             try writing a chess engine).
189              
190             To determine the color of a piece, AND with 0x80 (zero means a black
191             piece, 0x80 is white piece). In previous version we needed to do uc
192             $p eq $p, a lot slower.
193              
194             =head2 Position
195              
196             The diagram is represented in the "0x88 notation" (see [2]) -- an
197             array of 128 elements, of which only 64 are used. An index in this
198             array maps directly to a row, col in the chess board like this:
199              
200             my ($row, $col) = (1, 4); # E2
201             my $index = $row << 4 | $col; ( = 0x14)
202              
203             Valid row and col numbers are 0..7 (so they have bit 4 unset),
204             therefore it's easy to detect when an index is offboard by AND with
205             0x88. Read [2] for more detailed description of this representation.
206              
207             =head2 Some terms used in this doc
208              
209             Following, when I refer to a field "index", I really mean an index in
210             the position array, which can be 0..127. Using get_index() you can
211             compute an index from a field ID.
212              
213             By field ID I mean a field in standard notation, i.e. 'e4' (case
214             insensitive).
215              
216             When I refer to row / col, I mean a number 0..7. Field A1 corresponds
217             to row = 0 and col = 0, and has index 0x00. Field H7 has row = 7, col
218             = 7 and index 0x77.
219              
220             Internally this object works with field indexes.
221              
222             =cut
223              
224             =head1 OBJECT METHODS
225              
226             =head2 new($fen)
227              
228             Constructor. Pass a FEN string if you want to initialize to a certain
229             position. Otherwise it will be initialized with the standard starting
230             position.
231              
232             =cut
233              
234             sub new {
235 1     1 1 17 my ($class, $fen) = @_;
236 1         3 my $self = {};
237 1         3 bless $self, $class;
238 1   50     14 $self->set_from_fen($fen || FEN_STANDARD);
239 1         8 return $self;
240             }
241              
242             =head2 reset()
243              
244             Resets the object to standard start position.
245              
246             =cut
247              
248             sub reset {
249 0     0 1 0 shift->set_from_fen(FEN_STANDARD);
250             }
251              
252             =head2 set_from_fen($fen)
253              
254             Reset this object to a position described in FEN notation.
255              
256             =cut
257              
258             sub set_from_fen {
259 7     7 1 8309 my ($self, $fen) = @_;
260 7         35 $self->_reset;
261 7         309 my @data = split(/\s+/, $fen);
262 7         57 my ($board, $to_move, $castle, $enpa, $halfmove, $fullmove) = @data;
263 7         51 my @board = reverse(split(/\//, $board));
264 7         27 for my $row (0..7) {
265 56         88 my $data = $board[$row];
266 56         60 my $col = 0;
267 56         113 while (length $data > 0) {
268 143         257 my $p = substr($data, 0, 1, '');
269 143         430 my $id = PIECE_TO_ID->{$p};
270 143 100       643 if ($id) {
    50          
271 74         269 $self->set_piece_at_index(get_index_from_row_col($row, $col++), $id);
272             } elsif ($p =~ /[1-8]/) {
273 69         328 $col += $p;
274             } else {
275 0         0 die "Error parsing FEN position: $fen";
276             }
277             }
278             }
279 7         18 my $c = 0;
280 7 100       39 $c |= CASTLE_W_OO if index($castle, 'K') >= 0;
281 7 100       26 $c |= CASTLE_W_OOO if index($castle, 'Q') >= 0;
282 7 100       26 $c |= CASTLE_B_OO if index($castle, 'k') >= 0;
283 7 100       23 $c |= CASTLE_B_OOO if index($castle, 'q') >= 0;
284 7         15 $self->{castle} = $c;
285 7 100       39 if (lc $to_move eq 'w') {
    50          
286 1         3 $self->{to_move} = 0x80;
287             } elsif (lc $to_move eq 'b') {
288 6         13 $self->{to_move} = 0;
289             } else {
290 0         0 $self->{to_move} = undef;
291             }
292 7 50       27 $self->{enpa} = $enpa ne '-' ? get_index($enpa) : 0;
293 7         15 $self->{fullmove} = $fullmove;
294 7         11 $self->{halfmove} = $halfmove;
295 7         29 $self->compute_valid_moves;
296             }
297              
298             =head2 get_fen()
299              
300             Returns the current position in standard FEN notation.
301              
302             =cut
303              
304             sub get_fen {
305 0     0 1 0 my ($self, $short) = @_;
306 0         0 my @a;
307 0         0 for (my $row = 8; --$row >= 0;) {
308 0         0 my $str = '';
309 0         0 my $empty = 0;
310 0         0 for my $col (0..7) {
311 0         0 my $p = $self->get_piece_at_index(get_index_from_row_col($row, $col));
312 0 0       0 if ($p) {
313 0 0       0 $p = ($p & 0x80) ? uc ID_TO_PIECE->[$p & 0x3F] : ID_TO_PIECE->[$p];
314 0 0       0 $str .= $empty
315             if $empty;
316 0         0 $empty = 0;
317 0         0 $str .= $p;
318             } else {
319 0         0 ++$empty;
320             }
321             }
322 0 0       0 $str .= $empty
323             if $empty;
324 0         0 push @a, $str;
325             }
326 0         0 my $pos = join('/', @a);
327 0         0 @a = ( $pos );
328 0 0       0 $a[1] = $self->{to_move} ? 'w' : 'b';
329 0         0 my $castle = $self->{castle};
330 0         0 my $c = '';
331 0 0       0 $c .= 'K' if $castle & CASTLE_W_OO;
332 0 0       0 $c .= 'Q' if $castle & CASTLE_W_OOO;
333 0 0       0 $c .= 'k' if $castle & CASTLE_B_OO;
334 0 0       0 $c .= 'q' if $castle & CASTLE_B_OOO;
335 0   0     0 $a[2] = $c || '-';
336 0 0       0 $a[3] = $self->{enpa} ? lc get_field_id($self->{enpa}) : '-';
337 0 0       0 if (!$short) {
338 0         0 $a[4] = $self->{halfmove};
339 0         0 $a[5] = $self->{fullmove};
340             }
341 0         0 return join(' ', @a);
342             }
343              
344             =head2 status()
345              
346             Returns the status of the current position. The status is
347             automatically computed whenever the position is changed with
348             set_from_fen() or go_move(). The return valus is a hash as follows:
349              
350             {
351             moves => \@array_of_all_legal_moves,
352             pieces => \@array_of_pieces_to_move,
353             hash_moves => \%hash_of_all_legal_moves,
354             type_moves => \%hash_of_moves_by_type_and_target_field,
355             check => 1 if king is in check, undef otherwise,
356             mate => 1 if position is mate, undef otherwise,
357             stalemate => 1 if position is stalemate, undef otherwise
358             }
359              
360             The last three are obvious -- simple boolean indicators that describe
361             the position state. The first three are:
362              
363             =over
364              
365             =item * B
366              
367             An array of all the legal moves. A move is represented as a hash
368             containing:
369              
370             {
371             from => $index_of_origin_field,
372             to => $index_of_target_field,
373             piece => $id_of_the_moved_piece
374             }
375              
376             =item * B
377              
378             A hash table containing as keys all legal moves, in the form
379             "$from_index:$to_index". For example, should E2-E4 be the single
380             legal move, then this hash would be:
381              
382             {
383             '35-55' => 1
384             }
385              
386             =item * B
387              
388             Again a hash table that maps target fields to piece types. For
389             example, if you want to determine all white bishops that can move on
390             field C4 (index 58), you can do the following:
391              
392             my $a = $self->status->{type_moves}{58}{0x88};
393              
394             @$a now contains the indexes of the fields that currently hold white
395             bishops that are allowed to move on C4.
396              
397             This hash is mainly useful when we interpret standard algebraic
398             notation.
399              
400             =back
401              
402             =cut
403              
404             sub status {
405 0     0 1 0 return shift->{status};
406             }
407              
408             sub _reset {
409 7     7   14 my ($self) = @_;
410 7         211 my @a = (0) x 128;
411 7         34 $self->{pos} = \@a;
412 7         93 $self->{castle} = CASTLE_W_OO | CASTLE_W_OOO | CASTLE_B_OO | CASTLE_B_OOO;
413 7         26 $self->{has_castled} = 0;
414 7         19 $self->{to_move} = 0x80; # white
415 7         17 $self->{enpa} = 0;
416 7         12 $self->{halfmove} = 0;
417 7         21 $self->{fullmove} = 0;
418 7         23 $self->{status} = undef;
419             }
420              
421             =head2 set_piece_at($where, $piece)
422              
423             Sets the piece at the given position. $where can be:
424              
425             - a full index conforming to our representation
426             - a standard field ID (i.e. 'e2')
427              
428             The following are equivalent:
429              
430             $self->set_piece_at(0x14, 'P');
431             $self->set_piece_at('e2', 'P');
432              
433             Piece can be a piece ID as per our internal representation, or a piece
434             name such as 'P', 'B', etc.
435              
436             This function does not rebuild the valid moves hashes so if you call
437             status() you'll get wrong results. After you setup the position
438             manually using this function (same applies for set_piece_at_index())
439             you need to call $self->compute_valid_moves().
440              
441             =cut
442              
443             sub set_piece_at {
444 0     0 1 0 my ($self, $index, $p) = @_;
445 0 0       0 if ($p =~ /^[pnbrqk]$/i) {
446 0         0 $p = PIECE_TO_ID->{$p};
447             }
448 0 0       0 if ($index =~ /^[a-h]/oi) {
449 0         0 $index = get_index($index);
450             }
451 0         0 my $old = $self->{pos}[$index];
452 0         0 $self->{pos}[$index] = $p;
453 0         0 return $old;
454             }
455              
456             =head2 set_piece_at_index($index, $p)
457              
458             Sets the piece at the given index to $p. Returns the old piece. It's
459             similar to the function above, but faster as it only works with field
460             indexes.
461              
462             =cut
463              
464             sub set_piece_at_index {
465 86     86 1 6912 my ($self, $index, $p) = @_;
466 86         259 my $old = $self->{pos}[$index];
467 86         148 $self->{pos}[$index] = $p;
468 86         276 return $old;
469             }
470              
471             =head2 get_piece_at($where, $col)
472              
473             Returns the piece at the given position. $where can be:
474              
475             - a full index conforming to our representation
476             - a 0..7 row number (in which case $col is required)
477             - a standard field ID (i.e. 'e2')
478              
479             The following are equivalent:
480              
481             $self->get_piece_at('e2');
482             $self->get_piece_at(0x14);
483             $self->get_piece_at(1, 4);
484              
485             If you call this function in array context, it will return the index
486             of the field as well; this is useful if you don't pass a computed
487             index:
488              
489             ($piece, $index) = $self->get_piece_at('e2');
490             # now $piece is 'P' and $index is 0x14
491              
492             =cut
493              
494             sub get_piece_at {
495 6     6 1 17 my ($self, $index, $col) = @_;
496 6 50       36 if (defined $col) {
    50          
497 0         0 $index = get_index($index, $col);
498             } elsif ($index =~ /^[a-h]/oi) {
499 6         27 $index = get_index($index);
500             }
501 6         17 my $p = $self->{pos}[$index];
502 6 50       32 return ($p, $index)
503             if wantarray;
504 0         0 return $p;
505             }
506              
507             =head2 get_piece_at_index($index)
508              
509             Similar to the above function, this one is faster if you know for sure
510             that you pass an $index to it. That is, it won't support $row, $col
511             or field IDs, it only does field indexes.
512              
513             $self->get_piece_at_index(0x14)
514             == $self->get_piece_at(1, 4)
515             == $self->get_piece_at('e2')
516             == $self->get_piece_at(0x14)
517              
518             =cut
519              
520             sub get_piece_at_index {
521 1912     1912 1 4556 return shift->{pos}[shift];
522             }
523              
524             =head2 to_move()
525              
526             Returns (and optionally sets if you pass an argument) the color to
527             move. Colors are 0 (black) or 1 (white).
528              
529             =cut
530              
531             sub to_move {
532 0     0 1 0 my $self = shift;
533 0 0       0 if (@_) {
534 0 0       0 $self->{to_move} = $_[0] ? 0x80 : 0;
535             }
536 0         0 return $self->{to_move};
537             }
538              
539             =head2 go_move($move)
540              
541             Updates the position with the given move. The parser is very
542             forgiving; it understands a wide range of move formats:
543              
544             e4, e2e4, exf5, e:f5, e4xf5, e4f5, Nc3, b1c3, b1-c3,
545             a8=Q, a7a8q#, a7-a8=q#, a8Q, etc.
546              
547             After the move is executed, the position status is recomputed and you
548             can access it calling $self->status. Also, the turn is changed
549             internally (see L).
550              
551             This method returns a hash containing detailed information about this
552             move. For example, for "axb8=Q" it will return:
553              
554             {
555             from => 'A7'
556             from_index => 0x60
557             from_row => 6
558             from_col => 0
559             to => 'B8'
560             to_index => 0x71
561             to_row => 7
562             to_col => 1
563             piece => 'P'
564             promote => 'Q'
565             san => 'axb8=Q'
566             }
567              
568             Of course, the exact same hash would be returned for "a7b8q",
569             "A7-b8=Q", "b8Q". This method parses a move that can be given in a
570             variety of formats, and returns a canonical representation of it
571             (including a canonical SAN notation which should be understood by any
572             conformant parser on the planet).
573              
574             =cut
575              
576             sub go_move {
577 6     6 1 125 my ($self, $move) = @_;
578 6         11 my ($from, $from_index, $to, $to_index, $piece);
579              
580 6         17 my $color = $self->{to_move};
581 6         12 my $col;
582             my $row;
583 0         0 my $promote;
584              
585 6         13 my $orig_move = $move;
586              
587 6 50       40 if (index($move, 'O-O-O') == 0) {
    50          
588 0 0       0 $move = $color ? 'E1C1' : 'E8C8';
589             } elsif (index($move, 'O-O') == 0) {
590 0 0       0 $move = $color ? 'E1G1' : 'E8G8';
591             }
592              
593 6 50       51 if ($move =~ s/^([PNBRQK])//) {
594 0         0 $piece = lc $1;
595             }
596              
597 6 50       52 if ($move =~ s/^([a-h][1-8])[:x-]?([a-h][1-8])//i) { # great, no ambiguities
    0          
    0          
    0          
598              
599 6         34 ($from, $to) = ($1, $2);
600              
601             } elsif ($move =~ s/^([a-h])[:x-]?([a-h][1-8])//i) {
602              
603 0         0 $col = ord(uc $1) - 65;
604 0         0 $to = $2;
605              
606             } elsif ($move =~ s/^([1-8])[:x-]?([a-h][1-8])//i) {
607              
608 0         0 $row = ord($1) - 49;
609 0         0 $to = $2;
610              
611             } elsif ($move =~ s/^[:x-]?([a-h][1-8])//i) {
612              
613 0         0 $to = $1;
614              
615             } else {
616              
617 0         0 die("Could not parse move: $orig_move");
618              
619             }
620              
621 6 50       24 if ($move =~ s/^=?([RNBQ])//i) {
622 0         0 $promote = uc $1;
623             }
624              
625 6 50       15 if ($piece) {
626 0         0 $piece = PIECE_TO_ID->{$piece};
627             } else {
628 6 50       26 if (!$from) {
629 0         0 $piece = 1; # black pawn
630             } else {
631 6         26 ($piece, $from_index) = $self->get_piece_at($from);
632 6 50       23 if (!$piece) {
633 0         0 die("Illegal move: $orig_move (field $from is empty)");
634             }
635             }
636             }
637              
638 6         8 $piece |= $color; # apply color
639              
640 6 50       16 if (!$to) {
641 0         0 die("Can't parse move: $orig_move (missing target field)");
642             }
643              
644 6         12 $to_index = get_index($to);
645              
646             # all moves that a piece of type $piece can make to field $to_index
647 6         35 my $tpmove = $self->{status}{type_moves}{$to_index}{$piece};
648              
649 6 50 33     36 if (!$tpmove || !@$tpmove) {
650 0         0 die("Illegal move: $orig_move");
651             }
652              
653 6 50       21 if (!$from) {
654             # print Data::Dumper::Dumper($tpmove), "\n";
655 0 0       0 if (@$tpmove == 1) {
656             # unambiguous
657 0         0 $from_index = $tpmove->[0];
658             } else {
659 0         0 foreach my $origin (@$tpmove) {
660 0         0 my ($t_row, $t_col) = get_row_col($origin);
661 0 0 0     0 if (defined($row) && $row == $t_row) {
    0 0        
662 0         0 $from_index = $origin;
663 0         0 last;
664             } elsif (defined($col) && $col == $t_col) {
665 0         0 $from_index = $origin;
666 0         0 last;
667             }
668             }
669             }
670 0 0       0 if (defined $from_index) {
671 0         0 $from = get_field_id($from_index);
672             } else {
673 0         0 die("Ambiguous move: $orig_move");
674             }
675             } else {
676 6 50 33     49 die "Illegal move: $orig_move!\n"
677             unless ( defined $from_index && grep $_ == $from_index, @$tpmove );
678             }
679              
680 6 50       223 unless (defined $from_index) {
681 0         0 $from_index = get_index($from);
682             }
683              
684 6         14 $from = uc $from;
685 6         9 $to = uc $to;
686              
687 6         19 my ($from_row, $from_col) = get_row_col($from_index);
688 6         15 my ($to_row, $to_col) = get_row_col($to_index);
689              
690             # execute move
691              
692 6         14 my $prev_enpa = $self->{enpa};
693 6         23 $self->{enpa} = 0;
694              
695 6         7 my $is_capture = 0;
696 6         10 my $san; # compute canonical notation
697 6         11 my $is_pawn = $piece & 0x01;
698              
699             SPECIAL: {
700             # 1. if it's castling, we have to move the rook
701 6 50       10 if ($piece & 0x04) { # is king?
  6         15  
702 0 0 0     0 if ($from_index == 0x04 && $to_index == 0x06) {
    0 0        
    0 0        
    0 0        
703 0         0 $san = 'O-O';
704 0         0 $self->{has_castled} |= CASTLE_W_OO;
705 0         0 $self->_move_piece(0x07, 0x05);
706 0         0 last SPECIAL;
707             } elsif ($from_index == 0x74 && $to_index == 0x76) {
708 0         0 $san = 'O-O';
709 0         0 $self->{has_castled} |= CASTLE_B_OO;
710 0         0 $self->_move_piece(0x77, 0x75);
711 0         0 last SPECIAL;
712             } elsif ($from_index == 0x04 && $to_index == 0x02) {
713 0         0 $san = 'O-O-O';
714 0         0 $self->{has_castled} |= CASTLE_W_OOO;
715 0         0 $self->_move_piece(0x00, 0x03);
716 0         0 last SPECIAL;
717             } elsif ($from_index == 0x74 && $to_index == 0x72) {
718 0         0 $san = 'O-O-O';
719 0         0 $self->{has_castled} |= CASTLE_B_OOO;
720 0         0 $self->_move_piece(0x70, 0x73);
721 0         0 last SPECIAL;
722             }
723             }
724              
725             # 2. is it en_passant?
726 6 100       19 if ($is_pawn) {
727 2 50 33     21 if ($from_col != $to_col && $prev_enpa && $prev_enpa == $to_index) {
      33        
728 0         0 $self->set_piece_at_index(get_index_from_row_col($from_row, $to_col), 0);
729 0         0 $is_capture = 1;
730 0         0 last SPECIAL;
731             }
732 2 50       11 if (abs($from_row - $to_row) == 2) {
733 0         0 $self->{enpa} = get_index_from_row_col(($from_row + $to_row) / 2, $from_col);
734             }
735             }
736             }
737              
738             {
739 6         5 my $promote_id;
  6         10  
740 6 50       15 if ($promote) {
741 0         0 $promote_id = PIECE_TO_ID->{lc $promote} | $color;
742             }
743 6         36 my $tmp = $self->_move_piece($from_index, $to_index, $promote_id);
744 6   66     29 $is_capture ||= $tmp;
745             }
746 6         12 $self->{to_move} ^= 0x80;
747              
748 6 50       19 if ($self->{to_move}) {
749 6         15 ++$self->{fullmove};
750             }
751              
752 6 100 66     49 if (!$is_pawn && !$is_capture) {
753 4         8 ++$self->{halfmove};
754             } else {
755 2         6 $self->{halfmove} = 0;
756             }
757              
758 6         23 my $status = $self->compute_valid_moves;
759              
760 6 50       487 if (!$san) {
761 6 100       26 $san = $is_pawn ? '' : uc ID_TO_PIECE->[$piece & 0x3F];
762 6 100 66     59 $san .= lc (substr($from,0,1)) if ($is_pawn and $is_capture);
763              
764 6         15 my ($ambiguous, $rank_ambiguous, $file_ambiguous) = (0, 0, 0);
765 6         13 foreach my $origin (@$tpmove) {
766 12 100       36 if ($origin != $from_index) {
767 6         10 $ambiguous = 1;
768 6         13 $file_ambiguous |= (($origin & 0x07) == ($from_index & 0x07));
769 6         19 $rank_ambiguous |= (($origin & 0x70) == ($from_index & 0x70));
770             }
771             }
772             # The capture by a pawn has already been dis-abmigousized above
773 6 100 66     40 if ($ambiguous and !($is_pawn and $is_capture)) {
      100        
774 4 100 100     25 if ($rank_ambiguous and $file_ambiguous) {
775 1         8 $san .= lc (substr($from,0,2));
776             } else {
777 3 100       8 if ($file_ambiguous) {
778 1         5 $san .= lc (substr($from,1,1));
779             } else {
780 2         9 $san .= lc (substr($from,0,1));
781             }
782             }
783             }
784 6 100       20 if ($is_capture) {
785 2         7 $san .= 'x';
786             }
787 6         14 $san .= lc $to;
788 6 50       18 $san .= "=$promote"
789             if $promote;
790             }
791              
792 6 50       32 if ($status->{mate}) {
    50          
793 0         0 $san .= '#';
794             } elsif ($status->{check}) {
795 0         0 $san .= '+';
796             }
797              
798             # _debug("$orig_move \t\t\t $san");
799              
800             return {
801 6         128 from => lc $from,
802             from_index => $from_index,
803             from_row => $from_row,
804             from_col => $from_col,
805             to => lc $to,
806             to_index => $to_index,
807             to_row => $to_row,
808             to_col => $to_col,
809             piece => $piece,
810             promote => $promote,
811             san => $san,
812             };
813             }
814              
815             sub _move_piece {
816 6     6   15 my ($self, $from, $to, $promote) = @_;
817 6         25 my $p = $self->set_piece_at_index($from, 0);
818 6 50       20 if ($p & 0x04) { # is king?
819 0 0       0 if ($p & 0x80) {
820 0         0 $self->{castle} = $self->{castle} | CASTLE_W_OOO ^ CASTLE_W_OOO;
821 0         0 $self->{castle} = $self->{castle} | CASTLE_W_OO ^ CASTLE_W_OO;
822             } else {
823 0         0 $self->{castle} = $self->{castle} | CASTLE_B_OOO ^ CASTLE_B_OOO;
824 0         0 $self->{castle} = $self->{castle} | CASTLE_B_OO ^ CASTLE_B_OO;
825             }
826             }
827 6 50 33     36 if ($from == 0x00 || $to == 0x00) {
828 0         0 $self->{castle} = $self->{castle} | CASTLE_W_OOO ^ CASTLE_W_OOO;
829             }
830 6 50 33     28 if ($from == 0x70 || $to == 0x70) {
831 0         0 $self->{castle} = $self->{castle} | CASTLE_B_OOO ^ CASTLE_B_OOO;
832             }
833 6 50 33     31 if ($from == 0x07 || $to == 0x07) {
834 0         0 $self->{castle} = $self->{castle} | CASTLE_W_OO ^ CASTLE_W_OO;
835             }
836 6 50 33     28 if ($from == 0x77 || $to == 0x77) {
837 0         0 $self->{castle} = $self->{castle} | CASTLE_B_OO ^ CASTLE_B_OO;
838             }
839 6   33     33 $self->set_piece_at_index($to, $promote || $p);
840             }
841              
842             =head2 compute_valid_moves()
843              
844             Rebuild the valid moves hashes that are returned by $self->status()
845             for the current position. You need to call this function when you
846             manually interfere with the position, such as when you use
847             set_piece_at() or set_piece_at_index() in order to setup the position.
848              
849             =cut
850              
851             sub compute_valid_moves {
852 13     13 1 25 my ($self) = @_;
853              
854 13         21 my @pieces;
855             my $king;
856 13         25 my $op_color = $self->{to_move} ^ 0x80;
857              
858 13         36 for my $row (0..7) {
859 104         178 for my $col (0..7) {
860 832         1520 my $i = get_index_from_row_col($row, $col);
861 832         1681 my $p = $self->get_piece_at_index($i);
862 832 100       3226 if ($p) {
863 114 100       453 if (($p & 0x80) == $self->{to_move}) {
864 56         226 push @pieces, {
865             from => $i,
866             piece => $p,
867             };
868 56 100       352 if ($p & 0x04) {
869             # remember king position
870 13         34 $king = $i;
871             }
872             }
873             }
874             }
875             }
876              
877 13 50       47 if (defined $king) {
878 13         48 $self->{in_check} = $self->is_attacked($king, $op_color);
879             }
880              
881 13         21 my @all_moves;
882             my %hash_moves;
883 0         0 my %type_moves;
884              
885 13         29 foreach my $p (@pieces) {
886 56         131 my $from = $p->{from};
887 56         203 my $moves = $self->_get_allowed_moves($from);
888 56         113 my $piece = $p->{piece};
889 56         74 my @valid_moves;
890 56 50       118 if (defined $king) {
891 56         90 my $is_king = $from == $king;
892 56         207 my $try_move = {
893             from => $from,
894             piece => $piece,
895             };
896 294 100       1666 @valid_moves = grep {
897 56         123 $try_move->{to} = $_,
898             !$self->is_attacked($is_king ? $_ : $king, $op_color, $try_move);
899             } @$moves;
900             } else {
901 0         0 @valid_moves = @$moves;
902             }
903             # _debug("Found moves for $piece");
904 56         174 $p->{to} = \@valid_moves;
905 294         481 push @all_moves, (map {
906 56         184 my $to = $_ & 0xFF;
907 294         933 $hash_moves{"$from-$to"} = 1;
908 294   100     1447 my $a = ($type_moves{$to} ||= {});
909 294   100     1525 my $b = ($a->{$piece} ||= []);
910 294         764 push @$b, $from;
911 294         1739 { from => $from, to => $to, piece => $piece }
912             } @valid_moves);
913             }
914              
915             # _debug(Data::Dumper::Dumper($self));
916              
917 13   33     597 return $self->{status} = {
      33        
918             moves => \@all_moves,
919             pieces => \@pieces,
920             hash_moves => \%hash_moves,
921             type_moves => \%type_moves,
922             check => $self->{in_check},
923             mate => $self->{in_check} && !@all_moves,
924             stalemate => !$self->{in_check} && !@all_moves,
925             };
926             }
927              
928             =head2 is_attacked($index, $color, $try_move)
929              
930             Checks if the field specified by $index is under attack by a piece of
931             the specified $color.
932              
933             $try_move is optional; if passed it must be a hash of the following
934             form:
935              
936             { from => $from_index,
937             to => $to_index,
938             piece => $piece }
939              
940             In this case, the method will take the given move into account. This
941             is useful in order to test moves in compute_valid_moves(), as we need
942             to filter out moves that leave the king in check.
943              
944             =cut
945              
946             sub is_attacked {
947 350     350 1 588 my ($self, $i, $opponent_color, $try_move) = @_;
948              
949             # _debug("Checking if " . get_field_id($i) . " is attacked");
950              
951 350 100       946 $opponent_color = $self->{to_move} ^ 0x80
952             unless defined $opponent_color;
953              
954             my $test = sub {
955 13513     13513   20733 my ($type, $i) = @_;
956 13513 100       41857 return 1
957             if $i & 0x88;
958 8015         8664 my $p;
959 8015         33454 my $pos = $self->{pos};
960 8015 100       16732 if ($try_move) {
961 6564         15342 my ($from, $to, $piece) = ($try_move->{from}, $try_move->{to}, $try_move->{piece});
962 6564 100 33     44718 if ($i == $from) {
    100 33        
    50 0        
963 155         240 $p = 0;
964             } elsif ($i == $to) {
965 106         191 $p = $piece;
966             } elsif ($self->{enpa} # en-passant field defined
967             && ($piece & 0x01) # pawn
968             && $to == $self->{enpa} # trying en-passant move
969             && ($i == (($from & 0x70) | ($to & 0x07))) # captured piece field inquired
970             ) {
971             # emulate en-passant (clear captured piece field)
972 0         0 $p = 0;
973             } else {
974 6303         13768 $p = $pos->[$i];
975             }
976             } else {
977 1451         2111 $p = $pos->[$i];
978             }
979 8015 100 100     27525 if ($p && ($p & $type) && ($p & 0x80) == $opponent_color) {
      100        
980 5         73 die 1;
981             }
982 8010         23743 return $p;
983 350         1906 };
984              
985 350         3213 eval {
986              
987             # check pawns
988             # _debug("... checking opponent pawns");
989 350 100       657 if ($opponent_color) {
990 239         815 $test->(0x01, $i - 15);
991 239         534 $test->(0x01, $i - 17);
992             } else {
993 111         294 $test->(0x01, $i + 15);
994 111         242 $test->(0x01, $i + 17);
995             }
996              
997             # check knights
998             # _debug("... checking opponent knights");
999 350         621 for my $step (@MOVES_N) {
1000 2800         15249 $test->(0x02, $i + $step);
1001             }
1002              
1003             # check bishops or queens
1004             # _debug("... checking opponent bishops");
1005 350         834 for my $step (@MOVES_B) {
1006 1392         2102 my $j = $i;
1007 1392         1782 do { $j += $step }
  2831         7653  
1008             while (!$test->(0x28, $j));
1009             }
1010              
1011             # check rooks or queens
1012             # _debug("... checking opponent rooks or queens");
1013 345         804 for my $step (@MOVES_R) {
1014 1380         1855 my $j = $i;
1015 1380         1398 do { $j += $step }
  4422         10470  
1016             while (!$test->(0x30, $j));
1017             }
1018              
1019             # _debug("... checking opponent king");
1020 345         676 for my $step (@MOVES_K) {
1021 2760         6102 $test->(0x04, $i + $step);
1022             }
1023              
1024             };
1025              
1026 350 100       4122 return $@ ? 1 : 0;
1027             }
1028              
1029             sub _get_allowed_moves {
1030 56     56   111 my ($self, $index) = @_;
1031 56         176 my $p = uc ID_TO_PIECE->[$self->get_piece_at_index($index) & 0x3F];
1032 56         169 my $method = "_get_allowed_${p}_moves";
1033 56         274 return $self->$method($index);
1034             }
1035              
1036             sub _add_if_valid {
1037 547     547   882 my ($self, $moves, $from, $to) = @_;
1038              
1039             return undef
1040 547 100       1884 if $to & 0x88;
1041              
1042 385         846 my $what = $self->get_piece_at_index($to);
1043              
1044 385         1016 my $p = $self->get_piece_at_index($from);
1045 385         573 my $color = $p & 0x80;
1046              
1047 385 100 100     999 if (($p & 0x04) && $self->is_attacked($to)) {
1048 5         22 return undef;
1049             }
1050              
1051 380 100       1202 if (!$what) {
1052 316 100       768 if ($p & 0x01) {
1053 62 100       232 if (abs(($from & 0x07) - ($to & 0x07)) == 1) {
1054 29 50 33     78 if ($self->{enpa} && $to == $self->{enpa}) { # check en passant
1055 0         0 push @$moves, $to;
1056 0         0 return $to;
1057             }
1058 29         100 return undef; # must take to move this way
1059             }
1060             }
1061 287         594 push @$moves, $to;
1062 287         1036 return $to;
1063             }
1064              
1065 64 100       159 if (($what & 0x80) != $color) {
1066 7 50 66     37 if (($p & 0x01) && (($from & 0x07) == ($to & 0x07))) {
1067 0         0 return undef; # pawns can't take this way
1068             }
1069             # _debug("Adding capture: $p " . get_field_id($from) . "-" . get_field_id($to));
1070 7         16 push @$moves, $to;
1071 7         25 return $to;
1072             }
1073              
1074 57         225 return undef;
1075             }
1076              
1077             sub _get_allowed_P_moves {
1078 20     20   38 my ($self, $index, $moves) = @_;
1079 20   50     79 $moves ||= [];
1080 20         53 my $color = $self->get_piece_at_index($index) & 0x80;
1081 20 100       82 my $step = $color ? 16 : -16;
1082 20 100       47 my $not_moved = ($index & 0xF0) == ($color ? 0x10 : 0x60);
1083 20 100 100     57 if (defined $self->_add_if_valid($moves, $index, $index + $step) && $not_moved) {
1084 14         42 $self->_add_if_valid($moves, $index, $index + 2 * $step);
1085             }
1086 20 100       82 $self->_add_if_valid($moves, $index, $index + ($color ? 17 : -15));
1087 20 100       70 $self->_add_if_valid($moves, $index, $index + ($color ? 15 : -17));
1088             # print Data::Dumper::Dumper($moves);
1089 20         61 return $moves;
1090             }
1091              
1092             sub _get_allowed_N_moves {
1093 3     3   7 my ($self, $index, $moves) = @_;
1094 3   50     14 $moves ||= [];
1095 3         7 for my $step (@MOVES_N) {
1096 24         56 $self->_add_if_valid($moves, $index, $index + $step);
1097             }
1098 3         9 return $moves;
1099             }
1100              
1101             sub _get_allowed_R_moves {
1102 18     18   36 my ($self, $index, $moves) = @_;
1103 18   100     58 $moves ||= [];
1104 18         43 for my $step (@MOVES_R) {
1105 72         101 my $i = $index;
1106 72         228 while (defined $self->_add_if_valid($moves, $index, $i += $step)) {
1107 124 100       277 last if $self->get_piece_at_index($i);
1108             }
1109             }
1110 18         56 return $moves;
1111             }
1112              
1113             sub _get_allowed_B_moves {
1114 14     14   31 my ($self, $index, $moves) = @_;
1115 14   100     50 $moves ||= [];
1116 14         28 for my $step (@MOVES_B) {
1117 56         88 my $i = $index;
1118 56         131 while (defined $self->_add_if_valid($moves, $index, $i += $step)) {
1119 97 100       228 last if $self->get_piece_at_index($i);
1120             }
1121             }
1122 14         35 return $moves;
1123             }
1124              
1125             sub _get_allowed_Q_moves {
1126 12     12   28 my ($self, $index, $moves) = @_;
1127 12   50     58 $moves ||= [];
1128 12         54 $self->_get_allowed_R_moves($index, $moves);
1129 12         46 $self->_get_allowed_B_moves($index, $moves);
1130 12         37 return $moves;
1131             }
1132              
1133             sub _get_allowed_K_moves {
1134 13     13   42 my ($self, $index, $moves) = @_;
1135 13   50     76 $moves ||= [];
1136 13         35 my $color = $self->get_piece_at_index($index) & 0x80;
1137              
1138 13         30 for my $step (@MOVES_K) {
1139 104 100       338 if (defined $self->_add_if_valid($moves, $index, $index + $step)) {
1140 28 50 66     440 if ($step == 1 &&
    50 66        
      33        
      33        
      33        
      33        
      0        
      0        
      0        
1141             !$self->{in_check} && $self->can_castle($color, 0) &&
1142             !$self->get_piece_at_index($index + 1) &&
1143             !$self->get_piece_at_index($index + 2)) {
1144             # kingside castling possible
1145 0         0 $self->_add_if_valid($moves, $index, $index + 2);
1146             } elsif ($step == -1 &&
1147             !$self->{in_check} && $self->can_castle($color, 1) &&
1148             !$self->get_piece_at_index($index - 1) &&
1149             !$self->get_piece_at_index($index - 2) &&
1150             !$self->get_piece_at_index($index - 3)) {
1151             # queenside castling possible
1152 0         0 $self->_add_if_valid($moves, $index, $index - 2);
1153             }
1154             }
1155             }
1156              
1157 13         54 return $moves;
1158             }
1159              
1160             =head2 can_castle($color, $ooo)
1161              
1162             Return true if the given $color can castle kingside (if $ooo is false)
1163             or queenside (if you pass $ooo true).
1164              
1165             =cut
1166              
1167             sub can_castle {
1168 11     11 1 30 my ($self, $color, $ooo) = @_;
1169 11 100       26 if ($color) {
1170 6 50       70 return $self->{castle} & ($ooo ? CASTLE_W_OOO : CASTLE_W_OO);
1171             } else {
1172 5 50       74 return $self->{castle} & ($ooo ? CASTLE_B_OOO : CASTLE_B_OO);
1173             }
1174             }
1175              
1176             =head2 has_castled($color)
1177              
1178             Returns true (non-zero) if the specified color has castled, or false
1179             (zero) otherwise. If the answer to this question is unknown (which
1180             can happen if we initialize the Chess::Rep object from an arbitrary
1181             position) then it returns undef.
1182              
1183             =cut
1184              
1185             sub has_castled {
1186 0     0 1 0 my ($self, $color) = @_;
1187 0 0       0 if (defined $self->{has_castled}) {
1188 0 0       0 if ($color) {
1189 0         0 return $self->{has_castled} & (CASTLE_W_OO | CASTLE_W_OOO);
1190             } else {
1191 0         0 return $self->{has_castled} & (CASTLE_B_OO | CASTLE_B_OOO);
1192             }
1193             }
1194 0         0 return undef;
1195             }
1196              
1197             =head2 piece_color($piece)
1198              
1199             You can call this both as an object method, or standalone. It returns
1200             the color of the specified $piece, which must be in the established
1201             encoding. Example:
1202              
1203             Chess::Rep::piece_color(0x81) --> 0x80 (white (pawn))
1204             Chess::Rep::piece_color(0x04) --> 0 (black (king))
1205             $self->piece_color('e2') --> 0x80 (white (standard start position))
1206              
1207             If you call it as a method, the argument B be a field specifier
1208             (either full index or field ID) rather than a piece.
1209              
1210             =cut
1211              
1212             sub piece_color {
1213 0     0 1 0 my $p = shift;
1214 0 0       0 $p = $p->get_piece_at(shift)
1215             if ref $p;
1216 0         0 return $p & 0x80;
1217             }
1218              
1219             =head2 get_index($row, $col)
1220              
1221             Static function. Computes the full index for the given $row and $col
1222             (which must be in 0..7).
1223              
1224             Additionally, you can pass a field ID instead (and omit $col).
1225              
1226             Examples:
1227              
1228             Chess::Rep::get_index(2, 4) --> 45
1229             Chess::Rep::get_index('e3') --> 45
1230              
1231             =cut
1232              
1233             sub get_index {
1234 12     12 1 21 my ($row, $col) = @_;
1235 12 50       48 ($row, $col) = get_row_col($row)
1236             unless defined $col;
1237 12         31 return ($row << 4) | $col;
1238             }
1239              
1240             =head2 get_index_from_row_col($row, $col)
1241              
1242             This does the same as the above function, but it won't support a field
1243             ID (i.e. 'e3'). You have to pass it a row and col (which are 0..7)
1244             and it simply returns ($row << 4) | $col. It's faster than the above
1245             when you don't really need support for field IDs.
1246              
1247             =cut
1248              
1249             sub get_index_from_row_col {
1250 906     906 1 1247 my ($row, $col) = @_;
1251 906         1720 return ($row << 4) | $col;
1252             }
1253              
1254             =head2 get_field_id($index)
1255              
1256             Returns the ID of the field specified by the given index.
1257              
1258             Chess::Rep::get_field_id(45) --> 'e3'
1259             Chess::Rep::get_field_id('f4') --> 'f4' (quite pointless)
1260              
1261             =cut
1262              
1263             sub get_field_id {
1264 0     0 1 0 my ($row, $col) = @_;
1265 0 0       0 ($row, $col) = get_row_col($row)
1266             unless defined $col;
1267 0         0 return pack('CC', $col + 65, $row + 49);
1268             }
1269              
1270             =head2 get_row_col($where)
1271              
1272             Returns a list of two values -- the $row and $col of the specified
1273             field. They are in 0..7.
1274              
1275             Chess::Rep::get_row_col('e3') --> (2, 4)
1276             Chess::Rep::get_row_col(45) --> (2, 4)
1277              
1278             =cut
1279              
1280             sub get_row_col {
1281 24     24 1 32 my ($id) = @_;
1282 24 100       73 if ($id =~ /^[a-h]/oi) {
1283 12         57 my ($col, $row) = unpack('CC', uc $id);
1284             return (
1285 12         39 $row - 49,
1286             $col - 65,
1287             );
1288             } else {
1289             return (
1290 12         33 ($id & 0x70) >> 4,
1291             $id & 0x07,
1292             );
1293             }
1294             }
1295              
1296             =head2 dump_pos()
1297              
1298             Object method. Returns a string with the current position (in a form
1299             more readable than standard FEN). It's only useful for debugging.
1300              
1301             =cut
1302              
1303             sub dump_pos {
1304 0     0 1   my ($self) = @_;
1305 0           my $fen = $self->get_fen;
1306 0           my @a = split(/ /, $fen);
1307 0           $fen = shift @a;
1308 0           $fen =~ s/([1-8])/' 'x$1/ge;
  0            
1309 0           $fen =~ s{([^/])}{|$1}g;
1310 0           $fen =~ s/\//|\n|-+-+-+-+-+-+-+-|\n/g;
1311 0           $fen .= '|';
1312 0           return $fen;
1313             }
1314              
1315             sub _debug {
1316 0     0     print STDERR join(' / ', @_), "\n";
1317             }
1318              
1319             =head1 LINKS
1320              
1321             [1] SAN ("Standard Algebraic Notation") is the most popular notation
1322             for chess moves.
1323              
1324             http://en.wikipedia.org/wiki/Algebraic_chess_notation
1325              
1326             [2] Ideas for representing a chess board in memory.
1327              
1328             http://www.cis.uab.edu/hyatt/boardrep.html
1329              
1330             =head1 AUTHOR
1331              
1332             Mihai Bazon,
1333             http://www.dynarchlib.com/
1334             http://www.bazon.net/mishoo/
1335              
1336             This module was developed for Dynarch Chess --
1337             L
1338              
1339             =head1 COPYRIGHT
1340              
1341             Copyright (c) Mihai Bazon 2008. All rights reserved.
1342              
1343             This module is free software; you can redistribute it and/or modify it
1344             under the same terms as Perl itself.
1345              
1346             =head1 DISCLAIMER OF WARRANTY
1347              
1348             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
1349             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
1350             WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
1351             PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND,
1352             EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
1353             IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1354             PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
1355             SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME
1356             THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
1357              
1358             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
1359             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
1360             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE
1361             TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR
1362             CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
1363             SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
1364             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
1365             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
1366             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
1367             DAMAGES.
1368              
1369             =cut
1370              
1371             1;