view release on metacpan or search on metacpan
lib/Chess/Plisco/EPD/Record.pm
lib/Chess/Plisco/Engine.pm
lib/Chess/Plisco/Engine.pod
lib/Chess/Plisco/Engine/InputWatcher.pm
lib/Chess/Plisco/Engine/Position.pm
lib/Chess/Plisco/Engine/TimeControl.pm
lib/Chess/Plisco/Engine/TimeControl.pod
lib/Chess/Plisco/Engine/TranspositionTable.pm
lib/Chess/Plisco/Engine/Tree.pm
lib/Chess/Plisco/Engine/Tree.pod
lib/Chess/Plisco/Macro.pm
lib/Chess/Plisco/Macro.pod
lib/Chess/Plisco/Macro/abs.pm
lib/Chess/Plisco/Macro/attacked.pm
lib/Chess/Plisco/Macro/clearButMostSet.pm
lib/Chess/Plisco/Macro/countIsolatedTrailingZbits.pm
lib/Chess/Plisco/Macro/countTrailingZbits.pm
lib/Chess/Plisco/Macro/infoUpdate.pm
lib/Chess/Plisco/Macro/moveAttacked.pm
lib/Chess/Plisco/Macro/movePinned.pm
lib/Chess/Plisco/Macro/movesFromMask.pm
lib/Chess/Plisco/Macro/promotionMovesFromMask.pm
lib/Chess/Plisco/Tutorial.pod
perlcritic.rc
t/00base.t
t/01expand-placeholders.t
t/01pre-process.t
t/02bit-twiddling.t
t/02piece-at.t
t/02square-conversion.t
t/03attacked.t
t/03epd.t
## Library
See the [tutorial](lib/Chess/Plisco/Tutorial.pod) for a gentle introduction
to the library. When installed, you can also try the command
`perldoc Chess::Plisco::Tutorial`.
Reference documentation is available for
[Chess::Plisco](lib/Chess/Plisco.pod) (`perldoc Chess::Plisco`)
and
[Chess::Pllisco::Macro](lib/Chess/Plisco/Macro.pod)
(`perldoc Chess::Plisco::Macro`).
## Engine
### Running the Engine
The chess engine is started with the command "plisco". You can also run it
from inside the repository like this:
```shell
$ perl -Ilib bin/plisco
$ make install
=head2 Library
See the L<lib/Chess/Plisco/Tutorial.pod> for a gentle
introduction to the library. When installed, you can also try the
command C<perldoc Chess::Plisco::Tutorial>.
Reference documentation is available for
L<lib/Chess/Plisco.pod> (C<perldoc Chess::Plisco>) and
L<lib/Chess/Plisco/Macro.pod>
(C<perldoc Chess::Plisco::Macro>).
=head2 Engine
=head3 Running the Engine
The chess engine is started with the command "plisco". You can also run
it from inside the repository like this:
$ perl -Ilib bin/plisco
lib/Chess/Plisco.pm view on Meta::CPAN
# misrepresented as being the original code.
#
# 3. This notice may not be removed or altered from any source distribution.
# Make Dist::Zilla happy.
# ABSTRACT: Representation of a chess position with move generator, legality checker etc.
# Welcome to the world of spaghetti code! It is deliberately ugly because
# trying to avoid function/method call overhead is one of the major goals.
# In the future it may make sense to try to make the code more readable by
# more extensive use of Chess::Plisco::Macro.
package Chess::Plisco;
$Chess::Plisco::VERSION = '0.4';
use strict;
use integer;
no warnings qw(portable);
use overload '""' => sub { shift->toFEN };
use Locale::TextDomain qw('Chess-Plisco');
use Scalar::Util qw(reftype);
use Config;
# Macros from Chess::Plisco::Macro are already expanded here!
use base qw(Exporter);
# Colors.
use constant CP_WHITE => 0;
use constant CP_BLACK => 1;
# Piece constants.
use constant CP_NO_PIECE => 0;
use constant CP_PAWN => 1;
lib/Chess/Plisco.pod view on Meta::CPAN
=item Static Exchange Evaluation (SEE)
=item Zobrist Keys
=back
For a gentler introduction, please see L<Chess::Plisco::Tutorial>. The rest
of this document contains reference documentation only.
If performance is key for you, you are strongly advised to have a look at
L<Chess::Plisco::Macro> which documents macros resp. inline functions that
speed up tasks that can be done with L<Chess::Plisco> significantly.
The class exports a number of constants that can either be imported
individually, by export tag, or all at once by the export tag ':all'. All
constants are prefixed with 'CP_' and you will have little reason to not
import all constants.
=head2 Internals
An instance of a B<Chess::Plisco> is a blessed array reference. You can
lib/Chess/Plisco.pod view on Meta::CPAN
signatures.
If you want a different seed, you should override the constant
L</CP_RANDOM_SEED>.
=back
=head1 PROPERTIES
You can access individual properties either by using index constants or by
using accessor macros from L<Chess::Plisco::Macro>. All accessor macros
can be assigned to; they are L-values. But you are strongly advised
to modify properties of a B<Chess::Plisco> instance only with the methods
documented here.
For getting or setting the bitboard of all white pieces, you have
these options:
$whites_pieces = $pos->[CP_W_PIECES];
$white_pieces = cp_w_pieces $pos;
$white_pieces = cp_w_pieces($pos);
$pos->[CP_W_PIECES] = $white_pieces;
cp_w_pieces $pos = $white_pieces;
cp_w_pieces($pos) = $white_pieces;
The macros (all starting with "cp_") are only available when you have loaded
L<Chess::Plisco::Macro>, see there for more information.
All elements of the position array are documented below under
L</Accessor Indexes (:accessors)>.
=head1 EXPORT TAGS
The module exports only constants, all prefixed with "CP_".
Note that (lowercase) macros "cp_" are defined by using
L<Chess::Plisco::Macro>.
=head2 All Constants (:all)
You can import all constants with the export tag ":all".
=head2 Accessor Indexes (:accessors)
The array indices were carefully so that the following conditions are met:
=over 4
lib/Chess/Plisco.pod view on Meta::CPAN
=head3 CP_A1 .. CP_H8
Shifts for all squares of the chess board.
=head2 Magic Moves Resp. Magic Bitboard Constants (:magicmoves)
These are all large data tables that are used internally for the magic
bitboards that generate the attack masks for the sliding pieces (queens,
bishops, and rooks). See the source if you are curious. Otherwise just import
them if you want to use the macros C<cp_mm_bmagic()> and C<cp_mm_rmagic()>
from L<Chess::Plisco::Macro>.
=head3 CP_MAGICMOVES_B_MAGICS
Internal.
=head3 CP_MAGICMOVES_R_MAGICS
Internal.
=head3 CP_MAGICMOVES_B_MASK
lib/Chess/Plisco.pod view on Meta::CPAN
A pretty arbitrary value used to initialize the pseudo-random number
generator L</RNG>.
=head1 COPYRIGHT
Copyright (C) 2021 Guido Flohr <guido.flohr@cantanea.com>.
=head1 SEE ALSO
L<Chess::Plisco::Macro>, perl(1)
lib/Chess/Plisco/Engine/Position.pm view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
package Chess::Plisco::Engine::Position;
$Chess::Plisco::Engine::Position::VERSION = '0.4';
use strict;
use integer;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
use Chess::Plisco::Engine::Tree;
use base qw(Chess::Plisco);
use constant CP_POS_GAME_PHASE => 14;
use constant CP_POS_OPENING_SCORE => 15;
use constant CP_POS_ENDGAME_SCORE => 16;
use constant PAWN_PHASE => 0;
use constant KNIGHT_PHASE => 1;
lib/Chess/Plisco/Engine/Tree.pm view on Meta::CPAN
# http://www.wtfpl.net/ for more details.
package Chess::Plisco::Engine::Tree;
$Chess::Plisco::Engine::Tree::VERSION = '0.4';
use strict;
use integer;
use Locale::TextDomain qw('Chess-Plisco');
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
use Chess::Plisco::Engine::Position;
use Time::HiRes qw(tv_interval);
use constant DEBUG => $ENV{DEBUG_PLISCO_TREE};
use constant MATE => -15000;
use constant INF => 16383;
use constant MAX_PLY => 512;
use constant DRAW => 0;
lib/Chess/Plisco/Macro.pm view on Meta::CPAN
# Copyright (C) 2021 Guido Flohr <guido.flohr@cantanea.com>,
# all rights reserved.
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
package Chess::Plisco::Macro;
$Chess::Plisco::Macro::VERSION = '0.4';
use strict;
use Filter::Util::Call;
use PPI::Document;
sub _define;
sub _define_from_file;
sub preprocess;
sub _extract_arguments;
sub _split_arguments;
lib/Chess/Plisco/Macro.pod view on Meta::CPAN
=head1 NAME
Chess::Plisco::Macro - Macros/inline functions for Chess::Plisco
=head1 SYNOPSIS
use integer;
use Chess::Plisco qw(:all);
use Chess::Plisco::Macro;
my $white_pieces = cp_pos_white_pieces(Chess::Plisco->new);
my $bitboard = '0x8080808080808080';
my $popcount;
cp_bitboard_popcount $bitboard, $popcount;
cp_bitboard_popcount($bitboard, $popcount); # You can also use parentheses ...
print "There are $popcount bits set in $bitboard.\n";
=head1 DESCRIPTION
The module L<Chess::Plisco::Macro> is a source filter. It makes a number
of macros respectively inline functions available that can be invoked without
any subroutine call overhead. In fact, all invocations of these macros are
translated into constant expressions at compile-time.
All the functionality available in the module is also available as instance
or class methods of L<Chess::Plisco>. You should only use the macros
defined here if you have to squeeze out the last bit of performance from
your code, for example, when writing a chess engine. Otherwise, using the
macros has only disadvantages:
lib/Chess/Plisco/Macro.pod view on Meta::CPAN
If the parentheses were omitted in the macro definition, strange precedence
problems in the expanded code would occur instead. In other words, it is
not possible to fix both problems at once. In doubt, macros are wrapped
into parentheses and it is therefore usually safer to also use parentheses,
when you want to use macros as arguments to subroutines. The correct test
code would look like this:
is(cp_pos_material($pos), 0, "material test");
=head2 Do not Create References to Macros
The macro calls will be replaced at compile-time with other code. Therefore,
it is not possible to create a reference to a macro. Doing so may or may not
cause a compile-time error but it will never do what you wanted.
=head2 Do not Use the String Form of C<eval>
You should not do that anyway but with macros it would not even work because
the source code filter cannot know whether a string constant is really code.
The same applies to using the L<Benchmark> module. If you want to benchmark
the macros, you either have to translate them first with C<preprocess()>
before (see below), or somehow wrap it into a function call. Doing the latter
will probably eat up the performance gain the macros give you.
=head2 Expect Errors
Macros are expanded with the use of L<PPI::Document> and so the technique
shares all limitations of L<PPI::Document>.
And some more esoteric usages will probaly also not work.
=head1 FUNCTIONS
=over 4
=item B<preprocess>
You should only use one single function of this module, the function
C<preprocess()> that does the actual translation of your code. Example:
require Chess::Plisco::Macro;
open my $fh, '<', 'YourModule.pm' or die;
print Chess::Plisco::Macro::preprocess(join '', <$fh>);
This will dump the translated source code of F<YourModule.pm> on standard
output.
=back
=head1 MACROS
Note that the source filter is theoretically able to inline constants (that
are macros without arguments) as well but this feature is not used because
it does not have any advantage over the regular L<constant> pragma of Perl.
=head2 Macros for L<Chess::Plisco> Instances
=over 4
=item B<cp_pos_white_pieces(POS)>
Same as L<Chess::Plisco/whitePieces>.
=item B<cp_pos_black_pieces(POS)>
Same as L<Chess::Plisco/blackPieces>.
lib/Chess/Plisco/Macro.pod view on Meta::CPAN
=item B<cp_pos_signature(POS)>
Same as L<Chess::Plisco/signature>.
=item B<cp_pos_material(POS)>
Same as L<Chess::Plisco/material>.
=item B<cp_pos_info(POS)>
Same as L<Chess::Plisco/info>. See also L</Position Info Macros> below!
=back
=head2 Position Info Macros
All these work directly on a position info as returned by L</cp_pos_info>.
=over 4
=item B<cp_pos_info_castling_rights(INFO)>
Same as L</cp_pos_castling_rights> but work directly on position
info B<INFO> as returned by L</cp_pos_info>.
lib/Chess/Plisco/Macro.pod view on Meta::CPAN
Same as L</cp_pos_evasion> but work directly on position
info B<INFO> as returned by L</cp_pos_info>.
=item B<cp_pos_info_material(INFO)>
Same as L</cp_pos_material> but work directly on position
info B<INFO> as returned by L</cp_pos_info>.
=back
=head2 Move Macros
These macros operate on scalar moves for L<Chess::Plisco> which are just
plain integers. They do I<not> work for instances of a
L<Chess::Plisco::Move>!
=over 4
=item B<cp_move_to(MOVE)>
Same as L<Chess::Plisco/moveTo>.
lib/Chess/Plisco/Macro.pod view on Meta::CPAN
=item B<cp_move_significant(MOVE)>
Same as L<Chess::Plisco/moveSignificant>.
=item B<cp_move_coordinate_notation(MOVE)>
Same as L<Chess::Plisco/moveCoordinateNotation>.
=back
=head2 Macros for Magic Moves Resp. Magic Bitboards
=over 4
=item B<cp_mm_bmagic(SHIFT, OCCUPANCY)>
Same as L<Chess::Plisco/bMagic>.
=item B<cp_mm_rmagic(SHIFT, OCCUPANCY)>
Same as L<Chess::Plisco/rMagic>.
=back
=head2 Bitboard Macros
=over 4
=item B<cp_bitboard_popcount(BITBOARD, COUNT)>
Count the number of bits set in B<BITBOARD> and store it in B<COUNT>.
Example:
cp_bitboard_popcount $bitboard, $count;
lib/Chess/Plisco/Macro.pod view on Meta::CPAN
=item B<cp_bitboard_count_isolated_trailing_zbits(BITBOARD)>
Same as L<Chess::Plisco/bitboardCountIsolatedTrailingZbits>.
=item B<cp_bitboard_more_than_one_set(BITBOARD)>
Same as L<Chess::Plisco/bitboardMoreThanOneSet>.
=back
=head2 Miscellaneous Macros
=over 4
=item B<cp_coordinates_to_shift(FILE, RANK)>
Calculate a bit shift offset (0-63) for the square that B<FILE> (0-7) and
B<RANK> (0-7) point to.
=item B<cp_shift_to_coordinates(SHIFT)>
lib/Chess/Plisco/Tutorial.pod view on Meta::CPAN
=head3 C<Chess::Plisco> Instances
Unlike most Perl objects, instances of C<Chess::Plisco> are blessed
array references. This design decision was taken because accessing
accessing array elements is faster than accessing hash elements. But
there is no need to remember the exact ordering of the array. You can
either use dedicated macros that operate directly on
C<Chess::Plisco> instances or use constants for the indexes:
use Chess::Plisco (:all);
use Chess::Plisco::Macro;
$pos = Chess::Plisco->new;
# Equivalent!
$w_pieces = $pos->[CP_POS_WHITE_PIECES];
$pos->[CP_POS_WHITE_PIECES] = $_pieces;
$w_pieces = cp_pos_white_pieces $pos;
cp_pos_white_pieces $pos = $w_pieces;
=head3 Pieces
lib/Chess/Plisco/Tutorial.pod view on Meta::CPAN
The methods C<SAN> and C<moveCoordinateNotation> can be used to print a move in
humand-readable format:
$pos->SAN($move);
# Nxe7#
$pos->moveCoordinateNotation($move);
# d6e7
In general, you will prefer printing moves in Standard Algebraic Notation.
=head2 Using Macros
When dealing with chess programming you often find yourself executing
small operations many times, more than often millions of times. You can,
of course, write subroutines for these operations but the calling
overhead sums up and contributes significantly to the execution time of
your code.
Even writing these routines in C does not help at all because the
calling overhead is large compared to the execution time of the function
body.
This is why the module C<Chess::Plisco::Macro> exists. It makes a lot
of small helper functions available, the names of which all begin with
C<cp_>. You can use them more or less like functions but they are inlined
into your code at compile-time.
But this is only necessary, when performance is important. For normal
purposes, you can just use regular instance methods instead of macros.
But when you want to use the macros, there are a couple of caveats that you
have to keep in mind:
=head3 Use C<Chess::Plisco::Macro> and(!) C<Chess::Plisco>
The macros in C<Chess::Plisco::Macro> make use of constants defined in
C<Chess::Plisco>. If you do not import these constants, you will get
strange errors. You should therefore start your own code with this
boilerplate:
use strict;
use integer;
use Chess::Plisco qw(:all);
use Chess::Plisco::Macro;
=head3 Use C<integer>
Some of the macros will only work on integers. You must therefore always
C<use integer> in the scope of your code. Not doing so will result in
errors!
If you need floating point arithmetics, activate them only in the limited
scope of a block:
lib/Chess/Plisco/Tutorial.pod view on Meta::CPAN
no integer;
printf "avg. loss in centipedes: %g\n", $score / 100;
}
=head3 Do Not Use Here Documents
The translation currently chokes on here documents (E<lt>E<lt>EOF ...). So
sorry, I have to check out once again how to make L<PPI::Document> round-trip
safe.
=head3 Do not Create References to Macros
Macros are not Perl subroutines. They are more or less stupidly replaced
with chunks of code. Things like C<my $sub = \&cp_pos_white_pieces> may or
may not cause a syntax error but they will never do what you expect.
=head3 Be Prepared for Errors
The macro expansion internally makes use of C<PPI::Document> and it
therefore shares all of that module's inevitable limitations. And it
adds a fair amount of its own shortcomings. The macro approach is rather
an experiment than a production-ready general-purpose tool.
lib/Chess/Plisco/Tutorial.pod view on Meta::CPAN
my $pos = Chess::Plisco->new;
my $white_pawns = $pos->[CP_POS_WHITE_PIECES] & $self->[CP_POS_PAWNS];
my $count = $pos->bitboardPopcount($white_pawns);
print "There are $count white pawns on the board.\n";
Using macros looks a little bit strange at first glance but that strangeness
is unavoidable:
use Chess::Plisco;
use Chess::Plisco::Macro;
my $pos = Chess::Plisco->new;
my $white_pawns = cp_pos_white_pieces($pos) & cp_pos_pawns($pos);
my $count;
cp_bitboard_popcount $white_pawns, $count;
print "There are $count white pawns on the board.\n";
The important line is the last but one. The macro C<cp_bitboard_popcount>
counts the number of bits set in an integer, and this is exactly what
you need here. But you have to give the variable that should hold the
lib/Chess/Plisco/Tutorial.pod view on Meta::CPAN
=head3 Iterating Bitboards
Task: Print the square for every white pawn on the board.
=head4 Conventional and Slow Approach
Iterating over a bitboard can be done in an intuitive and straight-forward way:
use integer;
use Chess::Plisco qw(:all);
use Chess::Plisco::Macro;
my $white_pawn_mask = cp_pos_white_pieces($pos) & cp_pos_pawns($pos);
foreach my $shift (0 .. 63) {
my $shift_mask = 1 << $shift;
if ($shift_mask & $white_pawn_mask) {
my $square = cp_shift_to_square $shift;
print "There is a white pawn on $square.\n";
}
lib/Chess/Plisco/Tutorial.pod view on Meta::CPAN
corresponding bit is set in the bitboard. There is nothing wrong with this
approach and it is actually reasonably fast.
=head4 Efficient and Fast Approach
But there is a another technique that achieves the same result and is often
faster:
use integer;
use Chess::Plisco qw(:all);
use Chess::Plisco::Macro;
my $pos = Chess::Plisco->new;
my $white_pawn_mask = cp_pos_white_pieces($pos) & cp_pos_pawns($pos);
while ($white_pawn_mask) {
my $shift = cp_bitboard_count_trailing_zbits $shift_mask;
my $square = cp_shift_to_square $shift;
print "There is a white pawn on $square.\n";
lib/Chess/Plisco/Tutorial.pod view on Meta::CPAN
In array context, you get the piece and the color, in scalar context just the
piece. The piece is one of C<CP_NO_PIECE>, C<CP_PAWN>, C<CP_KNIGHT>, C<CP_BISHOP>,
C<CP_QUEEN>, or C<CP_KING>, and the color one of C<CP_WHITE>, C<CP_BLACK>,
or C<undef> if there is no piece at all at the specified location.
=head3 Castling State
The castling state is encoded with other state information in one single
integer as a bit mask. It is highly recommended that you use the dedicated
methods from L<Chess::Plisco> or the macros from L<Chess::Plisco::Macro> for it:
$white_can_castle_king_side = cp_pos_white_king_side_castling_right $pos;
# or $white_can_castle_king_side = $pos->whiteKingSideCastlingRight;
$white_can_castle_queen_side = cp_pos_white_queen_side_castling_right $pos;
# or $white_can_castle_queen_side = $pos->whiteQueenSideCastlingRight;
$black_can_castle_king_side = cp_pos_black_king_side_castling_right $pos;
# or $black_can_castle_king_side = $pos->blackKingSideCastlingRight;
$black_can_castle_queen_side = cp_pos_black_queen_side_castling_right $pos;
# or $black_can_castle_queen_side = $pos->blackKingSideCastlingRight;
perlcritic.rc view on Meta::CPAN
; Copyright (C) 2021 Guido Flohr <guido.flohr@cantanea.com>,
; all rights reserved.
; This program is free software. It comes without any warranty, to
; the extent permitted by applicable law. You can redistribute it
; and/or modify it under the terms of the Do What the Fuck You Want
; to Public License, Version 2, as published by Sam Hocevar. See
; http://www.wtfpl.net/ for more details.
; How can that be disabled just for lib/Chess/Position/Macro/*.pm?
[-TestingAndDebugging::RequireUseStrict]
t/01expand-placeholders.t view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use Test::More;
use PPI::Document;
# Do not "use" the module because we do not want to acti
require Chess::Plisco::Macro;
my %placeholders = (
'$m' => [PPI::Token::Symbol->new('$move')],
'$v' => [PPI::Token::Number->new(32)],
);
my $code = '(($m) = (($m) & ~0x3f) | (($v) & 0x3f))';
my $cdoc = PPI::Document->new(\$code);
Chess::Plisco::Macro::_expand_placeholders($cdoc, %placeholders);
is $cdoc->content, '(($move) = (($move) & ~0x3f) | ((32) & 0x3f))';
done_testing;
t/01pre-process.t view on Meta::CPAN
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use Test::More;
# Do not "use" the module because we do not want to acti
require Chess::Plisco::Macro;
my ($code);
$code = 'cp_move_to($move)';
is Chess::Plisco::Macro::preprocess($code), '(($move) & 0x3f)', $code;
$code = 'cp_move_to $move';
is Chess::Plisco::Macro::preprocess($code), '(($move) & 0x3f)', $code;
$code = 'cp_move_to($move); return;';
is Chess::Plisco::Macro::preprocess($code),
'(($move) & 0x3f); return;', $code;
$code = 'cp_move_to $move; return;';
is Chess::Plisco::Macro::preprocess($code),
'(($move) & 0x3f); return;', $code;
$code = 'cp_move_set_to($move, 32);';
is Chess::Plisco::Macro::preprocess($code),
'(($move) = (($move) & ~0x3f) | ((32) & 0x3f));', $code;
done_testing;
t/02bit-twiddling.t view on Meta::CPAN
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More tests => 35;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my ($bitboard, $count);
$bitboard = 0x88;
{ my $_b = $bitboard; for ($count = 0; $_b; ++$count) { $_b &= $_b - 1; } };
is $count, 2, 'popcount 0x88';
is $bitboard, 0x88, 'popcount 0x88';
$bitboard = 0xffff_ffff_ffff_ffff;
{ my $_b = $bitboard; for ($count = 0; $_b; ++$count) { $_b &= $_b - 1; } };
t/02piece-at.t view on Meta::CPAN
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More tests => 6 * 64;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
# The array elements are:
#
# - square
# - file (0 .. 7)
# - rank (0 .. 7)
# - shift (0 .. 63)
my @tests = (
# 1st rank.
['a1', 0, 0, 0, CP_ROOK, CP_WHITE],
t/02square-conversion.t view on Meta::CPAN
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More tests => 12 * 64;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
# The array elements are:
#
# - square
# - file (0 .. 7)
# - rank (0 .. 7)
# - shift (0 .. 63)
my @tests = (
# 1st rank.
['a1', 0, 0, 0],
t/02square-conversion.t view on Meta::CPAN
"squareToShift $square";
is $class->coordinatesToSquare($file, $rank), $square,
"coordinatesToSquare $square";
is $class->coordinatesToShift($file, $rank), $shift,
"coordinatesToShift $square";
is_deeply [$class->shiftToCoordinates($shift)], [$file, $rank],
"shiftToCoordinates $shift";
is_deeply [$class->squareToCoordinates($square)], [$file, $rank],
"squareToCoordinates $shift";
# Macros.
is(chr(97 + ($shift & 0x7)) . (1 + ($shift >> 3)), $square,
"cp_shift_to_square $square");
is((((substr $square, 1) - 1) << 3) + ord($square) - 97, $shift,
"cp_square_to_shift $square");
is(chr(97 + $file) . (1 + $rank), $square,
"cp_coordinates_to_square $square");
is((($rank << 3) + $file), $shift,
"cp_coordinates_to_shift $square");
is_deeply([($shift & 0x7, $shift >> 3)], [$file, $rank],
"cp_shift_to_coordinates $shift");
t/03attacked.t view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Data::Dumper;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my ($pos, @moves, @expect);
my @tests = (
{
name => 'attacked by white pawn',
square => 'd4',
fen => '7k/2n5/2p1R3/8/8/2P2Bq1/2K5/8 b - - 0 1',
attacked => 1,
},
t/03move-attacked.t view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Data::Dumper;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my ($pos, @moves, @expect);
my @tests = (
{
name => 'black king on f8 attacked by white queen on h8',
move => 'e8f8',
fen => 'r3k2Q/p1ppqp2/bn2p1pb/3PN3/1p2P3/2N4p/PPPBBPPP/R3K2R b KQq - 0 2',
attacked => 1,
},
t/03move-pinned.t view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Data::Dumper;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my ($pos, @moves, @expect);
my @tests = (
{
name => 'white rook pinned by rook on same file',
move => 'e4g4',
fen => '8/4r2k/8/8/4R3/8/4K3/8 w - - 0 1',
pinned => 1,
},
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More tests => 13;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my ($pos, $move, $from, $to);
$pos = Chess::Plisco->new;
$move = 0;
$from = (((substr 'e2', 1) - 1) << 3) + ord('e2') - 97;
$to = (((substr 'e4', 1) - 1) << 3) + ord('e4') - 97;
(($move) = (($move) & ~0xfc0) | (($from) & 0x3f) << 6);
(($move) = (($move) & ~0x3f) | (($to) & 0x3f));
t/03parse-san.t view on Meta::CPAN
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use Test::More;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my $fen;
my $pos = Chess::Plisco->new;
# Regular white piece move.
is $pos->moveCoordinateNotation($pos->parseMove("Nc3")), "b1c3", "Nc3";
is $pos->moveCoordinateNotation($pos->parseMove("b1c3")), "b1c3", "b1c3";
is $pos->moveCoordinateNotation($pos->parseMove("Nb1-c3")), "b1c3", "Nb1-c3";
t/04check-check.t view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Data::Dumper;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my ($pos, @moves, @expect);
my @tests = (
# Castlings.
{
name => 'white pawn checks on f5',
fen => '8/8/4k3/5P2/8/8/8/4K3 b - - 0 1',
checkers => [(1 << (CP_F_MASK & CP_5_MASK))],
},
t/04do-move.t view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Data::Dumper;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
use Time::HiRes qw(gettimeofday);
my ($pos, @moves, @expect);
my @tests = (
{
name => 'e4 after initial',
before => 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
move => 'e2e4',
after => 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1',
t/04insufficient-material.t view on Meta::CPAN
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my @tests = (
{
name => 'nothing',
fen => 'k7/8/8/8/8/8/8/7K w - - 10 20',
draw => 1,
},
{
name => 'white queen',
fen => 'k7/8/8/8/8/8/8/6QK w - - 10 20',
t/04king-shift.t view on Meta::CPAN
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use Test::More tests => 9;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my $pos = Chess::Plisco->new;
ok $pos, 'created';
is($pos->kingShift, CP_E1, 'initial white');
my $move = $pos->parseMove('e4');
ok $move, 'move e4';
ok $pos->doMove($move), 'doMove e4';
is($pos->kingShift, CP_E8, 'after 1. e4');
$pos = Chess::Plisco->new('8/8/4k3/5P2/8/8/8/K7 w - - 0 1');
t/04legal-moves.t view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Data::Dumper;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my ($pos, @moves, @expect);
my @tests = (
{
name => 'legal moves bug 1',
fen => '1B3b1R/2q4b/2nn1Kp1/3p2p1/r7/k6r/p1p1p1p1/2RN1B1N b - - 0 1',
moves => [qw(
a2a1q a2a1r a2a1b a2a1n c2d1q c2d1r
c2d1b c2d1n e2e1q e2e1r e2e1b e2e1n
t/04material.t view on Meta::CPAN
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my @tests = (
{
name => 'start position',
fen => 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
material => 0,
},
{
name => 'lisco vs. PANTELIS39 after 34. Kd3',
fen => '4r3/pp5p/2p1Nkpn/8/2B5/3K4/PP6/8 b - - 7 34',
t/04move-generator.t view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Data::Dumper;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
my ($pos, @moves, @expect);
my @tests = (
# Castlings.
{
name => 'white castlings',
fen => 'r3k2r/p6p/p6p/8/8/P6P/P6P/R3K2R w KQkq - 0 1',
moves => [qw(e1g1 e1c1 e1d1 e1d2 e1e2 e1f2 e1f1
a3a4 h3h4 a1b1 a1c1 a1d1 h1g1 h1f1)],
t/04move-gives-check.t view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Data::Dumper;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
use Time::HiRes qw(gettimeofday);
sub make_move;
my ($pos, @moves, @expect);
my @tests = (
{
name => 'white pawn gives check',
before => '8/8/4k3/2n5/3Pp3/5N2/5K2/8 w - - 0 1',
t/04move-legal.t view on Meta::CPAN
# and/or modify it under the terms of the Do What the Fuck You Want
# to Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
use strict;
use integer;
use Test::More;
use Data::Dumper;
use Chess::Plisco qw(:all);
# Macros from Chess::Plisco::Macro are already expanded here!
use Time::HiRes qw(gettimeofday);
sub make_move;
my ($pos, @moves, @expect);
my @tests = (
{
name => 'e4 after start position',
before => 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',