=head1 Chess-Plisco

Chess::Plisco is a representation of a chess position in Perl. It also
contains a UCI compatible chess engine. You can challenge the engine
most of the time at L<https://lichess.org/@/plisco-bot>.

It only works with Perl versions that are compiled with support for 64
bit integers!

Since it is reasonably fast and offers a lot of functionality needed for
chess engines, it can be used for rapid prototyping of a chess engine.
Writing a basic implementation of the AlphaBeta algorithm with
C<Chess::Plisco> will not require more than 30 lines of code.

The library also has a very high test coverage so that you can probably
use it as a reference implementation for your own experiments and tests.

=over

=item * L<#chess-plisco>
=over

=item * L<#installation>
=over

=item * L<#windows>

=item * L<#posix-systems-unx-linux-macos->
=over

=item * L<#installing-a-release>

=back

=item * L<#buildingusing-from-git-sources>
=over

=item * L<#installing-from-git-sources>

=item * L<#using-the-cloned-repository-directly>

=back

=back

=item * L<#library>

=item * L<#engine>
=over

=item * L<#running-the-engine>

=item * L<#graphical-user-interfaces>

=item * L<#syzygy-endgame-tablebases>

=item * L<#differences-to-other-uci-engines>
=over

=item * L<#commandline-options>

=item * L<#option-syzygypath>

=item * L<#options-syzygy7timecushion-and-syzygy3timecushion>

=item * L<#option-move-overhead>

=back

=back

=item * L<#internals>

=item * L<#copryight>

=back

=back

=head2 Installation

=head3 Windows

If you are just interested in running the integrated UCI compatible
chess engine, go to the
LL<https://github.com/gflohr/Chess-Plisco/releases> section,
download the executable image C<plisco.exe> and copy it wherever you
like.

If you want to do more with the software, you have to install at least a
Perl interpreter for Windows (LL<https://strawberryperl.com/> will usually be the first choice). If
you want to hack on the sources, you have to set up a development
environment that is close enough to a Un*x system. Just read on in this
case.

=head3 POSIX Systems (Un*x, Linux, macos, ...)

=head4 Installing a Release

You will need the program C<cpanm>. Try the command C<cpanm --version>. If
that does not print an error message but dumps some settings of your
Perl environment, you are all done. Otherwise, see
L<https://metacpan.org/pod/App::cpanminus> for help on installing the
program.

Note: The program C<cpanm> builds and installs Perl packages. By default,
it runs the test suites that ship with the packages. That can be time
consuming, and sometimes tests fail, that are not really relevant.
Therefore, you can always add the option C<--notest> to bypass this step
if you need that.

Once you have C<cpanm> working, installing the latest release of the
library and the engine is as easy as this:

 cpanm Chess::Plisco

You can now use the library (if you are a Perl hacker), or run the
engine with the command C<plisco>. The program C<plisco> should normally
be in your C<$PATH>.

=head3 Building/Using from Git Sources

Clone the repository first.

The usual plethora of building and maybe installing Perl modules goes
like this:

 perl Makefile.PL
 make
 make install # optional

Chances are that this will trigger warnings and errors.

 Checking if your kit is complete...
 Warning: the following files are missing in your kit:
         META.json
         META.yml
         README.pod
         t/release-cpan-changes.t
 Please inform the author.

That is normal in this case, and it is harmless. This one is not:

 Warning: prerequisite Some::Other::Module VERSION not found.

That means that you are missing a dependency.

=head4 Installing from Git Sources

If you want to install the software with all dependencies, you can
simply use this:

 cpanm .

=head4 Using the Cloned Repository Directly

If you really want to use the sources from C<git> directly, you will
still need the dependencies. You can install them like this:

 cpanm --installdeps .

You can now start the engine like this:

 perl -Ilib ./bin/plisco

You will notice it takes several seconds for the engine to start up. See
the section L<#Internals> below if you want to know why.

=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:

=over

=item * L<lib/Chess/Plisco.pod> (C<perldoc Chess::Plisco>)

=item * L<lib/Chess/Plisco/Macro.pod>
(C<perldoc Chess::Plisco::Macro>).

=item * L<lib/Chess/Plisco/EPD.pod>
(C<perldoc Chess::Plisco::EPD>)

=item * L<lib/Chess/Plisco/EPD/Record.pod>
(C<perldoc Chess::Plisco::EPD::Record>)

=item * L<lib/Chess/Plisco/Tablebase/Syzygy.pod>
(C<perldoc Chess::Plisco::Tablebase::Syzygy>).

=back

=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

The engine needs some time to come up because it compiles a number of
lookup tables. If you run it from a git checkout, it will also need time
to parse its own source code and expand the macros contained.

See the section L<#Internals> below, for details about this.

=head3 Graphical User Interfaces

Like almost all chess engines, plisco does not come with a graphical
user interface. Try using one of these:

=over

=item * LLL<https://cutechess.com/> (Linux, MacOS, and Windows)

=item * LLL<https://banksiagui.com/> (Linux, MacOS, and Windows)

=item * LLL<http://www.playwitharena.de/> (Linux, Windows)

=back

=head3 Syzygy Endgame Tablebases

When you want to use Syzygy Endgame Tablebases, make sure that they are
stored on a fast SSD disk. Conventional spinning disks are way too
small.

The DTZ files are optional but improve performance. They can be stored
on a slower storage medium. However, try to make sure that the disk does
not go to sleep while playing. Waking the disk up can take several
seconds and that can cause the engine to lose on time.

=head3 Differences to Other UCI Engines

=head4 Commandline Options

The program understands several commandline options. Try C<plisco --help>
for details.

=head4 Option C<SyzygyPath>

Unlike other engines do, directories are searched recursively for
tablebase files.

=head4 Options C<Syzygy7TimeCushion> and C<Syzygy3TimeCushion>

Probing the table bases in Perl is a lot slower than in C or similar
languages because the records have to be decompressed.

The engine will therefore not sort root moves if it is likely to be
flagged because of the tablebase probes. But the performance largely
depends on the speed of your storage media.

These two non-standard options control whether the engine will try to
order the root moves with tablebase probes. The default values for T7
(C<Syzygy7TimeCushion>) is 5000 (milliseconds) and the default value for
T3 (C<Syzygy3TimeCushion>) is 500 (milliseconds). If there are 7 pieces
on the board, and the maximum allocated time for the move is less than
T7, no tablebase will be probed. For fewer pieces, the formula is as
follows:

 min_time_left = max(T3, T7 / 5^(7 - n))

Where n is the number of pieces on the board.

If you see that the engine often loses on time, escpecially, with few
pieces on the board, increase the values accordingly.

=head4 Option C<Move Overhead>

You can use the option name C<Move Overhead> or C<MoveOverhead>, whatever
you prefer.

The default value for the move overhead is displayed as 10 ms. But this
is only the initial value, and in reality, the move overhead is
determined dynamically accurately measured. That has the advantage that
the engine automatically detects network lags or other performance
penalties.

The downside of this is that the engine output is not deterministic,
which can be a problem for debugging. You can avoid that by specifying
the move overhead explicitely:

 setoption name Move Overhead value 10

=head2 Internals

Functions and methods (subroutines) are the most fundamental way of
avoiding copy and paste - also known as Don't Repeat Yourself DRY (the
mother of all evil)- in source code, but it often comes at a cost, which
is called call overhead.

Often times, the code runs faster if you copy the same snippets over and
over again to the needed locations instead of invoking a subroutine with
arguments. This is called inlining. But it leads, of course, to really
ugly code, which is a nightmare to maintain.

But there are ways to achieve the same results in a more readable form.
The most prominent examples are the commands C<m4> and the infamous C
preprocessor C<cc -E> (or the equivalent C<cpp>). Both are preprocessors
that basically do a pretty smart search and replace on your source code.
Many purists hate these tools but they are key, when you have to improve
performance.

C++ tried to calm down the haters with the C<inline> keyword. It is
pretty much a politically correct C preprocessor without its quirks.
That turned out to be quite useful, and eventually, the C<inline> keyword
found its way back into C++'s mother language C.

Another such trick is generic programming. Search the internet if you
are interested.

Perl actually allowed you to automatically preprocess your code with the
C preprocessor, but the corresponding option C<-P> was dropped with Perl
5.18 because it had many practical issues. But you can, of course, use
it in your own setup. The same goes for C<m4>. Both options did not
really work well with C<Chess-Plisco>.

The solution was another Perl gimmick, so-called source code filters.
These filters are regular Perl modules that receive some source code as
input and are expected to produce output that can be processed by the
Perl interpreter. They are run before the Perl interpreter itself parses
the code, and this is what C<Chess-Plisco> is using for inlining.

What happens, if you run the embedded engine from a cloned source code
repository?

 perl -Ilib ./bin/plisco

That works. But it invokes the source code filter on-the-fly. The source
code filter parses the code with the notoriously slow module
LL<https://metacpan.org/pod/PPI> and replaces "macros" (see
LL<https://metacpan.org/dist/Chess-Plisco/view/lib/Chess/Plisco/Macro.pod>)
with the code that is actually executed. Inlining.

In order to speed up the installed module, there is a script
C<expand-macros> in the top-level directory that runs a whole directory
of Perl source files through that source filter and expands them in
place. This is one step in the build workflow. Therefore, the published
releases of C<Chess-Plisco> do not have this start-up penalty and compile
relatively fast. There is still a noticeable delay that comes from
pre-computing relatively large lookup tables.

Releases of C<Chess-Plisco> are created with the help of
LL<https://dzil.org/>, which makes the integration of the
source code filter really easy. It is probably feasible to integrate the
filter on a lower level after C<perl Makefile.PL && make>, so that you
will find expanded sources inside C<blib/lib>, but so far, there was no
demand for it. For the time being, you have to know that the library
created after the conventional Perl build plethor
C<perl Makefile.PL && make> will produce a module with a massive start-up
overhead.

=head2 Copryight

Copyright (C) 2021-2026, Guido Flohr, L<mailto:guido.flohr@cantanea.com>, all
rights reserved.
